These two examples do the factorial of a number:
(define (factorial n)
(define (execute n result)
(cond
[(> 2 n) result]
[else (execute (- n 1) (* result n))]))
(execute n 1))
And
(define (factorial n)
(let loop ((curr n)
(result 1))
(cond
[(> 2 curr) result]
[else (loop (- curr 1) (* result curr))])))
The difference reside in using the named-let. Are they both pure and tail recursive functions?
Yes, they are tail-recursive, and they're essentially equivalent.
A named let is just a shorthand for a function definition along with a first call using the initial values as the arguments.
A function is tail-recursive if all its calls to itself are in tail positions, i.e. it simply returns the value of that call. In the first function, the recursive call to execute is in the tail position; in the second function the same is true of the call to loop.
Related
The following code is used to implement a built-in function called "build-list":
(define (my-build-list-book n f)
(define (builder k)
(cond [(= n k) empty]
[else (cons (f k) (builder (add1 k)))]))
(builder 0))
(my-build-list-book 10 add1)
>> '(1 2 3 4 5 6 7 8 9 10)
Is this a recursive definition of an iterative procedure or a recursive definition of a recursive procedure?
builder is recursive because it calls itself: (builder (add1 k))
It's not tail recursive because the call to itself is not done in the place where a value is returned from the original procedure. It uses the result of the recursive call as an argument to cons rather than as the return value.
A tail-recursive variant would end with something like:
[else (builder ...)]
Converting a function like this to tail-recursion generally requires adding an additional argument that contains the accumulated result, which is returned by the base case.
(define (my-build-list-book n f)
(define (builder k result)
(cond [(= n k) result]
[else (builder (add1 k) (cons (f k) result))]))
(builder 0 '()))
I'm not sure what you mean by "long tail recursion", I've never heard that phrase and I can't find it with Google.
In an answer which explains how to convert a number to a list the number->list procedure is defined as follows:
(define (number->list n)
(let loop ((n n)
(acc '()))
(if (< n 10)
(cons n acc)
(loop (quotient n 10)
(cons (remainder n 10) acc)))))
Here a "named let" is used. I don't understand how this named let works.
I see that a loop is defined where the variable n is equal to n, and the variable acc equal to the empty list. Then if n is smaller than 10 the n is consed to the acc. Otherwise, "the loop" is applied with n equal to n/10 and acc equal to the cons of the remainder of n/10 and the previous accumulated stuff, and then calls itself.
I don't understand why loop is called loop (what is looping?), how it can automatically execute and call itself, and how it will actually add each number multiplied by its appropriate multiplier to form a number in base 10.
I hope someone can shine his or her light on the procedure and the above questions so I can better understand it. Thanks.
The basic idea behind a named let is that it allows you to create an internal function, that can call itself, and invoke it automatically. So your code is equivalent to:
(define (number->list n)
(define (loop n acc)
(if (< n 10)
(cons n acc)
(loop (quotient n 10)
(cons (remainder n 10) acc))))
(loop n '()))
Hopefully, that is easier for you to read and understand.
You might, then, ask why people tend to use a named let rather than defining an internal function and invoking it. It's the same rationale people have for using (unnamed) let: it turns a two-step process (define a function and invoke it) into one single, convenient form.
It's called a loop because the function calls itself in tail position. This is known as tail recursion. With tail recursion, the recursive call returns directly to your caller, so there's no need to keep the current call frame around. You can do tail recursion as many times as you like without causing a stack overflow. In that way, it works exactly like a loop.
If you'd like more information about named let and how it works, I wrote a blog post about it. (You don't need to read it to understand this answer, though. It's just there if you're curious.)
A normal let usage can be considered an anonymous procedure call:
(let ((a 10) (b 20))
(+ a b))
;; is the same as
((lambda (a b)
(+ a b))
10
20)
A named let just binds that procedure to a name in the scope of the procedure so that it is equal to a single procedure letrec:
(let my-chosen-name ((n 10) (acc '()))
(if (zero? n)
acc
(my-chosen-name (- n 1) (cons n acc)))) ; ==> (1 2 3 4 5 6 7 8 9 10)
;; Is the same as:
((letrec ((my-chosen-name
(lambda (n acc)
(if (zero? n)
acc
(my-chosen-name (- n 1) (cons n acc))))))
my-chosen-name)
10
'()) ; ==> (1 2 3 4 5 6 7 8 9 10)
Notice that the body of the letrec just evaluates to the named procedure so that the name isn't in the environment of the first call. Thus you could do this:
(let ((loop 10))
(let loop ((n loop))
(if (zero? n)
'()
(cons n (loop (- n 1))))) ; ==> (10 9 8 7 6 5 4 3 2 1)
the procedure loop is only in the environment of the body of the inner let and does not shadow the variable loop of the outer let.
In your example, the name loop is just a name. In Scheme every loop is ultimately done with recursion, but usually the name is used when it's tail recursion and thus an iterative process.
Does scheme have a function to call a function n times. I don't want map/for-each as the function doesn't have any arguments. Something along the lines of this :-
(define (call-n-times proc n)
(if (= 0 n)
'()
(cons (proc) (call-n-times proc (- n 1)))))
(call-n-times read 10)
SRFI 1 has a list-tabulate function that can build a list from calling a given function, with arguments 0 through (- n 1). However, it does not guarantee the order of execution (in fact, many implementations start from (- n 1) and go down), so it's not ideal for calling read with.
In Racket, you can do this:
(for/list ((i 10))
(read))
to call read 10 times and collect the result of each; and it would be done left-to-right. But since you tagged your question for Guile, we need to do something different.
Luckily, Guile has SRFI 42, which enables you to do:
(list-ec (: i 10)
(read))
Implementing tail-recursion modulo cons optimization by hand, to build the resulting list with O(1) extra space:
(define (iterate0-n proc n) ; iterate a 0-arguments procedure n times
(let ((res (list 1))) ; return a list of results in order
(let loop ((i n) (p res))
(if (< i 1)
(cdr res)
(begin
(set-cdr! p (list (proc)))
(loop (- i 1) (cdr p)))))))
This technique first (?) described in Friedman and Wise's TR19.
I basically need to do a iterative version of the following function which i've already made:
(define (expo base e)
(cond ((or (= base 1) (= e 0)) 1)
(else (* base (expo base (- e 1))))))
im not sure how to so i need help(in racket/scheme))
The general pattern with converting such recursive functions to iteration is to use an accumulator
(define (expo base e)
(define (go base e accum)
(if (or (= base 1) (= e 0))
accum
(go base (- e 1) (* accum base)))) ; Now this is tail recursion
???)
Where ??? calls go with the appropriate initial value of accum. Notice how before the recusive call was inside another call (namely *) but now it's the last thing called. This allows for the program to run in constant space.
All you have to do is pass the result around in an accumulator. For that you need an extra parameter, there are several ways to do it, for example using an inner helper procedure:
(define (expo base e)
; helper procedure
(define (iter e acc)
; now the base case returns the accumulator
(cond ((or (= base 1) (= e 0)) acc)
; see how the result is accumulated in the parameter
(else (iter (- e 1) (* base acc)))))
; at the beginning, initialize the parameter in the right values
(iter e 1))
Alternatively, we can use a named let for the same effect:
(define (expo base e)
(let iter ((e e) (acc 1))
(cond ((or (= base 1) (= e 0)) acc)
(else (iter (- e 1) (* base acc))))))
It's good to differentiate between recursive procedures and processes. Both of the above implementations are recursive procedures: syntactically, it's easy to see that they call themselves. But the processes they generate are iterative: they're written in a tail recursive style, so after each recursive call ends there's nothing left to do, and the compiler can optimize away the recursive call and, for all practical purposes, transform it into an iterative loop.
To better understand how iteration works in Scheme read more about this subject in the fantastic SICP book, in the section Procedures and the Processes They Generate
As others have noted, a tail recursive algorithm is an iterative algorithm. However, perhaps you need an explicit iterative algorithm?
(define (expo base exp)
(do ((acc 1 (* acc base))
(exp exp (- exp 1)))
((= 0 exp) acc))))
One could add a condition for (= base 1) - but, as written, this is a simple as it gets. Assumes exp is an integer.
The following example involves jumping into continuation and exiting out. Can somebody explain the flow of the function. I am moving in a circle around continuation, and do not know the entry and exit points of the function.
(define (prod-iterator lst)
(letrec ((return-result empty)
(resume-visit (lambda (dummy) (process-list lst 1)))
(process-list
(lambda (lst p)
(if (empty? lst)
(begin
(set! resume-visit (lambda (dummy) 0))
(return-result p))
(if (= 0 (first lst))
(begin
(call/cc ; Want to continue here after delivering result
(lambda (k)
(set! resume-visit k)
(return-result p)))
(process-list (rest lst) 1))
(process-list (rest lst) (* p (first lst))))))))
(lambda ()
(call/cc
(lambda (k)
(set! return-result k)
(resume-visit 'dummy))))))
(define iter (prod-iterator '(1 2 3 0 4 5 6 0 7 0 0 8 9)))
(iter) ; 6
(iter) ; 120
(iter) ; 7
(iter) ; 1
(iter) ; 72
(iter) ; 0
(iter) ; 0
Thanks.
The procedure iterates over a list, multiplying non-zero members and returning a result each time a zero is found. Resume-visit stores the continuation for processing the rest of the list, and return-result has the continuation of the call-site of the iterator. In the beginning, resume-visit is defined to process the entire list. Each time a zero is found, a continuation is captured, which when invoked executes (process-list (rest lst) 1) for whatever value lst had at the time. When the list is exhausted, resume-visit is set to a dummy procedure. Moreover, every time the program calls iter, it executes the following:
(call/cc
(lambda (k)
(set! return-result k)
(resume-visit 'dummy)))
That is, it captures the continuation of the caller, invoking it returns a value to the caller. The continuation is stored and the program jumps to process the rest of the list.
When the procedure calls resume-visit, the loop is entered, when return-result is called, the loop is exited.
If we want to examine process-list in more detail, let's assume the list is non-empty. Tho procedure employs basic recursion, accumulating a result until a zero is found. At that point, p is the accumulated value and lst is the list containing the zero. When we have a construction like (begin (call/cc (lambda (k) first)) rest), we first execute first expressions with k bound to a continuation. It is a procedure that when invoked, executes rest expressions. In this case, that continuation is stored and another continuation is invoked, which returns the accumulated result p to the caller of iter. That continuation will be invoked the next time iter is called, then the loop continues with the rest of the list. That is the point with the continuations, everything else is basic recursion.
What you need to keep in mind is that, a call to (call/cc f) will apply the function f passed as argument to call/cc to the current continuation. If that continuation is called with some argument a inside the function f, the execution will go to the corresponding call to call/cc, and the argument a will be returned as the return value of that call/cc.
Your program stores the continuation of "calling call/cc in iter" in the variable return-result, and begins processing the list. It multiplies the first 3 non-zero elements of the list before encountering the first 0. When it sees the 0, the continuation "processing the list element 0" is stored in resume-visit, and the value p is returned to the continuation return-result by calling (return-result p). This call will make the execution go back to the call/cc in iter, and that call/cc returns the passed value of p. So you see the first output 6.
The rest calls to iter are similar and will make the execution go back and forth between such two continuations. Manual analysis may be a little brain-twisting, you have to know what the execution context is when a continuation is restored.
You could achieve the same this way:
(define (prod-iter lst) (fold * 1 (remove zero? lst)))
... even though it could perform better by traversing only once.
For continuations, recall (pun intended) that all call/cc does is wait for "k" to be applied this way:
(call/cc (lambda (k) (k 'return-value)))
=> return-value
The trick here is that you can let call/cc return its own continuation so that it can be applied elsewhere after call/cc has returned like this:
;; returns twice; once to get bound to k, the other to return blah
(let ([k (call/cc (lambda (k) k))]) ;; k gets bound to a continuation
(k 'blah)) ;; k returns here
=> blah
This lets a continuation return more than once by saving it in a variable. Continuations simply return the value they are applied to.
Closures are functions that carry their environment variables along with them before arguments get bounded to them. They are ordinary lambdas.
Continuation-passing style is a way to pass closures as arguments to be applied later. We say that these closure arguments are continuations. Here's half of the current code from my sudoku generator/solver as an example demonstrating how continuation-passing style can simplify your algorithms:
#| the grid is internally represented as a vector of 81 numbers
example: (make-vector 81 0)
this builds a list of indexes |#
(define (cell n) (list (+ (* (car 9) (cadr n))))
(define (row n) (iota 9 (* n 9)))
(define (column n) (iota 9 n 9))
(define (region n)
(let* ([end (+ (* (floor-quotient n 3) 27)
(* (remainder n 3) 3))]
[i (+ end 21)])
(do ([i i
(- i (if (zero? (remainder i 3)) 7 1))]
[ls '() (cons (vector-ref *grid* i) ls)])
((= i end) ls))))
#| f is the continuation
usage examples:
(grid-ref *grid* row 0)
(grid-set! *grid* region 7) |#
(define (grid-ref g f n)
(map (lambda (i) (vector-ref g i)) (f n)))
(define (grid-set! g f n ls)
(for-each (lambda (i x) (vector-set! g i x))
(f n) ls))