[racket] Making a Racket function "recallable"

From: Danny Yoo (dyoo at cs.wpi.edu)
Date: Tue Feb 14 00:10:14 EST 2012

On Mon, Feb 13, 2012 at 11:52 PM, Joe Gilray <jgilray at gmail.com> wrote:
> Warning: extreme newbie question ahead.
>
> I wrote the following fibonacci function:
>
> ; function that returns the next fibonacci number each time it is called
> ; invoke as (fib)
> (define fib
>   (let ([n0 -1] [n1 1])
>     (lambda ()
>       (let ([next (+ n0 n1)])
>         (set! n0 n1)
>         (set! n1 next))
>       n1)))


One thing you can do is turn fib into a "sequence", and then from a
sequence into a stream that knows how to remember its previous values.

Here's what it might look like:

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
#lang racket
(require racket/sequence)

(define fib
  (let ([n0 -1] [n1 1])
    (lambda ()
      (let ([next (+ n0 n1)])
        (set! n0 n1)
        (set! n1 next))
      n1)))

(define fib-stream
  ;; Here's a sequence of the function:
  (let ([fib-sequence (in-producer fib 'donttellmecauseithurts)])

    ;; Let's wrap it and turn it into a stream that remembers...
    (sequence->stream fib-sequence)))


;; Ok, we've got a stream.  Let's look at its first few elements.
(define (peek-fibs n)
  (for ([elt fib-stream]
        [i (in-range n)])
    (displayln elt)))

(peek-fibs 10)
(printf "-----\n")
(peek-fibs 20)
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;


Posted on the users mailing list.