mike3996
mike3996

Reputation: 17497

Symbols quoted in Scheme

I'm no Scheme expert so not sure if I'm using the correct terminology here. Let the code speak for itself:

CSI> (define tree '(1 2 3 'Symb 4 5 6))
#<unspecified>
CSI> tree
(1 2 3 (quote Symb) 4 5 6)
CSI> (symbol? 'Symb)
#t
CSI> (map symbol? tree)
(#f #f #f #f #f #f #f)

Coming from Clojure background, I thought symbols were used like this in Scheme, like keywords in Clojure. I'm supposed to go through a nested list structure and replace symbols with a function call. This is my onedimensional solution and it does work:

(define (print-track track attrs)
    (apply fmt #t
        (map (lambda (attr)
               (cond 
                     ((symbol? attr) (get-attr attr track))
                     (else           attr)))
             attrs)))

The empty space above the (symbol?) line was for a (list?) conditional, but it's likely the wrong aproach.

I'm using Chicken Scheme.

Upvotes: 7

Views: 481

Answers (1)

Daniel Ralston
Daniel Ralston

Reputation: 2280

You've run into the Lisp quote "gotcha". In Scheme, symbols are used for variable reference, which you obviously understand. This evaluates to true:

> (symbol? 'Symb)

because you quoted the symbol, and prevented it from being used as a variable reference.

> (symbol? Symb)

Would first look up the value of the Symb variable, and then check if that value was a symbol.

> (let ((Symb 'foo)) (symbol? Symb))

Would evaluate to #t, since the value of Symb is a symbol: foo.

> (let ((Symb 7)) (symbol? Symb))

Would, of course, evaluate to #f.

You seem to have tripped on a nuance of quote.

'Symb

is actually shorthand; it's equivalent to

(quote Symbol)

which, again, returns its unevaluated argument.

But your code doesn't need the inner quote. When you

> (define tree '(1 2 3 'Symb 4 5 6))

the entire list is quoted; nothing inside of the list is going to be evaluated. That's why

> tree ; => (1 2 3 (quote Symb) 4 5 6)

Inside of the quoted list, 'Symb is equivalent to (quote Symb), which is actually a list. Since the whole list is quoted, using Symb unquoted would not be treated as a variable reference. It would just be the symbol.

> (define tree '(1 2 3 Symb 4 5 6))
> tree ; => (1 2 3 Symb 4 5 6)

Now, if you were passing all those arguments to the list function, what you originally did would be correct:

> (define tree (list 1 2 3 'Symb 4 5 6))
> tree ; => (1 2 3 Symb 4 5 6)

In that case, you're passing those arguments to a function; arguments to a function are evaluated, so you need quote to prevent symbols from being treated as variable references.

> (define tree (list 1 2 3 (quote Symb) 4 5 6))

Would do the same thing.

Upvotes: 19

Related Questions