scheme functions that "remember" values with let/set - scheme

I'm new to Scheme and trying to understand how certain values that appear within a function can persist across multiple uses. Take the following counter:
(define count
(let ((next 0))
(lambda ()
(let ((v next))
(set! next (+ next 1))
v))))
What I can't figure out (and haven't found explained anywhere), is why next doesn't get reset to 0 every time count is used.

This is called a closure. There's only one version of next in the whole program.
To make this clearer, consider the following program:
(define next 0)
(define count
(lambda ()
(let ((v next))
(set! next (+ next 1))
v))))
Now it's clear that there's only one next.
The version you wrote is different, because you've used let to make sure that only the lambda expression can see next. But there's still only one next. If you changed it to this, instead:
(define count
(lambda ()
(let ((next 0))
(let ((v next))
(set! next (+ next 1))
v))))
Then you would create a new version of next every time, because the declaration of next is inside the lambda, which means that it happens every time that lambda is called.

I have one thing to add to Sam's excellent answer: your question suggests that this behavior might have something to do with "let". It does not. Here's an example that does a similar thing without a "let" in it:
#lang racket
(define (make-counter-from counter)
(lambda ()
(set! counter (+ counter 1))
counter))
(define count (make-counter-from 9))
(count)
(count)
The moral (if there is one): Yes! Mutation is confusing!
EDIT: Based on your comment below, it sounds like you really are looking for some insight into what kind of mental model you can use for a language with mutation.
In a language with mutation of local variables, you can't use the simple "substitution" model that replaces arguments with values. Instead, each call to a function creates a new "binding" that can later be updated (a.k.a. "mutated").
So, in my code above, calling "make-counter-from" with 9 creates a new binding that associates the "counter" variable with the value 9. This binding is then attached/substituted-for all uses of the "counter" variable in the body of the function, including those inside of the lambda. The result of the function is then a lambda (a function) that is "closed over" two references to this newly created binding. You can think of these as two references to a heap-allocated object, if you like. This means that every call to the resulting function results in two accesses to this object/heap-thing.

I don't totally agree with your explanation. You're right in that the function's definition is evaluated only once, but the function itself is evaluated every time it is called.
The point I don't agree with is the "...rewrites the definition...", because the function is defined only once (and not explicitly overwritten).
I imagine it the following way: Due to the so-called lexical binding of variables in scheme, the scheme interpreter notices during the evaluation of the function definition that there's a variable defined in the environment of the function definition - the variable "next". Therefore it remembers not only the function definition, but the value of the variable "next", too (this means that it stores two things - the function definition and the enclosing environment). When the function in called for the first time, its definition is evaluated by the scheme interpreter within the stored environment (in which the variable "next" has the value 0, and were the value is incremented). The second time the function is called, exactly the same things happen - the same function definition is evaluated in its enclosing environment. This time, however, the environment provides the value 1 for the variable "next" and the result of the function call is 1.
To phrase is concisely: The function (definition) stays the same, it's the evaluation environment that changes.

