Reputation: 17497
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
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