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.
Symbols in Scheme are widely used in three ways: as items of discrete data, as lookup keys for alists and hash tables, and to denote variable references. Looking beyond how they are written, symbols are different from strings in two important respects. The first important difference is uniqueness.
Scheme provides a cleaner way of writing quote d expressions, using the special single-quote character ' . Rather than writing out (quote some-expression ) , you can just precede the quoted expression with the single-quote character. For example, we can write the same definition of foo as (define foo '(1 2 3)) .
If a comma appears followed immediately by an at-sign (@), then the following expression must evaluate to a list; the opening and closing parentheses of the list are then "stripped away" and the elements of the list are inserted in place of the comma at-sign expression sequence.
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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With