scheme - Building accumulator for lazy lists in Racket -
i defined simple lazy list of integers zero:
(define integers-from (lambda (n) (cons n (lambda () (integers-from (+ 1 n)))))) (define lz (integers-from 0))
i coded accumaltor gets lazy list parameter
(define lz-lst-accumulate (lambda (op initial lz) (if (null? lz) initial (cons (op (head lz) initial) (lambda () (lz-lst-accumulate op (op initial (head lz)) (tail lz)))))))
does accumaltor answer format of lazy lists? here simple test of accumulator:
(define acc (lz-lst-accumulate * 1 lz)) (take acc 4) => '(1 2 6 24)
take
helper function creates list first n
elements of lazy list:
(define head car) (define tail (lambda (lz-lst) ((cdr lz-lst)) )) (define take (lambda (lz-lst n) (if (= n 0) (list) (cons (car lz-lst) (take (tail lz-lst) (sub1 n)))) ))
in lz-lst-accumulate
calculate once (op (head lz) initial)
, (op initial (head lz))
. inconsistent; both should same , calculated once, since it's same value:
(define lz-lst-accumulate (lambda (op initial lz) (if (lz-lst-empty? lz) initial (let ((val (op (head lz) initial))) (cons val (lambda () (lz-lst-accumulate op val (tail lz))))))))
it works in example numbers because use type-symmetrical operation *
. cons
wouldn't work.
other it's ok. lz-lst-accumulate
known left fold (scanl
in haskell, actually, since produce progression of "accumulated" values, foldl f z xs = last (scanl f z xs)
).
re: version of take
, forcing 1 many elements of stream. better make it
(define take (lambda (lz n) (if (or (<= n 0) (lz-lst-empty? lz)) (list) (if (= n 1) (list (car lz)) ; forced (cons (car lz) (take (tail lz) (sub1 n)))))))
so forces many elements has produce, , not 1 more (which might e.g. divergent, (/ 1 0)
, invalidating whole calculation no reason).
that way, counter-example in srfi 41 (of (take 4 (stream-map 1/ (ints-from-by 4 -1)))
) will work (it calculates (1/4 1/3 1/2 1/1)
without forcing 1/0
, usual version of take
, 1 you're using, do).
Comments
Post a Comment