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