Thanks for asking this question. I was planning on investigating this question myself a while ago but never got around to it. Because of you I decided to spend the time finally. :-)Elica wrote:Now let me go back to newLisp. Does it support streams/sequences? (Not in the sense of I/O streams, but in the sense of infinite lists with delayed evaluation).
Short answer: Yes, but not elegantly like with Scheme. I think this is mainly due to the newLISP's dynamic scope. For example, trying to do memoization does not seem ... possible (actually it is, see several posts down). You might be able to do something with contexts but I think it would turn out ugly...
Long answer: You can get it... I've been playing around with this for several hours now, and here is what I have, I welcome everyone to try and improve upon this:
Code: Select all
(set 'the-empty-stream '())
(define-macro (cons-stream)
(letex (x (args 0) y (args 1))
(cons x (list (delay y)))
)
)
(define-macro (delay)
(letex (x (args 0)) (fn () x))
;(letex (x (args 0)) (memo-proc (fn () x)))
)
(define (memo-proc)
(letex (func (args 0))
(fn ()
(if (not already-run?)
(begin
(set 'result (func))
(set 'already-run true)
)
)
result
)
)
)
(define (head s)
(first s)
)
(define (tail p)
(force (last p))
)
(define (force func)
(func)
)
(define (nth-stream n s)
(if (= n 0)
(head s)
(nth-stream (- n 1) (tail s))
)
)
(define (empty-stream? s)
(empty? s)
)
(define (print-stream s)
(if (empty-stream? s)
"done"
(begin
(print (head s) " ")
(print-stream (tail s))
)
)
)
(define (enum-interval low high)
(if (> low high)
the-empty-stream
(expand (cons-stream low (enum-interval (+ low 1) high)) 'low 'high)
)
)
(define (integers-from n)
(expand (cons-stream n (integers-from (+ n 1))) 'n)
)
(set 'integers (integers-from 1))
(println "nth 20: " (nth-stream 20 integers))
(while true
(print "> ")
(read-line)
(if (= (current-line) "")
(exit)
(println (eval-string (current-line)))
)
)
Code: Select all
> (print-stream integers)
Code: Select all
call stack overflow in function list : delay
called from user defined function integers-from
called from user defined function func
called from user defined function force
called from user defined function tail
called from user defined function print-stream
called from user defined function print-stream
called from user defined function print-stream
...
This is simply because newLISP doesn't have tail-call recursion. You can change the stack size using the -s option when running newlisp. Update: Or, of course, you can just use an iterative version of print-stream:
Code: Select all
(define (print-stream s)
(while (not (empty-stream? s))
(print (head s) " ")
(set 's (tail s))
)
"done"
)
Code: Select all
> (set 'ones (cons-stream 1 ones))
(1 (lambda () ones))
> (print-stream ones)
1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 .... (it goes on.. and then crashes)