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 [:instreams] 2
;(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 :fun] tail ,[: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 0 [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 0 == 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