In terms of scope? Actual implementation in memory? The syntax? For eg, if (let a 1) Is \'a\' a variable or a symbol?
Quoting from the Common Lisp HyperSpec:
symbol n. an object of type symbol.
variable n. a binding in the “variable” namespace.
binding n. an association between a name and that which the name denotes. (…)
Explanation time.
What Lisp calls symbols is fairly close to what many languages call variables. In a first approximation, symbols have values; when you evaluate the expression x
, the value of the expression is the value of the symbol x
; when you write (setq x 3)
, you assign a new value to x
. In Lisp terminology, (setq x 3)
binds the value 3 to the symbol x
.
A feature of Lisp that most languages don't have is that symbols are ordinary objects (symbols are first-class objects, in programming language terminology). When you write (setq x y)
, the value of x
becomes whatever the value of y
was at the time of the assignment. But you can write (setq x 'y)
, in which case the value of x
is the symbol y
.
Conceptually speaking, there is an environment which is an association table from symbols to values. Evaluating a symbol means looking it up in the current environment. (Environments are first-class objects too, but this is beyond the scope of this answer.) A binding refers to a particular entry in an environment. However, there's an additional complication.
Most Lisp dialects have multiple namespaces, at least a namespace of variables and a namespace of functions. An environment can in fact contain multiple entries for one symbol, one entry for each namespace. A variable, strictly speaking, is an entry in an environment in the namespace of variables. In everyday Lisp terminology, a symbol is often referred to as a variable when its binding as a variable is what you're interested in.
For example, in (setq a 1)
or (let ((a 1)) ...)
, a
is a symbol. But since the constructs act on the variable binding for the symbol a
, it's common to refer to a
as a variable in this context.
On the other hand, in (defun a (...) ...)
or (flet ((a (x) ...)) ...)
, a
is a also symbol, but these constructs act on its function binding, so a
would not be considered a variable.
In most cases, when a symbol appears unquoted in an expression, it is evaluated by looking up its variable binding. The main exception is that in a function call (foo arg1 arg2 ...)
, the function binding for foo
is used. The value of a quoted symbol 'x
or (quote x)
is itself, as with any quoted expression. Of course, there are plenty of special forms where you don't need to quote a symbol, including setq
, let
, flet
, defun
, etc.