1

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!

ProgramFOX
  • 6,131
  • 11
  • 45
  • 51
Loïc Faure-Lacroix
  • 13,220
  • 6
  • 67
  • 99
  • 2
    If the answer to your question is **eval**, you're almost always doing at wrong. If you're new to Scheme, that goes up to 100% probability. – itsbruce Nov 09 '12 at 08:39
  • @itsbruce For that reason, its even more important to know how it works. Not that I would use it but I don't always read the code I write myself. – Loïc Faure-Lacroix Nov 10 '12 at 16:22

2 Answers2

1

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
Óscar López
  • 232,561
  • 37
  • 312
  • 386
  • I update my question. Thank for the fast answer. I updated using eval. Since the x and y should be only available from within the let. I believed that using eval should actually do the eval from within the let and finding a bounded x or y. – Loïc Faure-Lacroix Nov 08 '12 at 22:49
  • Mmm, what exactly do you need? it seems to me that you're trying to fit a square peg in a round hole, there probably is a simpler way to achieve what you need without that much complexity. Oh, and [eval() is evil](http://stackoverflow.com/questions/2571401/why-exactly-is-eval-evil). – Óscar López Nov 08 '12 at 23:00
  • I'm just learning scheme. One of the use would be to access function stored in an association list. Or a hashtable. But my guess is that it would be faster to do within the hashtable storing symbols only or actual text. I'm giving a lecture of 80 minutes in 10 days and trying to find enough things to talk about. – Loïc Faure-Lacroix Nov 08 '12 at 23:06
  • Well, for that you don't need to dynamically evaluate a symbol and replace its value in an expression. Just use a variable, like in the first snippet in my answer - keep it simple! – Óscar López Nov 08 '12 at 23:12
1
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.

Ankur
  • 33,367
  • 2
  • 46
  • 72
  • I guessed the problem was related to `eval`. I updated my question. Apparently eval is using global scoped variables. Even if you're using it within a different scope It might not even try to use them. I might be wrong about how scoping works in scheme. – Loïc Faure-Lacroix Nov 10 '12 at 16:26
  • Also, I'm not sure to understand what's the point to have `(a b ,a). I understand what result it gives. It will give a list with a b and 10. That said since a and b aren't evaluated here, how can I use that without using eval. – Loïc Faure-Lacroix Nov 11 '12 at 00:57