To directly answer your question, "next doesn't get reset to 0 every time count is used" because your code
(define count (let ((next 0))
(lambda ()
(let ((v next))
(set! next (+ next 1))
v))))
is equivalent to
(define count #f)
(set! count ( (lambda (next) ; close over `next`
(lambda () ; and then return lambda which _will_
(let ((v next)) ; read from `next`,
(set! next (+ v 1)) ; write new value to `next`,
v))) ; and then return the previous value;
0 )) ; `next` is initially 0
(this is "let-over-lambda" pattern; there's even a Lisp book by that name).
The value to assign count is "calculated" only once. This value is a closure referring to the binding for next, which (binding) is external to it (the closure). Then every time count is "used", i.e. a procedure that it refers to is called, it (the procedure) refers to that binding: first it reads from it, then it alters its contents. But it doesn't re-set it to its initial value; the binding is initiated only once, as part of its creation, which happens when the closure is created.
This binding is visible only from this procedure. The closure is a bundle of this procedure and the environment frame holding this binding. This closure is the result of evaluating the (lambda () ...) expression inside the lexical scope of next, the (lambda (next) ...) expression.

Ok, I've had something of an epiphany. I believe my confusion relates to the distinction between a definition and a procedure (lambda): Definitions occur once, while procedures evaluate each time they are run. In the original function, let defines a procedure with next set to zero. That definition happens one time, but using set! within the procedure rewrites the definition as if retroactively. Thus, each use of count produces a new version of the function in which next has been incremented.
Please correct me if this is totally off-base.

Here is a program that does precisely the same thing.
(define count
(local ((define next 0)
(define (inc)
(local ((define v next))
(begin
(set! next (+ next 1))
v))))
inc))
(count) 0
(count) 1
(count) 2 .........
Maybe your let/set sequence follows the same mechanism. The procedure that you are actually calling is inc, not count. The inc procedure increments next every time. An equivalent definition can be
(define next 0)
(define (inc)
(begin
(set! next (+ next 1))
(- next 1)))
(define count inc)
(count) 0
(count) 1
(count) 2......
So, I guess calling count in the first program is just like running the entire second program. I don't know. I too am new to scheme. Thanks, for the useful post.

Related

Scheme returns <#Closure> instead of 1

I have just start to pick up scheme and figuring out its ins and outs. I was trying to work out some practice problems and I came across this one. With my-counter defined, I thought calling my-counter would return 1, but instead it's returning <#Closure>. I understand to some extent what closures are and thought that count belongs to let, so it would return 1, but I supposed I overlooked something.
(define my-counter
(let ((count 0))
(lambda ()
(set! count (+ count 1))
count)))
my-counter returns a procedure. You need to call that procedure to get the next value.
(define counter-1 (my-counter))
(define counter-2 (my-counter))
(write (counter-1))
(write (counter-1))
(write (counter-2))

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)

Why does make-counter procedure contains two lambda definition?

I'm trying to understand the scheme code of make-counter procedure. It's a higher order procedure (a procedure outputs another procedure) and I'm stuck with it.
(define make-counter
(lambda (n)
(lambda ()
(set! n (+ n 1))
n)))
(define ca (make-counter 0))
(ca)
(ca)
This outputs 1 and 2 respectively as expected. Why do we need 2 nested procedures here? What are their functions individually?
I'd be appreciated if someone explains in details. Thanks from now on.
Indented properly, this is:
(define make-counter
(lambda (n)
(lambda ()
(set! n (+ n 1))
n)))
By the way, you can use a different syntax:
(define (make-counter n)
(lambda ()
(set! n (+ n 1))
n))
make-counter is a function that accepts a number n and returns an object called closure, which acts like a function but contains a state. Different invocations of make-counter will produce different closures, even when given the same n in argument. A closure can be called using the function-call syntax, as you experimented.
When you call the closure, the code that is contained within is executed. In your example, the closure accepts zero arguments, and mutates the variable named n. Again, the binding from n to a value is local to the closure and different for all instances of counters. But inside a particular counter, n always refer to the same memory location.
A call to the set! function changes what n evaluates to, and replaces the previous value with (+ n 1), incrementing the local counter variable.

How does a closure occur in this scheme snippet?

I'm having some trouble deciphering this code snippet.
(define (stream n f)
(define (next m)
(cons m (lambda () (next (f m)))))
(next n))
(define even (stream 0 (lambda (n) (+ n 2))))
I understand that 'even' is defined as a variable using the 'stream' function, which contains parameters 0 and '(lambda (n) (+ n 2))'. Inside of 'stream', wouldn't '(next n)' indefinitely create cons nodes with a car of n + 2? Yet when I return 'even', it is a cons of (0 . # < Closure>). Could someone be so kind as to explain why this is? Thanks!
Everytime (lambda ...) is evaluated it becomes a closure. What it means is that f is free and available for both procedures next and for the anonymous procedure it creates. m, which is a bound variable in next is also captured as a free variable in the anonymous procedure. If the language were dynamically bound none of them would exist if you called the resulting procedure in the cdr since the bindings would no longer exist, but since we have closures the variable exists even after the procedures that created them ended.
The pair returned by the stream procedure has references to the closure created when (lambda (n) (+ n 2)) was evaluated though the name f even though the call is finished. Thus if you do:
((cdr even)) ; ==>
(#<closure>) ; ==>
(cons 2 #<new-closure>) ; ==> Here
It's important to know that the evaluation of next becomes a pair with a new closure that has a new free variable m that is 2 this time. For each time you call the cdr it creates a new pair with a new closure. If it was the same each time you wouldn't have different result each iteration.
A lambda on it's own doesn't run the code in it's body. Thus instead of infinite recursion you only get one step and the result (cons 2 #<new-closure>). You need to call the cdr of this again ni order to get one more step. etc. Likewise if I did this:
(define (test a)
(define (helper b)
(+ a b))
helper) ; return the helper that has a as closure variable
Since we actually don't use the name one could just have anonymous lambda there instead of the define + the resulting variable. Anyway, you get something that gives you partially application:
((test 5) 2) ; ==> 7
(define ten-adder (test 10))
(ten-adder 2) ; ==> 12
(ten-adder 5) ; ==> 15

Name of this state representation idea without local variables

I know this is maybe an oddball idea, but I thought might as well give it a try to ask here.
I was experimenting in Racket about state representation without local variables.
The idea was defining a function that prints it's parameter value and if called again gives me another value. Since pure functions called with the same parameter always produce the same result, my workaround-idea got me the following.
(define (counter n)
(displayln n)
(λ () (counter (add1 n)))) ; unapplied lambda so it doesn't go in a loop
Then I devised a function to call counter and its resulting lambdas a certain number of times.
(define (call proc n)
(unless (zero? n)
(let ([x (proc)])
(call x (sub1 n)))))
Which results in this:
> (call (counter 0) 5)
0
1
2
3
4
5
What is the name for the concept applied here? Propably it's something trivial what you need in real applications all the time, but since I have no experience in that respect yet so I can't pinpoint a name for it. Or maybe I just complicated something very simple, but nonetheless I would appreciate an answer so I can look further into it.
Sorry if my question is not clear enough, but english is not my first language and to ask about things I have no name for makes me feel kinda uncertain.
You're using closures to save state: a lambda form stores the environment in which it was defined, and you keep redefining the procedure (called x in your code), so each time it "remembers" a new value for n.
Another way to do the same would be to let the procedure itself keep track of the value - in other words, counter should remember the current n value between invocations. This is what I mean:
(define (counter initial)
(let ((n (sub1 initial)))
(lambda ()
(set! n (add1 n))
n)))
In the above code, the first invocation of counter returns a new lambda that closes over n, and each invocation of that lambda modifies n and returns its new value. Equivalently, we could use Racket-specific syntax for currying and the begin0 special form to achieve the same effect:
(define ((counter n))
(begin0
n
(set! n (add1 n))))
Either way, notice how the procedure "remembers" its previous value:
(define proc (counter 0))
(proc)
=> 0
(proc)
=> 1
And we would call it like this:
(define (call proc n)
(unless (zero? n)
(displayln (proc))
(call proc (sub1 n))))
(call (counter 0) 5)
=> 0
1
2
3
4
Also notice that the above fixes an off-by-one error originally in your code - the procedure was being called six times (from 0 to 5) and not five times as intended, that happened because call invokes counter five times, but you called counter one more time outside, when evaluating (counter 0).

Resources