I have written a code which uses lazy evaluation to produce infinite data structure but there is an error.
Here is the code:
#!/usr/bin/guile \
-e main -s
!#
(define ints-f
(lambda (n)
(let ((n1 (delay (ints-f (+ n 1)))))
(cons n (force n1)))))
(define (main args)
(display (car (ints-f 3) ))
(newline)
)
This gives an error which says stack overflow. Which means that force is being executed even if not called. How to rectify this?
#!/usr/bin/guile \
-e main -s
!#
(define ints-f
(lambda (n)
(let ((n1 (delay (ints-f (+ n 1)))))
(cons n n1))))
(define (main args)
(display (car (ints-f 3) ))
(newline)
)
The above code is giving the expected output of 3 but if I use cdr as in the code below
#!/usr/bin/guile \
-e main -s
!#
(define ints-f
(lambda (n)
(let ((n1 (delay (ints-f (+ n 1)))))
(cons n n1))))
(define (main args)
(display (cdr (ints-f 3) ))
(newline)
)
It prints a promise object.
How to use lazy evaluation in guile scheme?
The first snippet is incorrect, you're forcing the value when building the sequence, hence defeating the whole purpose of lazy evaluation. On the other hand, the second snippet looks right - although it can be simplified a bit:
(define (ints-f n)
(cons n (delay (ints-f (+ n 1)))))
It's normal to get a promise when calling cdr
, it's a thunk built with delay
that will only yield its value when force
d. In fact, if you want to peek into the elements of an infinite sequence, you'll have to use a procedure for traversing the part you're interested in:
(define (take seq n)
(if (= n 0)
'()
(cons (car seq)
(take (force (cdr seq)) (- n 1)))))
Similarly:
(define (get seq idx)
(if (= idx 0)
(car seq)
(get (force (cdr seq)) (- idx 1))))
For example:
(take (ints-f 5) 5)
=> '(5 6 7 8 9)
(get (ints-f 5) 5)
=> 10