[racket] Making a Racket function "recallable"

From: Erik Silkensen (eriksilkensen at gmail.com)
Date: Tue Feb 14 03:40:45 EST 2012

Sure, sounds good.

The (let loop ([vs '()]) ...) is a 'named let' (http://docs.racket-lang.org/guide/let.html?q=named%20let#(part._.Named_let)) which as the guide says is equivalent to (letrec ([loop (lambda (vs) ...)]) (loop '()) --- so 'loop' is a recursive function that we're using to iterate until (fib) is >= n, accumulating the values in the vs argument.  If you're not familiar with letrec, another definition would be

(define (fib-less-than-n n)
  (define fib (mk-fib))
  (define (loop vs)
    (let ([fib-val (fib)])
      (if (>= fib-val n)
          (reverse vs)
          (loop (cons fib-val vs)))))
  (loop '()))



Thinking of loops as just a form of recursion can be a little strange at first.  There's more information in the Racket guide here- http://docs.racket-lang.org/guide/Lists__Iteration__and_Recursion.html or another page to check out might be http://mitpress.mit.edu/sicp/full-text/sicp/book/node15.html. 

Hope this helps,

- Erik


On Feb 14, 2012, at 1:00 AM, Joe Gilray wrote:

> Thanks Erik.  Very nice!  Although I miss the recursion.
> 
> please help me understand how this works, especially (let loop ([vs '()]). What exactly is going on there?
> 
> Thanks again,
> -joe
> 
> On Mon, Feb 13, 2012 at 9:51 PM, Erik Silkensen <eriksilkensen at gmail.com> wrote:
> 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))))))
> 
> - Erik
> 
> On Feb 13, 2012, at 10:41 PM, Joe Gilray wrote:
> 
>> Erik,
>> 
>> Intriguing idea and it works "flat", but if I write the following I end up with an infinite loop:
>> 
>> (define (fib-less-than-n n)
>>   (let ([f1 (mk-fib)])
>>     (let ([fib-val (f1)])
>>       (if (>= fib-val n) '() (cons fib-val (fib-less-than-n n))))))
>> 
>> How would I use your idea in this case?
>> 
>> thanks!
>> -joe
>> 
>> On Mon, Feb 13, 2012 at 9:18 PM, Erik Silkensen <eriksilkensen at gmail.com> wrote:
>> 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)))
>> 
>> - Erik
>> 
>> On Feb 13, 2012, at 10:10 PM, Danny Yoo wrote:
>> 
>> > 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)
>> > ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
>> >
>> > ____________________
>> >  Racket Users list:
>> >  http://lists.racket-lang.org/users
>> 
>> 
> 
> 

-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.racket-lang.org/users/archive/attachments/20120214/f659e407/attachment-0001.html>

Posted on the users mailing list.