Gauche:streamとgenerator

Gauche:streamとgenerator

yamasushi(2013/03/22 10:19:06 UTC)streamをgeneratorのようなインターフェースで使えるように試行しています。



コード

; 小物モジュール(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

コメント

Post a comment

Name:


関連


Tags: util.stream,


Last modified : 2013/05/07 09:27:01 UTC