Gauche:streamとgenerator
yamasushi(2013/03/22 10:19:06 UTC)streamをgeneratorのようなインターフェースで使えるように試行しています。
- yamasushi(2013/05/06 22:10:02 UTC) stream <---> generator相互変換を追加しました。これでgeneratorのような手続きをstreamに用意する動機がなくなってしまいました。
コード
; 小物モジュール(stream) ; streamにgeneratorのような操作を実装 (define-module komono-stream (extend util.stream) (use gauche.generator) (use gauche.lazy) (export ;stream stream-generate stream-iota stream-unfold x->stream generator->stream stream->generator stream->lseq iterator->generator ) ) (select-module komono-stream) ; generator->stream (define (generator->stream g) (let1 r (glet1 v (g) (stream-cons v (generator->stream g) ) ) (if (eq? r (eof-object)) stream-null r ) ) ) ; stream->generator (define (stream->generator s) (if (stream? s) (^[] (if (stream-null? s) (eof-object) (begin0 (stream-car s) (set! s (stream-cdr s) ) ) ) ) (errorf "~a is not stream" s) ) ) ; stream->lseq (define stream->lseq ($ generator->lseq $ stream->generator $) ) ;stream-iota ; shadow original (define (stream-iota :optional (count +inf.0) (start 0) (step 1)) ((with-module util.stream stream-iota) (if (infinite? count) -1 count) start step ) ) ; generatorのような生成 (define (stream-generate proc) (iterator->stream (^[yield end] (proc (^x (if (eq? x (eof-object) ) (end) (yield x) ) ) ) (end) ) ) ) ;iterator->generator : streamのようにgeneratorを生成 ; TODO #| Scheme/継続の種類と利用例 - Wikibooks http://ja.wikibooks.org/wiki/Scheme/%E7%B6%99%E7%B6%9A%E3%81%AE%E7%A8%AE%E9%A1%9E%E3%81%A8%E5%88%A9%E7%94%A8%E4%BE%8B Scheme:generatorとdoとwhile http://practical-scheme.net/wiliki/wiliki.cgi?Scheme%3agenerator%e3%81%a8do%e3%81%a8while#H-17qe7ru |# (define (iterator->generator proc) (define next #f) (define return #f) (^[] (let/cc break ;; break = generatorがcallされた後に相当する継続 (set! return break) ;; 環境を書き換え (if (not next) (begin (proc (^x (let/cc cc (set! next cc) (return x) ) ) (^[] (set! next null-generator) (return (eof-object) ) ) ) (set! next null-generator) (return (eof-object)) ) (next) ) ;; yieldの後に待ち構えている継続をcall ))) ;unfold ;TODO tailgen未対応 (define (stream-unfold p f g seed) (stream-unfoldn (^s (if (p s) (values #f '()) (values (g s) `(,(f s) )))) seed 1) ) ;; generic version (define-method x->stream ((obj <list>)) (list->stream obj)) (define-method x->stream ((obj <string>)) (string->stream obj)) (define-method x->stream ((obj <vector>)) ($ generator->stream $ vector->generator obj)) (define-method x->stream ((obj <integer>)) ($ generator->stream $ bits->generator obj)) (define-method x->stream ((obj <collection>)) (iterator->stream (^ (s-next s-end) (call-with-iterator obj (^[end? next] (let loop () (unless (end?) (s-next (next)) (loop)) (s-end) ) ) ) ) ) )
iterator->generatorについて
Scheme:generatorとdoとwhileのgeneratorのコードを書き換えてみました。
やってみよう
こうかな。cut-sea:2006/08/09 17:17:02 PDT
(define (make-generator proc) (define next #f) (define return #f) (lambda () (call/cc ;; break = generatorがcallされた後に相当する継続 (lambda (break) (set! return break) ;; 環境を書き換え (if (not next) (proc ;; yield (lambda arg ;; cc = yieldがcallされた後に相当する継続 (call/cc (lambda (cc) (set! next cc) ;; 環境を書き換え (apply return arg))))) ;; breakの後に待ち構えている継続をcall (next)))))) ;; yieldの後に待ち構えている継続をcall
コメント
関連
Tags: util.stream,
Post a comment