aUCBLogo Demos and Tests / streams


; Implementation of SICP streams (lazy-evaluation lists) in Logo.

; Since we don't have special forms, we put the second argument to STREAM
; in a (quoted) list.

; Since we don't have lexical scope, we use substitution (`) into saved
; expressions.

to stream :car :delayed_cdr
output fput :car (list "*delayed* :delayed_cdr)
end

to head :astream
output first :astream
end

to tail :astream
if emptyp bf :astream [output []]
if not equalp first bf :astream "*delayed* [output bf :astream]
localmake "result run last :astream
_setbf :astream :result
output :result
end

; higher order functions for streams

; Remember that if the functional argument uses local variables, it has to
; be backquoted.

to stream_map :fun [:instreams2
;(show "fun= fun "instreams= instreams)
if emptyp first :instreams [output []]
output stream apply :fun firsts :instreams ~
           `
[(apply "stream_map fput ,[quoted :fun] (map "tail ,[:instreams]))]
end

to stream_filter :fun :astream
   
if emptyp :astream [output []]
   
if invoke :fun head :astream ~
   
[   output stream head :astream 
         `
[stream_filter ,[quoted :funtail ,[:astream]]
   
]
   
output stream_filter :fun tail :astream
end

to flatten :stream_of_streams
if emptyp :stream_of_streams [output []]
output flatten1 head :stream_of_streams :stream_of_streams
end

to flatten1 :astream :delayed_more_streams
if emptyp :astream [output flatten tail :delayed_more_streams]
output stream (head :astream) ~
              `
[flatten1 tail ,[:astream]
                         ,[
:delayed_more_streams]]
end

; helper for debugging

to show_stream :astream [:num 10]
show show_stream1 :astream :num
end

to show_stream1 :astream :num
if emptyp :astream [output []]
if equalp :num [output [...]]
output fput head :astream (show_stream1 tail :astream :num-1)
end

; examples

to integers_from :n
output stream :n `[integers_from ,[:n+1]]
end

to sieve :astream
output stream (head :astream) ~
              `
[sieve stream_filter [not divisiblep ? ,[head :astream]]
                                    
tail ,[:astream]]
end

to divisiblep :big :small
output == remainder :big :small
end

to stream_iseq :from :to_
   
if :from :to_ [output []]
   
output stream :from `[stream_iseq ,[:from+1] ,:to_]
end

to streams
   
make "integers integers_from 1
   
make "primes sieve tail :integers
end