Scheme Scoping (define and let) - scheme

So I know that in Scheme define is for dynamic scoping and let for static scoping, yet the following thing confuses me:
If I have
(let ((x 0))
(define f (lambda () x))
(display (f))
(let ((x 1))
(display (f))
)
)
It will display 00. So far so good. However, if I add an extra define for x like so:
(let ((x 0))
(define f (lambda () x))
(display (f))
(define x 4)
(let ((x 1))
(display (f))
)
)
It will display undefined4. Why is this? Why does defining x after evaluating f affect the returned value of (f)? And why is the return value "undefined"?
It is also worth mentioning that binding f with letrec instead of define will also work:
(let ((x 0))
(letrec ((f (lambda () x)))
(display (f))
(define x 4)
(let ((x 1))
(display (f))
)
)
)
Returns 00.
Note: I have used DrRacket with the languge set on "Pretty Big"

The issue you're experiencing in the second case is that (define x 42) makes x a variable for the entire scope in which it's defined. Now, although the variable is defined for the entire scope, its value is undefined until the actual (define x 42) line.
(let ()
;; up here, `x` is defined but has an undefined value
;; ...
(define x 42)
;; down here `x` has the value 42
;; ...
)
It's acting more like this:
(let ([x 'undefined])
;; ... up here, `x` is 'undefined
(set! x 42)
;; ... down here, `x` is 42
)

Your second and third code snippets are not Scheme (none of R5RS, R6RS nor R7RS). The <body> (of a let and others) is defined as:
<body> -> <definition>* <sequence>
<sequence> -> <command>* <expression>
<command> -> <expression>
and thus a define (which is a <definition>) cannot follow display (an <expression>). You are likely getting confusing results because the compiler/interpreter is incorrectly handling the expansion of 'let'.
Here is what a 'good' R6RS compiler does:
> (let ((x 0))
(letrec ((f (lambda () x)))
(display (f))
(define x 4)
(let ((x 1))
(display (f))
)
)
)
Unhandled exception
Condition components:
1. &who: define
2. &message: "a definition was found where an expression was expected"
3. &syntax:
form: (define x 4)
subform: #f
4. &trace: #<syntax (define x 4)>
>

Case 1: the body of f binds to the outermost let in both invocations, resulting in 00 as static scope requires.
Case 2: I'm not very sure about this, but the internal (define x 4) shadows the outermost x=0 binding, and is in scope throughout even though it's textually after the call to f. Then some order of evaluation trickiness makes the first call happen before the new x binding is fully initialized, so it's "uninitialized". The second call in the inner let happens after everything is initialized, so 4.
Case 3: Now that we have explicitly put the letrec and the define in separate scopes, f obviously refers to the outermost let. The define does nothing here.

Related

What Scheme special forms must the hygienic macro expander know about?

syntax-rules in Scheme are "hygienic" and "referentially transparent" and must preserve Scheme's lexical scoping. From my understanding, this means that during the macro expansion phase, the expander would need to know about lambda and define.
The expander needs to know about lambda.
Suppose we have this code:
(define x 1)
((lambda (x) x) 2)
If the expander did not know about the lambda special form, it would consider the two xs in (lambda (x) x) to be bound to the x in (define x 1), which is incorrect.
The expander needs to know about define, so that it knows where (i.e. in which scope) a particular identifier is defined. In addition, suppose we have this code:
(define n 1)
(define f (lambda (x y) (+ x y)))
(define lambda f)
(lambda n n)
In order to correctly determine that both n in (lambda n n) refer to (define n 1), the expander has to understand that (define lambda f) has changed the meaning of lambda (and therefore the expander has to stop using special rules for handling lmabda in this scope).
What other special forms does the macro expander need to know about? Does it need to know about set!?
The examples seem to be about lexical scoping, not macro expansion.
(define x 1)
((lambda (x) x) 2)
The binding of x in the second line shadows that in the first.
Similarly in the second example (define lambda f) binds lambda
in the region following the define; there is no macro expansion.
The identifier lambda can be used as a keyword in a syntactic extension (macro);
lexical scoping applies normally, there are no special rules:
> (let-syntax ([lambda (syntax-rules ()
[(lambda arg) ((lambda (x) (+ 1 x)) arg)])])
(lambda 2))
3
>
But:
> (letrec-syntax ([lambda (syntax-rules ()
[(lambda arg) ((lambda (x) (+ 1 x)) arg)])])
(lambda 2))
Exception: invalid syntax (lambda (x) (+ 1 x))
>

Lexical vs Dynamic interpreter in Scheme language

I still do not understand how a dynamic interpreter differ from a lexical one.
I am working on scheme and i find it very difficult to know how a simple code like these one works dynamically and lexically.
(define mystery
(let ((x 2018))
(lambda (y)
(let ((result (cons x y)))
(set! x (+ x 1))
result))))
any guidance?
Lexical bindings have limited visibility and unlimited lifespan. All functions "remember" environment, where they were created- that kind of functions is called lexical closures.
In your example, this part:
(let ((x 2018))
(lambda (y) (let ((result (cons x y)))
(set! x (+ x 1)) result))))
returns function, which remembers environment with x = 2018. That function is bind to symbol mystery and when you call it, it changes value of x in that environment.
> (mystery 1)
'(2018 . 1)
> (mystery 1)
'(2019 . 1)
In Scheme with dynamic bindings (unlimited visibility, limited lifespan), functions don't remember environment, where they were created. So, function mystery won't remember environment with x = 2018 and call (mystery 1) ends with error during evaluation of (cons x y), because symbol x has no value.
Lets just make a program with your code:
;; a global binding
(define x 100)
;; your function
(define mystery
(let ((x 2018))
(lambda (y)
(let ((result (cons x y)))
(set! x (+ x 1))
result))))
;; just to add newlines in prints
(define displayln
(lambda (v)
(display v)
(newline)))
;; a indirect call
(define local-test
(lambda (x)
(displayln x)
(displayln (mystery 'local))
(displayln (mystery 'local))
(displayln x)))
(define global-test
(lambda ()
(displayln x)
(displayln (mystery 'global))
(displayln (mystery 'global))
(displayln x)))
;; program
(local-test 1)
(local-test 11)
(global-test 1)
(global-test 11)
Results from a normal Scheme relies only on closures and not about the call stack bound variables:
1
(2018 local)
(2019 local)
1
11
(2020 local)
(2021 local)
11
1
(2022 global)
(2023 global)
1
11
(2024 global)
(2025 global)
11
Results from a dynamic "Scheme" has the let in mystery as dead code. It does nothing since the bindings are not saved with the function object. Thus only the variables in active let and calls are matched:
1
(1 local)
(2 local)
3
11
(11 local)
(12 local)
13
100
(100 global)
(101 global)
102
102
(102 global)
(103 global)
104
(define mystery
(let ((x 2018))
(lambda (y)
(let ((result (cons x y)))
(set! x (+ x 1))
result))))
This is a not a very good example to understand the difference between dynamic and static binding. It's merely a corner case.
The idea is, in static binding the free variables are associated with the static scope (the lexical code that is visible when writing) and in dynamic binding, they are associated with the dynamic code (what is stored on the execution stack).
Your code evaluates to a result that is this lambda expression:
(lambda (y)
(let ((result (cons x y)))
(set! x (+ x 1))
result))
In this result, the only free variable is X.
What is the value of X when you apply the result to a value for Y?
In static scoping, it will be 2018, in dynamic binding the value of X will be stored on the stack--for example,
(define X 100)
(define F (result 200)))
will apply result with a bound X=100 (X's will be kept on the stack). Of course, X's value is not physically kept on the stack, just a pointer to the environment frame where it is, or maybe in a value cell if a rerooting is performed on the environment, etc.
To understand your misunderstanding you can take a course of lambda calculus. And, of course, what I said here supposes you use the common interpretation, many other interpretations can be associated to the same syntax as your input example, etc.

How do I get a function's name as a symbol?

I am trying to define a function func->symbol that takes a function and returns its name as a symbol. For example:
(define (pythagoras a b)
(sqrt (+ (* a a) (* b b))))
;; #1
(func->symbol pythagoras) ; Returns: 'pythagoras
;; #2
(func->symbol (if #t pythagoras sqrt)) ; Returns: 'pythagoras
;; #3
(let ((f (if #t pythagoras sqrt)))
(func->symbol f)) ; Returns: 'pythagoras
;; #4
(let ((f (if #t pythagoras sqrt)))
(let ((g f))
(func->symbol g))) ; Returns: 'pythagoras
This is a follow-up question on How do I get a definition's name as a symbol? which only deals with case #1. For case #1, a simple macro def->symbol is sufficient:
(define-syntax def->symbol
(syntax-rules ()
((_ def) 'def)))
However, this macro definition does not pass cases #2, #3, #4. Is it possible to define func->symbol, or is Scheme not expressive enough for this?
In Racket, in many cases, you can get a function's name using object-name. But it is probably a bad idea to rely on this result for anything other than debugging.
Perhaps it's worth an answer which shows why this is not possible in any language with first-class functions.
I'll define what I mean by a language having first-class functions (there are varying definitions).
Functions can be passed as arguments to other functions, and returned as values from them.
Functions can be stored in variables and other data structures.
There are anonymous functions, or function literals.
Scheme clearly has first-class functions in this sense. Now consider this code:
(define a #f)
(define b #f)
(let ((f (lambda (x)
(+ x 1))))
(set! a f)
(set! b f))
Let's imagine there is a function-name function, which, given a function, returns its name. What should (function-name a) return?
Well, the answer is that there's simply no useful value it can return (in Racket, (object-name a) returns f, but that's clearly exposing implementation details which might be useful for debugging but would be very misleading as a return value for a function-name procedure.
This is why such a procedure can't exist in general in a language with first-class functions: the function which maps from names to values is many-to-one and thus has no inverse.
Here is an example of the sort of disgusting hack you could do to make this 'work' and also why it's horrible. The following is Racket-specific code:
(define-syntax define/naming
;; Define something in such a way that, if it's a procedure,
;; it gets the right name. This is a horrid hack.
(syntax-rules ()
[(_ (p arg ...) form ...)
(define (p arg ...) form ...)]
[(_ name val)
(define name (let ([p val])
(if (procedure? p)
(procedure-rename p 'name)
p)))]))
And now, given
(define/naming a
(let ([c 0])
(thunk
(begin0
c
(set! c (+ c 1))))))
(define/naming b a)
Then:
> (object-name a)
'a
> (object-name b)
'b
> (eqv? a b)
#f
> (a)
0
> (b)
1
> (a)
2
So a and b have the 'right' names, but because of that they are necessarily not the same object, which I think is semantically wrong: if I see (define a b) then I want (eqv? a b) to be true, I think. But a and b do capture the same lexical state, so that works, at least.

lexical scoping in scheme

I am trying to understand concepts of lexical and dynamic scoping and the differences between them.
Let's take a look at the following code:
(let ((a 1)
(b 2))
(letrec ((f (lambda () F))
(g (lambda (c) G)))
(lambda (d)
(+ (f) (g b)))))
For expressions F and G, which variables are at lexical scope of (lambda(d)...)?
(lambda(d)...) has d as bound variable and f, g a b and all of the global scope as free variables.
EDIT
Just to demonstrate the code in Scheme and some other language where the same bindings are dynamic. Since neither of your functions call each other you might as well keep them in the same let:
(define test
(let ((a 1)
(b 2)
(f (lambda () F))
(g (lambda (c) G)))
(lambda (d)
(+ (f) (g b)))))
;; for the test we need the F and G defined
(define F 10)
(define G 20)
(test 4) ; ==> 30 (aka (+ F G))
What happens is that when the lambda gets evaluated the variables it uses from the lexical scope lives on even after the let is gone. In a dymaic scope this isn't true:
(test 4)
; ERROR f: unbound identifier
The reason for this is while a, b, f and g existed when the lamba was evaluated none of the variables get captured like in lexical scope and thus when the procedure test is made none of the local variables exist anymore. In fact you might as well write it like this:
;; in a dynamic lisp this s the same
(define test
(lambda (d)
(+ (f) (g b))))
And you must make sure the variable exist when you call the function (aka dynamic)
(define g (lambda (v) 1337))
(define f (lambda () 3.1415927))
(define b 13)
(test 4) ; ==> 1340.1415927
Now if you were to add the above definitions in the global scope and keep the original definition you'd still get 30 since a lexical lisp uses the closer lexical bindings rather than the global ones.
Another great example is this:
(define x 10)
(define (test v)
(+ x v))
(let ((x 20))
(test 10))
; ==> ?
In a lexical lisp the result would be always 20 since test does not have any idea of the let since it is not in its lexical scope. It's x is always the global bindings x. In a dymamic lisp the x from the let is the closest one from the runtime point of view which would result in 30 since the x in test is the same as the x in the let and it shadows the global x.

evaluating my own functions from list with eval, R5RS

I am having problems with this
e.g. i have
(define (mypow x) (* x x))
and I need to eval expressions from given list. (I am writing a simulator and I get a sequence of commands in a list as an argument)
I have already read that R5RS standard needs to include in function eval as second arg (scheme-report-environment 5), but still I am having issues with this.
This works (with standard function):
(eval '(sqrt 5) (scheme-report-environment 5))
but this does not:
(eval '(mypow 5) (scheme-report-environment 5))
It says:
../../../../../../usr/share/racket/collects/racket/private/kw.rkt:923:25: mypow: undefined;
cannot reference undefined identifier
Eventhough simply called mypow in prompt returns:
#<procedure:mypow>
Any advice, please? (btw I need to use R5RS)
(scheme-report-environment 5) returns all the bindings that are defined in the R5RS Scheme standard and not any of the user defined ones. This is by design. You will never be able to do what you want using this as the second parameter to eval.
The report mentions (interaction-environment) which is optional. Thus you have no guarantee the implementation has it, but it will have all the bindings from (scheme-report-environment 5)
For completeness there is (null-environment 5) which only has the bindings for the syntax. eg. (eval '(lambda (v) "constan) (null-environment 5)) works, but (eval '(lambda (v) (+ 5 v)) (null-environment 5)) won't since + is not in the resulting procedures closure.
Other ways to get things done
Usually you could get away without using eval alltogether. eval should be avoided at almost all costs. The last 16 years I've used eval deliberately in production code twice.
By using a thunk instead of data:
(define todo
(lambda () ; a thunk is just a procedure that takes no arguments
(mypow 5))
(todo) ; ==> result from mypow
Now imagine you have a list of operations you'd like done instead:
(define ops
`((inc . ,(lambda (v) (+ v 1))) ; notice I'm unquoting.
(dec . ,(lambda (v) (- v 1))) ; eg. need the result of the
(square . ,(lambda (v) (* v v))))) ; evaluation
(define todo '(inc square dec))
(define with 5)
;; not standard, but often present as either fold or foldl
;; if not fetch from SRFI-1 https://srfi.schemers.org/srfi-1/srfi-1.html
(fold (lambda (e a)
((cdr (assq e ops)) a))
with
todo)
; ==> 35 ((5+1)^2)-1

Resources