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)
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
____________________
Racket Users list:
http://lists.racket-lang.org/users
(define (mk-fib)
(let ([n0 -1] [n1 1])
(lambda ()
(let ([next (+ n0 n1)])
(set! n0 n1)
(set! n1 next))
n1)))
- Erik
I realize that I forgot to add explanation.
This line creates a "sequence" by repeatedly calling your fib
function. in-producer will continue to call fib until it sees the
second argument. But since the fibonacci numbers don't end, I want to
tell in-producer to go on forever, so I passed it something that fib
won't ever produce.
... and It's from a song by the music group No Doubt. Why? Dunno.
Valentine's Day brought it to mind for some reason. :)
The second part:
;; Let's wrap it and turn it into a stream that remembers...
(sequence->stream fib-sequence)
turns the sequence into another sequence. But this one will remember
its previous values as we walk across it.
So when we do start walking the streamified sequence, we can do that
repeatedly without losing the old values.
A stream is a sequence, and also has a few more functions that act
very much like the familiar list-oriented functions.
http://docs.racket-lang.org/reference/streams.html#(tech._stream)
So you could use stream-first and stream-rest on the fib-stream, as if
you had entire fibonacci sequence in front of you as an infinite list.
Just don't try to stream->list it.
Another option is you could turn change your fib function to be 'mk-fib' that returns a new instance of the fib function each time it's called:
(define (mk-fib)
(let ([n0 -1] [n1 1])
(lambda ()
(let ([next (+ n0 n1)])
(set! n0 n1)
(set! n1 next))
n1)))
Instead of calling fib-less-than-n recursively, you could add a loop inside, for example something like,(define (fib-less-than-n n)(define fib (mk-fib))(let loop ([vs '()])(let ([fib-val (fib)])(if (>= fib-val n)(reverse vs)(loop (cons fib-val vs))))))
This function works, but is not "recallable" (is there a better word?). In other words I cannot do the following:(define f1 fib)(define f2 fib)(f1) (f1) (f2) ...and have f1 and f2 be separate fibonacci lists.
Are you sure you mean to use fib-less-than-n here?
Some of the documentation is meant to be reference, but other docs are
approachable as tutorials. The ones listed here:
http://docs.racket-lang.org/getting-started/index.html
use extended examples that should be straightforward. I'd go at the
"Quick", "More", and "Continue" tutorials there.
I have some ideas for more documented guides through Racket... but I
have to graduate or get kicked out first. :) I've written a guide
about one way to apply the language extension features in Racket:
(http://hashcollision.org/brainfudge/index.html)
I think there's supposed to be something about "Realm of Racket"
(http://realmofracket.com/), but they've been very hush-hush.
Or in lazy racket, where that example becomes very clear:
#lang lazy
(define fibs (list* 1 1 (map + fibs (cdr fibs))))
--
((lambda (x) (x x)) (lambda (x) (x x))) Eli Barzilay:
http://barzilay.org/ Maze is Life!