elisp: capturing variable from inner function - elisp

My lovely function:
(defun f (x)
(lambda (y) (+ x y)))
Then, I expect this:
(funcall (f 2) 2)
To return 4. But alas, I got this instead:
Debugger entered--Lisp error: (void-variable x)
So how can I capture variable from inner function?

You've been bitten by elisp's dynamic scoping. The x in the lambda refers to the variable x that is in scope when the lambda is called (and since in this case there is no x in scope when you call it, you get an error), not to the x which is in scope when you create the lambda.
Some ways of simulating lexical closures in elisp are explained on this page on the EmacsWiki.

Related

dynamic scope returns undefined var

The code below, under dynamic scope assumption, would return error.
(let ((f (lambda (g)
(lambda (n)
(if (zero? n)
1
(* n ((g g) (- n 1))))))))
((f f) 5))
My answer was 0, because:
n*(n-1)*(n-2)*(n-3)*(n-3)*(n-4)*1;; since the call with n=0, n bound to 0
0*0*0*0*1
What am I missing here?
(define test
(let ((x 10))
(lambda () x)))
Here we return lambda function from the scope where x is a local variable. Under lexical scope an environment gets attached to the created lambda function. This environment consists of the bound variables on top of the free variables that were available when the lambda function was being created -- here, x, bound to 10. Thus when this returned lambda function is called, its x can only be 10.
In dynamic scope the let is dead code. The lambda function that is created does not store its lexical environment and thus when it will be called, x will be looked up fresh, at the actual time of the call. The variable that was called x with value 10 will no longer exist by then. The x looked up by the lambda will be whatever you have x bound to, at the call time:
(let ((x 20))
(test))
; ==> 20
And of course:
(test); == ERROR: Unbound variable x
So to your code it's the same problem. Whatever g is when (lambda (n) ...) is evaluated, creating the lambda function, goes out of scope when that lambda function is returned, and thus when that returned lambda function is called, g will be looked up fresh, and will be whatever g is bound to at the time of calling, as before. In order for this to work in a dynamic scope you could do this:
(let ((f (lambda (g n)
(if (zero? n)
1
(* n (g g (- n 1)))))))
(f f 5))
The difference here is that g never goes out of scope. This works in both dynamic and lexical scope. You can simplify it for dynamic scope like this:
(let ((f (lambda (n) ; ((lambda (f) (f 5))
(if (zero? n) ; (lambda (n)
1 ; (if (zero? n)
(* n (f (- n 1))))))) ; 1
(f 5)) ; (* n (f (- n 1))))))
In lexical scope the f inside (lambda (n) ...) is unbound variable, but in a dynamic scope f is first established, and after the call (f 5) it remains available for all the nested calls, (f 4), (f 3) etc., until the evaluation of (f 5) inside (lambda (f) (f 5)) is finished; only then that f is disestablished, destroyed, when that lambda is exited returning the result of (f 5).
In Paul Grahams nice wrap-up of McCarthys original lisp paper he mentions that there was a bug in the paper. The very first higher order function, maplist, had x as the name for the list argument. In the demonstration diff he passes a function to maplist that has x as a parameter. These two collide after the first pair and thus it does not work because of dynamic scope. Dynamic scope is extremely error prone and in Common Lisp where all globals are dynamic, the *earmuffs* naming convention is a necessity to avoid countless hours finding the global that changed the function to do something completely different than expected.
Using dynamic scope, g will be undefined because there is no variable named g on line 6.

analysis of higher orden function in Scheme

I found the following code about Higher Order Functions in Scheme:
(define make-double (lambda (f)
(lambda (x)
(f x x))))
(define square (make-double *))
For what I see make-double receives as an argument a function:f, and this function receives and x as argument. This argument x is doubled and make-double return the function f with this x value doubled. Is it like that?
The call to the function square is straightforward, just call the function make-double and the function *, but how can I run this program? When I execute it with:
square
It returns to me:
(lambda (x) (f x x))
How to interpret that? I suppose this function allowed to print an element twice, but maybe I am mistaken? Any help?
Try evaluating (square 42). :-)
Typing square just prints the value of square, which is a function.
(lambda (x) (f x x))
Tells you that square is a function accepting one argument, whose value will be used as both arguments of the function bound by f, which is in this case is *.

Scheme: append to local environment

