I'm studying for a Christmas test and doing some sample exam questions, I've come across this one that has me a bit stumped
I can do regular recursion fine, but I can't wrap my head around how to write the same thing using tail recursion.
Regular version:
(define (factorial X)
(cond
((eqv? X 1) 1)
((number? X)(* X (factorial (- X 1))))))
For a function to be tail recursive, there must be nothing to do after the function returns except return its value. That is, the last thing that happens in the recursive step is the call to the function itself. This is generally achieved by using an accumulator parameter for keeping track of the answer:
(define (factorial x acc)
(if (zero? x)
acc
(factorial (sub1 x) (* x acc))))
The above procedure will be initially called with 1 as accumulator, like this:
(factorial 10 1)
=> 3628800
Notice that the accumulated value gets returned when the base case is reached, and that the acc parameter gets updated at each point in the recursive call. I had to add one extra parameter to the procedure, but this can be avoided by defining an inner procedure or a named let, for example:
(define (factorial x)
(let loop ((x x)
(acc 1))
(if (zero? x)
acc
(loop (sub1 x) (* x acc)))))
Related
I am going through the tutorial at Lisp Tutor Jr, on my own.
After completing an assignment on recursion, I started thinking about expanding the numeric range to negative numbers.
If I bind as in the following code, it gets adjusted together with x.
1) Do I understand correctly that using defconstant inside the function is wrong?
2) How would I bind a minimal variable based on x, in this case attempted via (- x).
(defun list-odd-range(x)
(let ((neg (- x)))
(cond
((< x neg) nil)
((oddp x)(cons x (list-odd (1- x))))
(t (list-odd (1- x))))))
The function as-is returns
(list-odd 5)=>(5 3 1)
I would like to bind neg once, as (- x)
and have the function return a range from positive to negative x:
(list-odd 5)=>(5 3 1 -1 -3 -5)
Binding with an integer, such as the following bit, works:
(let ((neg -5))
What is the correct way to have it defined in relation to x, such as (- x) ?
1) Defconstant doesn't really make sense in a function. It defines a global constant, which is constant. If you ever call the function again, you either provide the same (eql) value and have no effect, or a different value, which is illegal.
2) As you observed, the inner call doesn't know anything about the outer environment except what is passed as an argument. You can either keep it at that and add the remaining part after the return of the inner call (I elide checking the inputs in the following, you'd need to make sure that x is always a nonnegative integer):
(defun odd-range (x)
(cond ((zerop x) ())
((evenp x) (odd-range (1- x)))
(t (cons x
(append (odd-range (1- x))
(list (- x)))))))
Or you can pass the end number along as an additional argument:
(defun odd-range (start end)
(cond ((< start end) ())
((evenp start) (odd-range (1- start) end))
(t (cons start
(odd-range (1- start) end)))))
This would have the benefit of giving the caller free choice of the range as long as end is smaller than start.
You can also pass along the constructed list so far (often called an accumulator, abbreviated acc):
(defun odd-range (start end acc)
(cond ((< start end) (reverse acc))
((evenp start) (odd-range (1- start) end acc))
(t (odd-range (1- start) end (cons start acc)))))
This conses to the front of the list while accumulating and only reverses the result at the end. This avoids walking the accumulated list at every step and is a big improvement on running time. It also moves the recursive call into tail position so that the compiler may produce code that is equivalent to a simple loop, avoiding stack limits. This compiler technique is called tail call elimination or tail call optimization (TCO).
Since Common Lisp compilers are not required to do TCO, it is good style to write loops actually as loops. Examples:
(defun odd-range (start)
(do ((x start (1- x))
(end (- start))
(acc ()
(if (oddp x)
(cons x acc)
acc)))
((<= x end) (reverse acc))))
(defun odd-range (x)
(let* ((start (if (oddp x) x (1- x)))
(end (- start)))
(loop :for i :from start :downto end :by 2
:collect i)))
I'm studying for a Christmas test and doing some sample exam questions, I've come across this one that has me a bit stumped
I can do regular recursion fine, but I can't wrap my head around how to write the same thing using tail recursion.
Regular version:
(define (factorial X)
(cond
((eqv? X 1) 1)
((number? X)(* X (factorial (- X 1))))))
For a function to be tail recursive, there must be nothing to do after the function returns except return its value. That is, the last thing that happens in the recursive step is the call to the function itself. This is generally achieved by using an accumulator parameter for keeping track of the answer:
(define (factorial x acc)
(if (zero? x)
acc
(factorial (sub1 x) (* x acc))))
The above procedure will be initially called with 1 as accumulator, like this:
(factorial 10 1)
=> 3628800
Notice that the accumulated value gets returned when the base case is reached, and that the acc parameter gets updated at each point in the recursive call. I had to add one extra parameter to the procedure, but this can be avoided by defining an inner procedure or a named let, for example:
(define (factorial x)
(let loop ((x x)
(acc 1))
(if (zero? x)
acc
(loop (sub1 x) (* x acc)))))
I was going through Structure and interpretation of computer programming by Brain harvey. I came across this question which i could not figure out how to do it.
How do we write recursive procedure with lambda in Scheme?
TL;DR: Use named let (if you are executing a recursive function immediately) or rec (if you are saving the recursive function for later execution).
The usual way is with letrec, or something that uses a letrec behind the scenes, like named let or rec. Here's a version of (factorial 10) using letrec:
(letrec ((factorial (lambda (x)
(if (< x 1) 1
(* (factorial (- x 1)) x)))))
(factorial 10))
And the same thing using named let:
(let factorial ((x 10))
(if (< x 1) 1
(* (factorial (- x 1)) x)))
The key understanding here is that both versions are exactly the same. A named let is just a macro that expands to the letrec form. So because the named let version is shorter, that is usually the preferred way to write a recursive function.
Now, you might ask, what if you want to return the recursive function object directly, rather than execute it? There, too, you can use letrec:
(letrec ((factorial (lambda (x)
(if (< x 1) 1
(* (factorial (- x 1)) x)))))
factorial)
There, too, is a shorthand for this, although not using named let, but instead using rec:
(rec (factorial x)
(if (< x 1) 1
(* (factorial (- x 1)) x)))
The nice thing about using rec here is that you can assign the function object to a variable and execute it later.
(define my-fact (rec (factorial x)
(if (< x 1) 1
(* (factorial (- x 1)) x))))
(my-fact 10) ; => 3628800
The more theoretical and "pure" way to create recursive functions is to use a Y combinator. :-) But most practical Scheme programs do not use this approach, so I won't discuss it further.
No need to write factorial body twice ;)
(((lambda (f)
(lambda (x)
(f f x)))
(lambda (fact x)
(if (= x 0) 1 (* x (fact fact (- x 1)))))) 5)
Here is a recursive function that calculates the factorial of 5 using lambda
((lambda (f x)
(if (= x 0)
1
(* x (f f (- x 1)))))
(lambda (f x)
(if (= x 0)
1
(* x (f f (- x 1)))))
5)
When you run this program in Drracket you get 120 :)
The function is supposed to be tail-recursive and count from 1 to the specified number. I think I'm fairly close. Here's what I have:
(define (countup l)
(if (= 1 l)
(list l)
(list
(countup (- l 1))
l
)
)
)
However, this obviously returns a list with nested lists. I've attempted to use the append function instead of the second list to no avail. Any guidance?
Here's an incorrect solution:
(define (countup n)
(define (help i)
(if (<= i n)
(cons i (help (+ i 1)))
'()))
(help 1))
This solution:
uses a helper function
recurses over the numbers from 1 to n, cons-ing them onto an ever-growing list
Why is this wrong? It's not really tail-recursive, because it creates a big long line of cons calls which can't be evaluated immediately. This would cause a stack overflow for large enough values of n.
Here's a better way to approach this problem:
(define (countup n)
(define (help i nums)
(if (> i 0)
(help (- i 1)
(cons i nums))
nums)))
(help n '()))
Things to note:
this solution is better because the calls to cons can be evaluated immediately, so this function is a candidate for tail-recursion optimization (TCO), in which case stack space won't be a problem.
help recurses over the numbers backwards, thus avoiding the need to use append, which can be quite expensive
You should use an auxiliar function for implementing a tail-recursive solution for this problem (a "loop" function), and use an extra parameter for accumulating the answer. Something like this:
(define (countup n)
(loop n '()))
(define (loop i acc)
(if (zero? i)
acc
(loop (sub1 i) (cons i acc))))
Alternatively, you could use a named let. Either way, the solution is tail-recursive and a parameter is used for accumulating values, notice that the recursion advances backwards, starting at n and counting back to 0, consing each value in turn at the beginning of the list:
(define (countup n)
(let loop ((i n)
(acc '()))
(if (zero? i)
acc
(loop (sub1 i) (cons i acc)))))
Here a working version of your code that returns a list in the proper order (I replaced l by n):
(define (countup n)
(if (= 1 n)
(list n)
(append (countup (- n 1)) (list n))))
Sadly, there is a problem with this piece of code: it is not tail-recursive. The reason is that the recursive call to countup is not in a tail position. It is not in tail position because I'm doing an append of the result of (countup (- l 1)), so the tail call is append (or list when n = 1) and not countup. This means this piece of code is a normal recusrive function but to a tail-recursive function.
Check this link from Wikipedia for a better example on why it is not tail-recusrive.
To make it tail-recursive, you would need to have an accumulator responsible of accumulating the counted values. This way, you would be able to put the recursive function call in a tail position. See the difference in the link I gave you.
Don't hesitate to reply if you need further details.
Assuming this is for a learning exercise and you want this kind of behaviour:
(countup 5) => (list 1 2 3 4 5)
Here's a hint - in a tail-recursive function, the call in tail position should be to itself (unless it is the edge case).
Since countup doesn't take a list of numbers, you will need an accumulator function that takes a number and a list, and returns a list.
Here is a template:
;; countup : number -> (listof number)
(define (countup l)
;; countup-acc : number, (listof number) -> (listof number)
(define (countup-acc c ls)
(if ...
...
(countup-acc ... ...)))
(countup-acc l null))
In the inner call to countup-acc, you will need to alter the argument that is checked for in the edge case to get it closer to that edge case, and you will need to alter the other argument to get it closer to what you want to return in the end.
I'm in a Scheme class and I was curious about writing a recursive function without using define. The main problem, of course, is that you cannot call a function within itself if it doesn't have a name.
I did find this example: It's a factorial generator using only lambda.
((lambda (x) (x x))
(lambda (fact-gen)
(lambda (n)
(if (zero? n)
1
(* n ((fact-gen fact-gen) (sub1 n)))))))
But I can't even make sense of the first call, (lambda (x) (x x)): What exactly does that do? And where do you input the value you want to get the factorial of?
This is not for the class, this is just out of curiosity.
(lambda (x) (x x)) is a function that calls an argument, x, on itself.
The whole block of code you posted results in a function of one argument. You could call it like this:
(((lambda (x) (x x))
(lambda (fact-gen)
(lambda (n)
(if (zero? n)
1
(* n ((fact-gen fact-gen) (sub1 n)))))))
5)
That calls it with 5, and returns 120.
The easiest way to think about this at a high level is that the first function, (lambda (x) (x x)), is giving x a reference to itself so now x can refer to itself, and hence recurse.
The expression (lambda (x) (x x)) creates a function that, when evaluated with one argument (which must be a function), applies that function with itself as an argument.
Your given expression evaluates to a function that takes one numeric argument and returns the factorial of that argument. To try it:
(let ((factorial ((lambda (x) (x x))
(lambda (fact-gen)
(lambda (n)
(if (zero? n)
1
(* n ((fact-gen fact-gen) (sub1 n)))))))))
(display (factorial 5)))
There are several layers in your example, it's worthwhile to work through step by step and carefully examine what each does.
Basically what you have is a form similar to the Y combinator. If you refactored out the factorial specific code so that any recursive function could be implemented, then the remaining code would be the Y combinator.
I have gone through these steps myself for better understanding.
https://gist.github.com/z5h/238891
If you don't like what I've written, just do some googleing for Y Combinator (the function).
(lambda (x) (x x)) takes a function object, then invokes that object using one argument, the function object itself.
This is then called with another function, which takes that function object under the parameter name fact-gen. It returns a lambda that takes the actual argument, n. This is how the ((fact-gen fact-gen) (sub1 n)) works.
You should read the sample chapter (Chapter 9) from The Little Schemer if you can follow it. It discusses how to build functions of this type, and ultimately extracting this pattern out into the Y combinator (which can be used to provide recursion in general).
You define it like this:
(let ((fact #f))
(set! fact
(lambda (n) (if (< n 2) 1
(* n (fact (- n 1))))))
(fact 5))
which is how letrec really works. See LiSP by Christian Queinnec.
In the example you're asking about, the self-application combinator is called "U combinator",
(let ((U (lambda (x) (x x)))
(h (lambda (g)
(lambda (n)
(if (zero? n)
1
(* n ((g g) (sub1 n))))))))
((U h) 5))
The subtlety here is that, because of let's scoping rules, the lambda expressions can not refer to the names being defined.
When ((U h) 5) is called, it is reduced to ((h h) 5) application, inside the environment frame created by the let form.
Now the application of h to h creates new environment frame in which g points to h in the environment above it:
(let ((U (lambda (x) (x x)))
(h (lambda (g)
(lambda (n)
(if (zero? n)
1
(* n ((g g) (sub1 n))))))))
( (let ((g h))
(lambda (n)
(if (zero? n)
1
(* n ((g g) (sub1 n))))))
5))
The (lambda (n) ...) expression here is returned from inside that environment frame in which g points to h above it - as a closure object. I.e. a function of one argument, n, which also remembers the bindings for g, h, and U.
So when this closure is called, n gets assigned 5, and the if form is entered:
(let ((U (lambda (x) (x x)))
(h (lambda (g)
(lambda (n)
(if (zero? n)
1
(* n ((g g) (sub1 n))))))))
(let ((g h))
(let ((n 5))
(if (zero? n)
1
(* n ((g g) (sub1 n)))))))
The (g g) application gets reduced into (h h) application because g points to h defined in the environment frame above the environment in which the closure object was created. Which is to say, up there, in the top let form. But we've already seen the reduction of (h h) call, which created the closure i.e. the function of one argument n, serving as our factorial function, which on the next iteration will be called with 4, then 3 etc.
Whether it will be a new closure object or same closure object will be reused, depends on a compiler. This can have an impact on performance, but not on semantics of the recursion.
I like this question. 'The scheme programming language' is a good book. My idea is from Chapter 2 of that book.
First, we know this:
(letrec ((fact (lambda (n) (if (= n 1) 1 (* (fact (- n 1)) n))))) (fact 5))
With letrec we can make functions recursively. And we see when we call (fact 5), fact is already bound to a function. If we have another function, we can call it this way (another fact 5), and now another is called binary function (my English is not good, sorry). We can define another as this:
(let ((another (lambda (f x) .... (f x) ...))) (another fact 5))
Why not we define fact this way?
(let ((fact (lambda (f n) (if (= n 1) 1 (* n (f f (- n 1))))))) (fact fact 5))
If fact is a binary function, then it can be called with a function f and integer n, in which case function f happens to be fact itself.
If you got all the above, you could write Y combinator now, making a substitution of let with lambda.
With a single lambda it's not possible. But using two or more lambda's it is possible. As, all other solutions are using three lambdas or let/letrec, I'm going to explain the method using two lambdas:
((lambda (f x)
(f f x))
(lambda (self n)
(if (= n 0)
1
(* n (self self (- n 1)))))
5)
And the output is 120.
Here,
(lambda (f x) (f f x)) produces a lambda that takes two arguments, the first one is a lambda(lets call it f) and the second is the parameter(let's call it x). Notice, in its body it calls the provided lambda f with f and x.
Now, lambda f(from point 1) i.e. self is what we want to recurse. See, when calling self recursively, we also pass self as the first argument and (- n 1) as the second argument.
I was curious about writing a recursive function without using define.
The main problem, of course, is that you cannot call a function within
itself if it doesn't have a name.
A little off-topic here, but seeing the above statements I just wanted to let you know that "without using define" does not mean "doesn't have a name". It is possible to give something a name and use it recursively in Scheme without define.
(letrec
((fact
(lambda (n)
(if (zero? n)
1
(* n (fact (sub1 n)))))))
(fact 5))
It would be more clear if your question specifically says "anonymous recursion".
I found this question because I needed a recursive helper function inside a macro, where one can't use define.
One wants to understand (lambda (x) (x x)) and the Y-combinator, but named let gets the job done without scaring off tourists:
((lambda (n)
(let sub ((i n) (z 1))
(if (zero? i)
z
(sub (- i 1) (* z i)) )))
5 )
One can also put off understanding (lambda (x) (x x)) and the Y-combinator, if code like this suffices. Scheme, like Haskell and the Milky Way, harbors a massive black hole at its center. Many a formerly productive programmer gets entranced by the mathematical beauty of these black holes, and is never seen again.