Scheme what are symbols good for and evaluate them - scheme

I'm quite new to scheme and I'm not so sure of something about quote and symbols.
Here is what I understand:
'a
-> a
'()
->(list)
'(1 2 3)
(list 1 2 3)
'(1 . 2)
(cons 1 2)
''a
(quote a)
So:
'(1 . 'a)
(1 quote a) => (list 1 quote a)
What I'd like to achieve is the following.
((let ((x 1) (y 2))
(lambda(f) ,f)) 'x)
-> 1
I send a symbol to the function and the symbol should be evaluated to the current scope which in this case would return 1.
Instead, I have this error:
*** ERROR IN #<procedure #4>, (console)#243.32 -- Unbound variable: unquote
It's as if unquote was only available from within quote itself.
EDIT
I was just reading some docs and found the function: "eval" which seems to do what I was looking for.
(define a 'foobar)
(define foobar 2)
(eval a)
-> 2
(define a 'x)
(define f (let ((x 1) (y 2))
(lambda (h) (eval h))))
(f a)
*** ERROR -- Unbound variable: y
(f y)
*** ERROR IN (console)#278.4 -- Unbound variable: y
But I'm not sure to really understand.
Here is a stacktrace in chicken
Error: unbound variable: x
Call history:
<syntax> (f (quote x))
<syntax> (quote x)
<syntax> (##core#quote x)
<eval> (f (quote x))
<eval> (eval h) <--
Edit2
Eval is Evil but I guess it's quite important to know how it works.
So after reading the answer of Ankur, I was pretty sure that it was a problem of scope and it is in fact it. So from what I understand, It appears that eval may be trying to evaluate anything using "globals".
> (define a 11)
> (define b 'a)
> (eval b)
11
> (let ((a 10)) (eval b))
11
> (let* ((a 10) (b 'a)) (eval b))
11
> (let* ((a 10) (b 'a)) b)
a
> (let* ((c 10) (d 'c)) d)
c
> (let* ((c 10) (d 'c)) (eval d))
*** ERROR -- Unbound variable: c
Eval in scheme is clearly evil!

It's as if unquote was only available from within quote itself.
Yes, you can only do unquoting inside a quoted expression as that is where only unquoting make sense, i.e you are quoting an expression (not want to evaluate the items in the expression) but want a specific part of the expression to be evaluated, in that case you use unquote.
(define a 10)
`(a b ,a) ==> '(a b 10)
In the last expression i want a and b to be unevaluated but the 3rd element i.e a should be evaluated and be replaced with its value hence we use unquote for that.
Your code:
(define f (let ((x 1) (y 2))
(lambda (h) (eval h))))
The param for f has to be an unevaluated expression because the param h is evalued using eval.
hence you need to use (f 'a).
NOTE: (f 'y) will not work because the scope of y which was created using let is gone.

For this case in particular you don't need to quote the expression to be evaluated, this will work:
(let ((x 1) (y 2))
((lambda (f) f) x))
=> 1
In the code in the question, be aware that the variable x only exists in the scope of the let that defined it; the outermost 'x symbol will only be that, a symbol with no relation to the x inside the let expression:
((let ((x 1) (y 2))
(lambda (f) f)) 'x)
=> 'x

Related

scheme: order of internal definition

It's a problem in SICP book ch4,here is the code
(let ((a 1))
(define (f x)
(define b (+ a x))
(define a 5)
(+ a b))
(f 10))
the error message is “a: undefined; cannot use before initialization”,if I use lambda expression
((lambda (a)
(define (f x)
(define a 5)
(define b (+ a x))
(+ a b))
(f 10)) 1)
still dont work,but if I write this as procedure define,like this
(define (f a)
(define (g x)
(define b (+ a x))
(+ a b))
(g 10))
(f 1)
it runs without error,but these two are basically the same right? why the let and lambda expression failed? thanks.
Because it refers to the inner a, not the one in the let:
(let ((a 1))
(define (f x)
(define b (+ a x)) ; `a` here refers to
(define a 5) ; **this one**
(+ a b))
(f 10))
Internal defines are all placed in one shared scope. It is done so we can define mutually recursive functions.
If you switch the order of the two defines it'll work (put a definition above the b definition) because then a will be initialized before being used in the b initialization, but only if you use #lang racket.
In #lang sicp the following works:
(let ((a 1))
(define (f x)
(define a 5)
(define b (lambda () (+ a x)))
(+ a (b)))
(f 10))

Both (funcall (lambda and (lambda worked

I am reading Simple-Lambda in elisp docs with an example
#+begin_src emacs-lisp :session sicp :lexical t
(funcall (lambda (a b c) (+ a b c))
1 (* 2 3) (- 5 4))
#+end_src
#+RESULTS:
: 8
the below works as well
#+begin_src emacs-lisp :session sicp :lexical t
((lambda (a b c) (+ a b c))
1 (* 2 3) (- 5 4))
#+end_src
#+RESULTS:
: 8
This confused me, elisp is lisp-2 style, so when evaluate (lambda (a b c) (+ a b c)), the interpreter will look into the block's cell for definition object, and thus the doc's demonstration make sense to invoke funcall
(funcall (lambda (a b c) (+ a b c))
1 (* 2 3) (- 5 4))
Nonetheless, it works without funcall?
((lambda (a b c) (+ a b c))
1 (* 2 3) (- 5 4))
Additionally, lambda is not of self-evaluating forms
It is common to write numbers, characters, strings, and even vectors
in Lisp code, taking advantage of the fact that they self-evaluate.
Elisp has a special case for lambda forms being called directly.
((lambda ...) ...)
As you've noted, that approach doesn't work in more general cases for other function-returning forms. It is also deprecated for this case where it does work, so it's best not to use it at all.
This syntax is covered briefly in (elisp)Function Indirection:
the following example calls a function without any
symbol function indirection, because the first element is an anonymous
Lisp function, not a symbol.
((lambda (arg) (erste arg))
'(1 2 3))
⇒ 1
Executing the function itself evaluates its body; this does involve
symbol function indirection when calling ‘erste’.
This form is rarely used and is now deprecated. Instead, you should
write it as:
(funcall (lambda (arg) (erste arg))
'(1 2 3))
or just
(let ((arg '(1 2 3))) (erste arg))

Error during macro expansion: Empty body #f

I'm learning Scheme and I can't figure out what I did wrong with this code:
(define (distance a b)
(define c 1)
(define loop
(lambda (a b c)
((if (<= c b)
(begin
(display (c (* a c)))
(newline)
(apply loop '(a b (+ c 1))))
'done)))))
I'm trying to make a program that takes in speed and hours, then displays the distance traveled for each hour on a separate line. When I run the code in an interpreter, I get an empty body error:
Error during macro expansion: Empty body #f
I'm running the code with the Larceny interpreter.
edit:
I rewrote the code to call the inside function loop from the body of the distance function and the code works perfectly. Updated code:
(define (distance a b)
(define c 1)
(define (loop x y z)
(if (<= z y)
(begin
(display "Hour: ")
(display z)
(display " Speed: ")
(display x)
(display " Distance: ")
(display (* x z))
(newline)
(loop x y (+ z 1)))
'done))
(loop a b c))
There seems to be a missing body. In Scheme a lambda is defined as
(lambda (args ...)
(define local-binding ...) ...
body ...)
In distance c and loop are local defines, but there is no body. Thus distance doesn't do anything with a or b and if it worked it would always return an undefined value. eg. not a very useful procedure.
When you'e fixed that you might want to have a look at My code signals the error “application: not a procedure” or “call to non procedure”

Scheme Scoping (define and let)

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.

Scheme rewrite let* as nested unary lets

I have written a function match-rewriter that is essentially match-lambda except that it returns its argument if no match is found:
(define-syntax match-rewriter
(syntax-rules ()
((_ (patt body) ...)
(λ (x) (match x (patt body) ... (_ x))))))
Now I would like to use match-rewriter to take strings representing source code for let* and rewrite it as nested unary lets:
(define let*→nested-unary-lets
(match-rewriter (`(let*((,<var> ,<val>) ...) ,<expr1> ,<expr2> ...)
I am really stumped over how to pattern match this. I need to return:
`(let((,<var1> ,<val1>)) let((,<var2> ,<val2>)) let((...)) ... )...) ,<expr1> . ,#<expr2>)
But the nesting has me stumped. Any advice is appreciated.
Okay, here is my best attempt:
(define let*→nested-unary-lets
(match-rewriter
(`(let* (()) ,<expr1> ,<expr2> ...)
(`(let () ,<expr1> . ,<expr2>)))
(`(let* ((,<var1> ,<val1>) (,<var2> ,<val2>) ...) ,<expr1> ,<expr2> ...)
`(let ((,<var1> ,<val1>) (let*→nested-unary-lets
'(let* ((,<var2> ,<val2>) ...) ,<expr1> . ,<expr2>)))))
))
But this is how it behaves:
(let*→nested-unary-lets '(let* ((a 1) (b (+ a 1)) (c (+ a b))) (displayln c)))
'(let ((a 1)
(let*→nested-unary-lets
'(let* (((b c) ((+ a 1) (+ a b)))
...)
(displayln c)))))
I am confused about the order of the arguments in:
(let* (((b c) ((+ a 1) (+ a b)))
It seems to me it should be:
(let* ((b (+ a 1)) (c (+ a b)))
Also, it would be nice if the call to let*→nested-unary-lets would execute instead of just printing as text.
Yes, you can do this; it shouldn't be too difficult. Specifically, the key idea you need here is not to try to handle the whole list at once. Instead, your patterns should separate the first binding from the rest, and then wrap one let around a recursive call to let*->nested-unary-lets.
Let me know if you have trouble formulating this.
Here is a definition of let* in syntax-rules-like pseudocode that you can use to write your own version:
(let* ((a b) (c d) ...) body ...) === (let ((a b)) (let* ((c d) ...) body ...))
(let* () body ...) === body
You should be able to turn that into a function using match or a macro using syntax-rules.

Resources