Say, I want to implement "declarative" object system in Scheme by defining object symbol and then appending methods and fields to that object. While doing so, I want to exploit the local environment of this object to properly bind it's fields in methods (which are added later), for instance (a very "hacked-together" example):
(define myobj
(begin
(define x 5) ; some local field (hard-coded for example)
(define (dispatch m d)
(cond ((eq? m 'add-meth) (define localmethod1 d))
((eq? m 'inv-meth) (localmethod1 d))))
dispatch
))
(myobj 'add-meth (lambda (y) (+ y x)) ;want this to bind to x of myobj
(myobj 'inv-meth 3) ;8
Don't mind silly dispatching mechanism and hard-coded "localmethod1" :) Also do mind, that x may not be available during definition of dispatcher.
First of all, I get problems with using define in define (Bad define placement).
Then: how to make sure that x in lambda binds to the right one (inside of myobj) and not to some x in global environment?
Last: Is there a way to mutate such local enivornments (closures, right?) at all?
EDIT2: I know that you can make this with local lists like "fields" and "methods" and then mutate those by a dispatcher. I wanted to know if there is a possibility of mutating local environment (produced by a dispatch lambda).
begin in Scheme does not produce local environment. To introduce local variables use let. Or, alternatively define an object, or rather a class to construct the object, as lambda-procedure, that will act as a constructor. This will solve your first two problems.
To mutate: you can mutate by having a right dispatch method. For example,
(define (make-object init-val)
(define x init-val)
(define (dispatch msg)
(cond ((eq? msg 'inc)
(lambda (y)
(set! x (+ x y))))
((eq? msg 'x)
x)
(else
(error "Unknown msg"))))
dispatch)
> (define obj (make-object 10))
> (obj 'x)
10
> ((obj 'inc) 20)
> (obj 'x)
30
SICP, Chapter 3 provides good examples of how to make objects with local state.
You are saying:
x may not be available during definition of dispatcher
and then you are asking:
Then: how to make sure that x in lambda binds to the right one (inside of myobj) and not to some x in global environment?
The short answer is: you can't.
The reason is that (see for instance the Mit-Scheme manual):
Scheme is a statically scoped language with block structure. In this respect, it is like Algol and Pascal, and unlike most other dialects of Lisp except for Common Lisp.
The fact that Scheme is statically scoped (rather than dynamically bound) means that the environment that is extended (and becomes current) when a procedure is called is the environment in which the procedure was created (i.e. in which the procedure's defining lambda expression was evaluated), not the environment in which the procedure is called. Because all the other Scheme binding expressions can be expressed in terms of procedures, this determines how all bindings behave.
(emphasis mine)

Using 'define' in Scheme

I'm new to Scheme and was just curious about 'define'. I've seen things like:
(define (square x) (* x x))
which makes sense [Function name 'square' input parameter 'x']. However, I found some example code from the 90's and am trying to make sense of:
(define (play-loop-iter strat0 strat1 count history0 history1 limit) (~Code for function~)
Except for the function name, are all of those input parameters?
Short answer - yes, all the symbols after the first one are parameters for the procedure (the first one being the procedures's name). Also it's good to point out that this:
(define (f x y)
(+ x y))
Is just syntactic sugar for this, and both forms are equivalent:
(define f
(lambda (x y)
(+ x y)))
In general - you use the special form define for binding a name to a value, that value can be any data type available, including in particular functions (lambdas).
A bit more about parameters and procedure definitions - it's good to know that the . notation can be used for defining procedures with a variable number of arguments, for example:
(define (f . x) ; here `x` is a list with all the parameters
(apply + x))
(f 1 2 3 4 5) ; 0 or more parameters can be passed
=> 15
And one final trick with define (not available in all interpreters, but works in Racket). A quick shortcut for defining procedures that return procedures, like this one:
(define (f x)
(lambda (y)
(+ x y)))
... Which is equivalent to this, shorter syntax:
(define ((f x) y)
(+ x y))
((f 1) 2)
=> 3
Yes, strat0 through limit are the parameters of the play-loop-iter function.
The general form for define is:
(define (desired-name-of-procedure item-1 item-2 item-3 ... item-n)
(; what to do with the items))
Another way to explain the behaviour of define, is in terms of "means of combination", and "means of abstraction".
[A] The means of combination in simple terms:
The syntax (item-1 item-2 item-3 ... ... item-n) is the fundamental means of combination provided by Scheme (and Lisp in general.)
All code is a list represented using the above pattern
The very first (leftmost) item is always treated as an operator
Parentheses enforce the application of the operator... The leftmost item is required to accept all the items that follow, as arguments
[B] means of abstraction is simply; a way to name things.
An example will demonstrate how this all folds into the idea of the define primitive...
Example--Arriving at define in a bottom-up way
Consider this expression:
(lambda (x y) (* x y))
In plain English, the above expression translates to "Create a nameless procedure that accepts two arguments, and returns the value of the their product". Note that this generates a nameless procedure.
More accurately, in terms of means of combination, Scheme provides us the keyword lambda as a primitive operator that creates user-defined procedures.
The leftmost item--lambda--is passed items (x y) and (* x y) as arguments, and the operator-application rule forces lambda to do something with the items.
The way lambda is defined internally causes it to parse the list (x y), and treat x and y as arguments to pass to the list (* x y), which lambda assumes is the user's definition of what to do when arguments x and y are encountered. Any value assigned to x and y will be processed in accordance with the rule (* x y).
Enter, means of abstraction...
Suppose I wanted to refer to this type of multiplication at several places in my program, I might tweak the above lambda expression like this:
(define mul-two-things (lambda (x y) (* x y)))
define takes mul-two-things and the lambda expression as arguments, and "binds" them together. Now Scheme knows that mul-two-things should be associated with a procedure to take two arguments and return their product.
As it happens, the requirement of naming procedures is so very common and provides so much power of expression, that Scheme provides a cleaner-looking shortcut to do it.
Like #oscar-lopez says, define is the "special form" Scheme provides, to name things. And as far as Scheme's Interpreter is concerned, both the following definitions are identical:
(define (mul-two-things x y) (* x y))
(define mul-two-things (lambda (x y) (* x y))

Why does Scheme allow mutation to closed environment in a closure?

The following Scheme code
(let ((x 1))
(define (f y) (+ x y))
(set! x 2)
(f 3) )
which evaluates to 5 instead of 4. It is surprising considering Scheme promotes static scoping. Allowing subsequent mutation to affect bindings in the closed environment in a closure seems to revert to kinda dynamic scoping. Any specific reason that it is allowed?
EDIT:
I realized the code above is less obvious to reveal the problem I am concerned. I put another code fragment below:
(define x 1)
(define (f y) (+ x y))
(set! x 2)
(f 3) ; evaluates to 5 instead of 4
There are two ideas you are confusing here: scoping and indirection through memory. Lexical scope guarantees you that the reference to x always points to the binding of x in the let binding.
This is not violated in your example. Conceptually, the let binding is actually creating a new location in memory (containing 1) and that location is the value bound to x. When the location is dereferenced, the program looks up the current value at that memory location. When you use set!, it sets the value in memory. Only parties that have access to the location bound to x (via lexical scope) can access or mutate the contents in memory.
In contrast, dynamic scope allows any code to change the value you're referring to in f, regardless of whether you gave access to the location bound to x. For example,
(define f
(let ([x 1])
(define (f y) (+ x y))
(set! x 2)
f))
(let ([x 3]) (f 3))
would return 6 in an imaginary Scheme with dynamic scope.
Allowing such mutation is excellent. It allows you to define objects with internal state, accessible only through pre-arranged means:
(define (adder n)
(let ((x n))
(lambda (y)
(cond ((pair? y) (set! x (car y)))
(else (+ x y))))))
(define f (adder 1))
(f 5) ; 6
(f (list 10))
(f 5) ; 15
There is no way to change that x except through the f function and its established protocols - precisely because of lexical scoping in Scheme.
The x variable refers to a memory cell in the internal environment frame belonging to that let in which the internal lambda is defined - thus returning the combination of lambda and its defining environment, otherwise known as "closure".
And if you do not provide the protocols for mutating this internal variable, nothing can change it, as it is internal and we've long left the defining scope:
(set! x 5) ; WRONG: "x", what "x"? it's inaccessible!
EDIT: your new code, which changes the meaning of your question completely, there's no problem there as well. It is like we are still inside that defining environment, so naturally the internal variable is still accessible.
More problematic is the following
(define x 1)
(define (f y) (+ x y))
(define x 4)
(f 5) ;?? it's 9.
I would expect the second define to not interfere with the first, but R5RS says define is like set! in the top-level.
Closures package their defining environments with them. Top-level environment is always accessible.
The variable x that f refers to, lives in the top-level environment, and hence is accessible from any code in the same scope. That is to say, any code.
No, it is not dynamic scoping. Note that your define here is an internal definition, accessible only to the code inside the let. In specific, f is not defined at the module level. So nothing has leaked out.
Internal definitions are internally implemented as letrec (R5RS) or letrec* (R6RS). So, it's treated the same (if using R6RS semantics) as:
(let ((x 1))
(letrec* ((f (lambda (y) (+ x y))))
(set! x 2)
(f 3)))
My answer is obvious, but I don't think that anyone else has touched upon it, so let me say it: yes, it's scary. What you're really observing here is that mutation makes it very hard to reason about what your program is going to do. Purely functional code--code with no mutation--always produces the same result when called with the same inputs. Code with state and mutation does not have this property. It may be that calling a function twice with the same inputs will produce separate results.

Resources