confusion of letrec, Scheme - scheme

I am struggling the difference between let, letrec, let* ...
since scheme is not my primary programming language, my memory is not existing for long time..
I have this function.. now I am very confusing with letrec here.. this is again recursion.that I can understand...but can't make connection enough in this code.. (maybe still confuse about recursion)
can someone explain why here need letrec
(define myFunc
(lambda (start end res func)
(letrec ((func:rec_func
(lambda (x i y)
(if (>= i start)
(func:rec_func (cons i x) (- i res) (cons (func i) y)) ;; line6
(cons x (cons y '())))))) ;; line7
(func:rec_func '() end '()))))
(edited)
what I understand it's tail recursion
-> [Q1] Does it tail recursion?
-> [Q2] then, should use always letrec for tail recursion?
this function returns the lists of x, y with boundaries of start, end
so it checks index i is inside boundaries , if yes, then do line 6
-> [Q3]then, what does line6 ? I can't get the line6

The difference with letrec, let and let* is when they do the declaration available to the program.
(letrec ((X (you could use X here))
(Y (you could use X here too))
)
(X also is available here)
)
(let ((X (nope, X isn't declared yet))
(Y (in fact, no declaration body will see X))
)
(But X is available here)
)
(let* ((X (X isn't available here))
(Y (but you could use it here))
)
(X also is available here)
)
To recap:
The scope of a variable declared with letrec is ALL inside of the body of letrec. The compiler do some magic so the references are replaced after the declarations are over.
The scope of a variable declared with let* are all expresions in the scope of let* after the declaration of the variable.
And the scope of a variable declared with let is just the body of let, not the declaration parts.

If I remember correctly, this construct requires letrec rather than let or let* because the body of func:rec_func refers to itself. If you used let or let* here, the symbol func:rec_func within the nested lambda would be bound to any definition visible outside the top-level form, or undefined if there was no such definition - neither is what you want.

[Q1] Does it tail recursion?
Answer Yes, it does tail recursion.
[Q2] then, should use always letrec for tail recursion?
Answer There are two ways of interpreting your question.
Should we always use letrec for tail recursion? I don't think you meant to ask this. But ...
The answer is no. Top level lambda functions can also be used for tail recursion.
Should letrec always use tail recursion?
The answer to that is: It's better for any recursive function to be tail recursive. If you can, you should make it tail recursive.
[Q3] then what does line6 ?
The code at line 6 performs the recursive call.
Let's say start is 0, end is 5, and res is 1. In the first call to func:rec_func, x is the empty list (), i is 5, and y is the empty list ().
When the first recursive function is called at line 6, the arguments are (cons i x), (- i res), and (cons (func i) y), which evaluate to: (5), 4, and ((func 5).
In the next iteration, the arguments are (4 5), 3, and ((func 4) (func 5)).
It continues until i becomes less than start. Then the recursion stops with the result ((0 1 2 3 4 5) ((func 0) (func 1) (func 2) (func 3) (func 4) (func 5)))
The code at line 7 is executed when the terminating criterion for the recursion is met, which is when (>= i start) is false.

Related

What is the purpose of Closures in Scheme/Racket?

I am learning Scheme and just came across Closures. The following example provided, demonstrating the use of Closures:
(define (create-closure x)
(lambda () x))
(define val (create-closure 10))
From what I understand, when the above code is evaluated, val will equal to 10. I realize this is just an example, but I don't understand just how a closure would be helpful. What are the advantages and what would a scenario where such a concept would be needed?
val is not 10 but a closure. If you call it like (val) it returns the value of x. x is a closure variable that still exists since it's still in use. A better example is this:
(define (larger-than-predicate n)
(lambda (v) (> v n )))
(filter (larger-than-predicate 5) '(1 2 3 4 5 6 7 8 9 10))
; ==> (6 7 8 9 10)
So the predicate compares the argument with v which is a variable that still holds 5. In a dynamic bound lisp this is not possible to do because n will not exist when the comparison happens.
Lecical scoping was introduces in Algol and Scheme. JavaScript, PHP amd C# are all algol dialects and have inherited it from there. Scheme was the first lisp to get it and Common Lisp followed. It's actually the most common scoping.
From this example you can see that the closure allows the functions local environment to remain accessible after being called.
(define count
(let ((next 0))
(lambda ()
(let ((v next))
(set! next (+ next 1))
v))))
(count)
(count)
(count)
0..1..2
I believe in the example you give, val will NOT equal to 10, instead, a lambda object (lambda () 10) will be assigned to val. So (val) equals to 10.
In the world of Scheme, there are two different concepts sharing the same term "closure". See this post for a brief introduction to both of these terms. In your case, I believe by "closure" you mean "lexical closure". In your code example, the parameter x is a free variable to the returned lambda and is referred to by that returned lambda, so a lexical closure is kept to store the value of x. I believe this post will give you a good explanation on what (lexical) closure is.
Totally agree with Lifu Huang's answer.
In addition, I'd like to highlight the most obvious use of closures, namely callbacks.
For instance, in JavaScript, I might write
function setup(){
var presses = 0;
function handleKeyPress(evt){
presses = presses + 1;
return mainHandler(evt);
}
installKeyHandler(handleKeyPress);
}
In this case, it's important to me that the function that I'm installing as the key handler "knows about" the binding for the presses variable. That binding is stored in the closure. Put differently, the function is "closed over" the binding for presses.
Similar things occur in nearly every http GET or POST call made in JS. It crops up in many many other places as well.
Btw, create-closure from your question is known by some as the Kestrel combinator, from the family of Combinator Birds. It is also known as True in Church encoding, which encodes booleans (and everything else) using lambdas (closures).
(define (kestrel a)
(lambda (b) a))
(define (create-list size proc)
(let loop ((x 0))
(if (= x size)
empty
(cons (proc x)
(loop (add1 x))))))
(create-list 5 identity)
; '(0 1 2 3 4)
(create-list 5 (kestrel 'a))
; '(a a a a a)
In Racket (I'm unsure about Scheme), this procedure is known as const -
(create-list 5 (const 'a))
; '(a a a a a)

Compile/Evaluate operands in tailposition

I have a project for school for which I'm supposed to optimize a compiler/evaluator for Scheme.
The task is to implement tail-call optimization wherever possible.
I'm aware of the known tail-call optimization as shown below:
(define (f x)
<send some rockets into space>
(f (+ x 1)))
However, I'm thinking about evaluating operands in tail position as well. Suppose the following:
; The function
(define (f a b c)
<send some monkeys into space>
1)
; Call the function with (f 3 4 5)
(f (+ 1 2) (begin (define x 4) x) 5))
Evaluating the operands (+ 1 2), (begin (define x 4)) and 5 could be done in tail position, right?
Each of the operands are evaluated in their own environment. I tried this by using the regular R5RS in DrRacket with the following expression:
(+ (begin (define x 5) x) x)
If the operands would be evaluated in the same environment I would be able to pass the x defined in the first operand as the second operand. This is however not possible.
So, is it correct for me to assume that each operand can be evaluated in tail position?
"Tail position" is always relative to some outer expression. For example, consider this:
(define (norm . args)
(define (sum-of-squares sum args)
(if (null? args)
sum
(let ((arg (car args)))
(sum-of-squares (+ sum (* arg arg)) (cdr args)))))
(sqrt (sum-of-squares 0 args)))
The recursive call to sum-of-squares is indeed in tail position relative to sum-of-squares. But is it in tail position relative to norm? No, because the return value from sum-of-squares is sent to sqrt, not directly to norm's caller.
The key to analysing whether an expression A is in tail position relative to outer expression B, is to see whether A's return value is directly returned by B, without any further processing.
In your case, with your expression (f (+ 1 2) (begin (define x 4) x) 5) (which isn't actually valid, by the way: perhaps you meant (f (+ 1 2) (let () (define x 4) x) 5) instead), none of the subexpressions (+ 1 2), (let () (define x 4) x), and 5 are in tail position with respect to f, since their values have to be collected first, and then passed to f (which is a tail call).
None of the operands of an application (op1 op2 ...) is in tail position.
For R5RS Scheme you can see the position in which an application occurs in a tail context here:
https://groups.csail.mit.edu/mac/ftpdir/scheme-reports/r5rs-html.old/r5rs_22.html
So I finally figured it out.
In regular R6RS operands can never be evaluated in tail position because R6RS specifies that there is no strict order in which they are evaluated.
However, in this self-built evaluator for Scheme I do specify the order in which they are evaluated. Ergo, I can strictly define which operator is the last one, and that one can be evaluated in tail position.

Getting elisp to return a function as return value

I'm trying to create a function in elisp that returns another function. I looked at this answer to a similar question (how to return function in elisp) but did not understand the answer (I'm literally just starting learning elisp today, so please excuse my ignorance). I thought a simpler example would help. First, consider a function that test whether a number is divisible by 5:
(defun divisible-by-5 (x)
;; tests whether a number is divsible by 5.
(setq remainder (% x 5))
(if (= remainder 0) 1 0)
)
This works fine:
(divisible-by-5 25)
1
Now suppose I want to create a function that can create more of these kinds of test functions---something like:
(defun divisible-by-z (z)
(lambda (z)
(setq remainder (% x z))
(if (= remainder 0) 1 0))
)
This does not work. E.g.,
(defun divisible-by-3 (divisible-by-z 3))
(divisible-by-3 4)
returns an error. I think even seeing an elisp-idiomatic example of how one would implement this pattern would be helpful.
First, make sure you have lexical-binding enabled. The simplest way to do so is to evaluate (setq lexical-binding t) in your current buffer. More information on the topic can be found here.
Your definition of divisible-by-z is basically correct except that you have a mistype (naming both parameters z; the lambda's parameter should be x). Also, it would be more idiomatic to introduce the binding for remainder with let - setq is generally reserved for mutating bindings that already exist. Here's the result:
(defun divisible-by-z (z)
(lambda (x)
(let ((remainder (% x z)))
(if (= remainder 0) 1 0))))
You can't use defun to create divisible-by-3 in quite the way you've tried - it's expecting the argument list for a new function to be where you have the call to divisible-by-z.
You could either create a global, dynamic binding with
(defvar divisible-by-3 (divisible-by-z 3))
Or a local, lexical binding with
(let ((divisible-by-3 (divisible-by-z 3)))
...)
Either way, you'll then need to use funcall to call the function
(funcall divisible-by-3 9) ; => 1
Of course, you could also skip giving it its own name entirely and simply
(funcall (divisible-by-z 3) 10) ; => 0
funcall is necessary because Emacs Lisp is (basically) a Lisp-2, meaning it can attach both a function and a value to a given symbol. So when you're treating functions as values (returning one from a function or passing one in to a function as a parameter) you essentially have to tell it to look in that value "cell" rather than the usual function cell. If you search for "Lisp-1 vs Lisp-2" you'll find more than you want to know about this.
A possible solution:
(defun divisible-by-3 (x)
(funcall (divisible-by-z 3) x))
Another (perhaps simpler) method is to include x as a variable to be passed to the function:
(defun divisible-by-z (x z) "
Check if x is divisible by z.
If so, return 0.
If not, return the remainder."
(if (% x z) (% x z) 0))
thus:
(divisible-by-z 5 2) --> 1
(divisible-by-z 4 2) --> 0

Letrec and reentrant continuations

I have been told that the following expression is intended to evaluate to 0, but that many implementations of Scheme evaluate it as 1:
(let ((cont #f))
(letrec ((x (call-with-current-continuation (lambda (c) (set! cont c) 0)))
(y (call-with-current-continuation (lambda (c) (set! cont c) 0))))
(if cont
(let ((c cont))
(set! cont #f)
(set! x 1)
(set! y 1)
(c 0))
(+ x y))))
I must admit that I cannot tell where even to start with this. I understand the basics of continuations and call/cc, but can I get a detailed explanation of this expression?
This is an interesting fragment. I came across this question because I was searching for discussions of the exact differences between letrec and letrec*, and how these varied between different versions of the Scheme reports, and different Scheme implementations. While experimenting with this fragment, I did some research and will report the results here.
If you mentally walk through the execution of this fragment, two questions should be salient to you:
Q1. In what order are the initialization clauses for x and y evaluated?
Q2. Are all the initialization clauses evaluated first, and their results cached, and then all the assignments to x and y performed afterwards? Or are some of the assignments made before some of the initialization clauses have been evaluated?
For letrec, the Scheme reports say that the answer to Q1 is "unspecified." Most implementations will in fact evaluate the clauses in left-to-right order; but you shouldn't rely on that behavior.
Scheme R6RS and R7RS introduce a new binding construction letrec* that does specify left-to-right evaluation order. It also differs in some other ways from letrec, as we'll see below.
Returning to letrec, the Scheme reports going back at least as far as R5RS seem to specify that the answer to Q2 is "evaluate all the initialization clauses before making any of the assignments." I say "seem to specify" because the language isn't as explicit about this being required as it might be. As a matter of fact, many Scheme implementations don't conform to this requirement. And this is what's responsible for the difference between the "intended" and "observed" behavior wrt your fragment.
Let's walk through your fragment, with Q2 in mind. First we set aside two "locations" (reference cells) for x and y to be bound to. Then we evaluate one of the initialization clauses. Let's say it's the clause for x, though as I said, with letrec it could be either one. We save the continuation of this evaluation into cont. The result of this evaluation is 0. Now, depending on the answer to Q2, we either assign that result immediately to x or we cache it to make the assignment later. Next we evaluate the other initialization clause. We save its continuation into cont, overwriting the previous one. The result of this evaluation is 0. Now all of the initialization clauses have been evaluated. Depending on the answer to Q2, we might at this point assign the cached result 0 to x; or the assignment to x may have already occurred. In either case, the assignment to y takes place now.
Then we begin evaluating the main body of the (letrec (...) ...) expression (for the first time). There is a continuation stored in cont, so we retrieve it into c, then clear cont and set! each of x and y to 1. Then we invoke the retrieved continuation with the value 0. This goes back to the last-evaluated initialization clause---which we've assumed to be y's. The argument we supply to the continuation is then used in place of the (call-with-current-continuation (lambda (c) (set! cont c) 0)), and will be assigned to y. Depending on the answer to Q2, the assignment of 0 to x may or may not take place (again) at this point.
Then we begin evaluating the main body of the (letrec (...) ...) expression (for the second time). Now cont is #f, so we get (+ x y). Which will be either (+ 1 0) or (+ 0 0), depending on whether 0 was re-assigned to x when we invoked the saved continuation.
You can trace this behavior by decorating your fragment with some display calls, for example like this:
(let ((cont #f))
(letrec ((x (begin (display (list 'xinit x y cont)) (call-with-current-continuation (lambda (c) (set! cont c) 0))))
(y (begin (display (list 'yinit x y cont)) (call-with-current-continuation (lambda (c) (set! cont c) 0)))))
(display (list 'body x y cont))
(if cont
(let ((c cont))
(set! cont #f)
(set! x 1)
(set! y 1)
(c 'new))
(cons x y))))
I also replaced (+ x y) with (cons x y), and invoked the continuation with the argument 'new instead of 0.
I ran that fragment in Racket 5.2 using a couple of different "language modes", and also in Chicken 4.7. Here are the results. Both implementations evaluated the x init clause first and the y clause second, though as I said this behavior is unspecified.
Racket with #lang r5rs and #lang r6rs conforms to the spec for Q2, and so we get the "intended" result of re-assigning 0 to the other variable when the continuation is invoked. (When experimenting with r6rs, I needed to wrap the final result in a display to see what it would be.)
Here is the trace output:
(xinit #<undefined> #<undefined> #f)
(yinit #<undefined> #<undefined> #<continuation>)
(body 0 0 #<continuation>)
(body 0 new #f)
(0 . new)
Racket with #lang racket and Chicken don't conform to that. Instead, after each initialization clause is evaluated, it gets assigned to the corresponding variable. So when the continuation is invoked, it only ends up re-assigning a value to the final value.
Here is the trace output, with some added comments:
(xinit #<undefined> #<undefined> #f)
(yinit 0 #<undefined> #<continuation>) ; note that x has already been assigned
(body 0 0 #<continuation>)
(body 1 new #f) ; so now x is not re-assigned
(1 . new)
Now, as to what the Scheme reports really do require. Here is the relevant section from R5RS:
library syntax: (letrec <bindings> <body>)
Syntax: <Bindings> should have the form
((<variable1> <init1>) ...),
and <body> should be a sequence of one or more expressions. It is an error
for a <variable> to appear more than once in the list of variables being bound.
Semantics: The <variable>s are bound to fresh locations holding undefined
values, the <init>s are evaluated in the resulting environment (in some
unspecified order), each <variable> is assigned to the result of the
corresponding <init>, the <body> is evaluated in the resulting environment, and
the value(s) of the last expression in <body> is(are) returned. Each binding of
a <variable> has the entire letrec expression as its region, making it possible
to define mutually recursive procedures.
(letrec ((even?
(lambda (n)
(if (zero? n)
#t
(odd? (- n 1)))))
(odd?
(lambda (n)
(if (zero? n)
#f
(even? (- n 1))))))
(even? 88))
===> #t
One restriction on letrec is very important: it must be possible to evaluate
each <init> without assigning or referring to the value of any <variable>. If
this restriction is violated, then it is an error. The restriction is necessary
because Scheme passes arguments by value rather than by name. In the most
common uses of letrec, all the <init>s are lambda expressions and the
restriction is satisfied automatically.
The first sentence of the "Semantics" sections sounds like it requires all the assignments to happen after all the initialization clauses have been evaluated; though, as I said earlier, this isn't as explicit as it might be.
In R6RS and R7RS, the only substantial changes to this part of the specification is the addition of a requirement that:
the continuation of each <init> should not be invoked more than once.
R6RS and R7RS also add another binding construction, though: letrec*. This differs from letrec in two ways. First, it does specify a left-to-right evaluation order. Correlatively, the "restriction" noted above can be relaxed somewhat. It's now okay to reference the values of variables that have already been assigned their initial values:
It must be possible to evaluate each <init> without assigning or
referring to the value of the corresponding <variable> or the
<variable> of any of the bindings that follow it in <bindings>.
The second difference is with respect to our Q2. With letrec*, the specification now requires that the assignments take place after each initialization clause is evaluated. Here is the first paragraph of the "Semantics" from R7RS (draft 6):
Semantics: The <variable>s are bound to fresh locations, each
<variable> is assigned in left-to-right order to the result of evaluating
the corresponding <init>, the <body> is evaluated in the resulting
environment, and the values of the last expression in <body> are
returned. Despite the left-to-right evaluation and assignment order, each
binding of a <variable> has the entire letrec* expression as its region,
making it possible to define mutually recursive procedures.
So Chicken, and Racket using #lang racket---and many other implementations---seem in fact to implement their letrecs as letrec*s.
The reason for this being evaluated to 1 is because of (set! x 1). If instead of 1 you set x to 0 then it will result in zero. This is because the continuation variable cont which is storing the continuation is actually storing the continuation for y and not for x as it is being set to y's continuation after x's.

Variadic Function in Scheme

I have to define a variadic function in Scheme that takes the following form:
(define (n-loop procedure [a list of pairs (x,y)]) where the list of pairs can be any length.
Each pair specifies a lower and upper bound. That is, the following function call: (n-loop (lambda (x y) (inspect (list x y))) (0 2) (0 3)) produces:
(list x y) is (0 0)
(list x y) is (0 1)
(list x y) is (0 2)
(list x y) is (1 0)
(list x y) is (1 1)
(list x y) is (1 2)
Obviously, car and cdr are going to have to be involved in my solution. But the stipulation that makes this difficult is the following. There are to be no assignment statements or iterative loops (while and for) used at all.
I could handle it using while and for to index through the list of pairs, but it appears I have to use recursion. I don't want any code solutions, unless you feel it is necessary for explanation, but does anyone have a suggestion as to how this might be attacked?
The standard way to do looping in Scheme is to use tail recursion. In fact, let's say you have this loop:
(do ((a 0 b)
(b 1 (+ a b))
(i 0 (+ i 1)))
((>= i 10) a)
(eprintf "(fib ~a) = ~a~%" i a))
This actually get macro-expanded into something like the following:
(let loop ((a 0)
(b 1)
(i 0))
(cond ((>= i 10) a)
(else (eprintf "(fib ~a) = ~a~%" i a)
(loop b (+ a b) (+ i 1)))))
Which, further, gets macro-expanded into this (I won't macro-expand the cond, since that's irrelevant to my point):
(letrec ((loop (lambda (a b i)
(cond ((>= i 10) a)
(else (eprintf "(fib ~a) = ~a~%" i a)
(loop b (+ a b) (+ i 1)))))))
(loop 0 1 0))
You should be seeing the letrec here and thinking, "aha! I see recursion!". Indeed you do (specifically in this case, tail recursion, though letrec can be used for non-tail recursions too).
Any iterative loop in Scheme can be rewritten as that (the named let version is how loops are idiomatically written in Scheme, but if your assignment won't let you use named let, expand one step further and use the letrec). The macro-expansions I've described above are straightforward and mechanical, and you should be able to see how one gets translated to the other.
Since your question asked how about variadic functions, you can write a variadic function this way:
(define (sum x . xs)
(if (null? xs) x
(apply sum (+ x (car xs)) (cdr xs))))
(This is, BTW, a horribly inefficient way to write a sum function; I am just using it to demonstrate how you would send (using apply) and receive (using an improper lambda list) arbitrary numbers of arguments.)
Update
Okay, so here is some general advice: you will need two loops:
an outer loop, that goes through the range levels (that's your variadic stuff)
an inner loop, that loops through the numbers in each range level
In each of these loops, think carefully about:
what the starting condition is
what the ending condition is
what you want to do at each iteration
whether there is any state you need to keep between iterations
In particular, think carefully about the last point, as that is how you will nest your loops, given an arbitrary number of nesting levels. (In my sample solution below, that's what the cur variable is.)
After you have decided on all these things, you can then frame the general structure of your solution. I will post the basic structure of my solution below, but you should have a good think about how you want to go about solving the problem, before you look at my code, because it will give you a good grasp of what differences there are between your solution approach and mine, and it will help you understand my code better.
Also, don't be afraid to write it using an imperative-style loop first (like do), then transforming it to the equivalent named let when it's all working. Just reread the first section to see how to do that transformation.
All that said, here is my solution (with the specifics stripped out):
(define (n-loop proc . ranges)
(let outer ((cur ???)
(ranges ranges))
(cond ((null? ranges) ???)
(else (do ((i (caar ranges) (+ i 1)))
((>= i (cadar ranges)))
(outer ??? ???))))))
Remember, once you get this working, you will still need to transform the do loop into one based on named let. (Or, you may have to go even further and transform both the outer and inner loops into their letrec forms.)

Resources