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)))
Related
I've been trying to tinker with this code to rewrite a "repeat" function using tail-end recursion but have gotten a bit stuck in my attempts.
(define (repeat n x)
(if (= n 0)
'()
(cons x (repeat (- n 1) x))))
This is the original "repeat" function. It traverses through 'n - 1' levels of recursion then appends 'x' into a list in 'n' additional recursive calls. Instead of that, the recursive call should be made and the 'x' should be appended to a list at the same time.
(define (repeat-tco n x)
(trace-let rec ([i 0]
[acc '()])
(if (= i n)
acc
(rec (+ i 1) (cons x acc)))))
This is the closest rewritten version that I've come up with which I believe follows tail-call recursion but I'm not completely sure.
Your repeat-tco function is indeed tail recursive: it is so because the recursive call to rec is in 'tail position': at the point where it's called, the function that is calling it has nothing left to do but return the value of that call.
[The following is just some perhaps useful things: the answer is above, but an answer which was essentially 'yes' seemed too short.]
This trick of taking a procedure p which accumulates some result via, say (cons ... (p ...)) and turning it into a procedure with an extra 'accumulator' argument which is then tail recursive is very common. A result of using this technique is that the results come out backwards: this doesn't matter for you because all the elements of your list are the same, but imagine this:
(define (evens/backwards l)
(let loop ([lt l]
[es '()])
(if (null? lt)
es
(loop (rest lt)
(if (even? (first lt))
(cons (first lt) es)
es)))))
This will return the even elements of its arguments, but backwards. If you want them the right way around, a terrible answer is
(define (evens/terrible l)
(let loop ([lt l]
[es '()])
(if (null? lt)
es
(loop (rest lt)
(if (even? (first lt))
(append es (list (first lt)))
es)))))
(Why is it a terrible answer?) The proper answer is
(define (evens l)
(let loop ([lt l]
[es '()])
(if (null? lt)
(reverse es)
(loop (rest lt)
(if (even? (first lt))
(cons (first lt) es)
es)))))
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)))))
We are tasked to print out the values in the pascal triangle in this manner
(pascal 2)
(1 2 1)
(pascal 0)
(1)
I copied the code for the binomial thereom somewhere in the internet defined as follows:
(defun choose(n k)
(labels ((prod-enum (s e)
(do ((i s (1+ i)) (r 1 (* i r))) ((> i e) r)))
(fact (n) (prod-enum 1 n)))
(/ (prod-enum (- (1+ n) k) n) (fact k))))
Now I'm trying to create a list out of the values here in my pascal function:
(defun pascal (start end)
(do ((i start (+ i 1)))
((> i end) )
(print (choose end i) ))
)
The function produces 1 2 1 NIL if I test it with (pascal 0 2). How can I eliminate the NIL and create the list?
Note: I explicitly didn't provide an implementation of pascal, since the introductory “we are tasked…” suggests that this is a homework assignment.
Instead of printing the result of (choose end i) on each iteration, just collect the values produced by (choose end i) into a list of results, and then return the results at the end of the loop. It's a common idiom to construct a list in reverse order by pushing elements into it, and then using nreverse to reverse it to produce the final return value. For instance, you might implement range by:
(defun range (start end &optional (delta 1) &aux (results '()))
(do ((i start (+ i delta)))
((>= i end) (nreverse results))
(push i results)))
or (It always feels satisfying to write a do/do* loop that doesn't need any code in the body.)
(defun range (start end &optional (delta 1))
(do* ((results '() (list* i results))
(i start (+ i delta)))
((>= i end) (nreverse results))))
so that
(range 0 10 3)
;=> (0 3 6 9)
However, since the rows in Pascal's triangle are palidromes, you don't need to reverse them. Actually, since the rows are palindromes, you should even be able to adjust the loop to generate just half the list return, e.g.,
(revappend results results)
when there are an even number of elements, and
(revappend results (rest results))
when there are an odd number.
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'm trying to solve this problem in a pure-functional way, without using set!.
I've written a function that calls a given lambda for each number in the fibonacci series, forever.
(define (each-fib fn)
(letrec
((next (lambda (a b)
(fn a)
(next b (+ a b)))))
(next 0 1)))
I think this is as succinct as it can be, but if I can shorten this, please enlighten me :)
With a definition like the above, is it possible to write another function that takes the first n numbers from the fibonacci series and gives me a list back, but without using variable mutation to track the state (which I understand is not really functional).
The function signature doesn't need to be the same as the following... any approach that will utilize each-fib without using set! is fine.
(take-n-fibs 7) ; (0 1 1 2 3 5 8)
I'm guessing there's some sort of continuations + currying trick I can use, but I keep coming back to wanting to use set!, which is what I'm trying to avoid (purely for learning purposes/shifting my thinking to purely functional).
Try this, implemented using lazy code by means of delayed evaluation:
(define (each-fib fn)
(letrec
((next (lambda (a b)
(fn a)
(delay (next b (+ a b))))))
(next 0 1)))
(define (take-n-fibs n fn)
(let loop ((i n)
(promise (each-fib fn)))
(when (positive? i)
(loop (sub1 i) (force promise)))))
As has been mentioned, each-fib can be further simplified by using a named let:
(define (each-fib fn)
(let next ((a 0) (b 1))
(fn a)
(delay (next b (+ a b)))))
Either way, it was necessary to modify each-fib a little for using the delay primitive, which creates a promise:
A promise encapsulates an expression to be evaluated on demand via force. After a promise has been forced, every later force of the promise produces the same result.
I can't think of a way to stop the original (unmodified) procedure from iterating indefinitely. But with the above change in place, take-n-fibs can keep forcing the lazy evaluation of as many values as needed, and no more.
Also, take-n-fibs now receives a function for printing or processing each value in turn, use it like this:
(take-n-fibs 10 (lambda (n) (printf "~a " n)))
> 0 1 1 2 3 5 8 13 21 34 55
You provide an iteration function over fibonacci elements. If you want, instead of iterating over each element, to accumulate a result, you should use a different primitive that would be a fold (or reduce) rather than an iter.
(It might be possible to use continuations to turn an iter into a fold, but that will probably be less readable and less efficient that a direct solution using either a fold or mutation.)
Note however that using an accumulator updated by mutation is also fine, as long as you understand what you are doing: you are using mutable state locally for convenience, but the function take-n-fibs is, seen from the outside, observationally pure, so you do not "contaminate" your program as a whole with side effects.
A quick prototype for fold-fib, adapted from your own code. I made an arbitrary choice as to "when stop folding": if the function returns null, we return the current accumulator instead of continuing folding.
(define (fold-fib init fn) (letrec ([next (lambda (acc a b)
(let ([acc2 (fn acc a)])
(if (null? acc2) acc
(next acc2 b (+ a b)))))])
(next init 0 1)))
(reverse (fold-fib '() (lambda (acc n) (if (> n 10) null (cons n acc)))))
It would be better to have a more robust convention to end folding.
I have written few variants. First you ask if
(define (each-fib fn)
(letrec
((next (lambda (a b)
(fn a)
(next b (+ a b)))))
(next 0 1)))
can be written any shorter. The pattern is used so often that special syntax called named let has been introduced. Your function looks like this using a named let:
(define (each-fib fn)
(let next ([a 0] [b 1])
(fn a)
(next b (+ a b))))
In order to get the control flowing from one function to another, one can in languages with supports TCO use continuation passing style. Each function gets an extra argument often called k (for continuation). The function k represents what-to-do-next.
Using this style, one can write your program as follows:
(define (generate-fibs k)
(let next ([a 0] [b 1] [k k])
(k a (lambda (k1)
(next b (+ a b) k1)))))
(define (count-down n k)
(let loop ([n n] [fibs '()] [next generate-fibs])
(if (zero? n)
(k fibs)
(next (λ (a next)
(loop (- n 1) (cons a fibs) next))))))
(count-down 5 values)
Now it is a bit annoying to write in style manually, so it could
be convenient to introduce the co-routines. Breaking your rule of not using set! I have chosen to use a shared variable fibs in which generate-fibs repeatedly conses new fibonacci numbers onto. The count-down routine merely read the values, when the count down is over.
(define (make-coroutine co-body)
(letrec ([state (lambda () (co-body resume))]
[resume (lambda (other)
(call/cc (lambda (here)
(set! state here)
(other))))])
(lambda ()
(state))))
(define fibs '())
(define generate-fib
(make-coroutine
(lambda (resume)
(let next ([a 0] [b 1])
(set! fibs (cons a fibs))
(resume count-down)
(next b (+ a b))))))
(define count-down
(make-coroutine
(lambda (resume)
(let loop ([n 10])
(if (zero? n)
fibs
(begin
(resume generate-fib)
(loop (- n 1))))))))
(count-down)
And a bonus you get a version with communicating threads:
#lang racket
(letrec ([result #f]
[count-down
(thread
(λ ()
(let loop ([n 10] [fibs '()])
(if (zero? n)
(set! result fibs)
(loop (- n 1) (cons (thread-receive) fibs))))))]
[produce-fibs
(thread
(λ ()
(let next ([a 0] [b 1])
(when (thread-running? count-down)
(thread-send count-down a)
(next b (+ a b))))))])
(thread-wait count-down)
result)
The thread version is Racket specific, the others ought to run anywhere.
Building a list would be hard. But displaying the results can still be done (in a very bad fashion)
#lang racket
(define (each-fib fn)
(letrec
((next (lambda (a b)
(fn a)
(next b (+ a b)))))
(next 0 1)))
(define (take-n-fibs n fn)
(let/cc k
(begin
(each-fib (lambda (x)
(if (= x (fib (+ n 1)))
(k (void))
(begin
(display (fn x))
(newline))))))))
(define fib
(lambda (n)
(letrec ((f
(lambda (i a b)
(if (<= n i)
a
(f (+ i 1) b (+ a b))))))
(f 1 0 1))))
Notice that i am using the regular fibonacci function as an escape (like i said, in a very bad fashion). I guess nobody will recommend programming like this.
Anyway
(take-n-fibs 7 (lambda (x) (* x x)))
0
1
1
4
9
25
64