In terms of scope? Actual implementation in memory? The syntax? For eg, if (let a 1) Is \'a\' a variable or a symbol?
Jörg's answer points in the right direction. Let me add a bit to it.
I'll talk about Lisps that are similar to Common Lisp.
Symbols as a data structure
A symbol is a real data structure in Lisp. You can create symbols, you can use symbols, you can store symbols, you can pass symbols around and symbols can be part of larger data structures, for example lists of symbols. A symbol has a name, can have a value and can have a function value.
So you can take a symbol and set its value.
(setf (symbol-value 'foo) 42)
Usually one would write (setq foo 42)
, or (set 'foo 42)
or (setf foo 42)
.
Symbols in code denoting variables
But!
(defun foo (a)
(setq a 42))
or
(let ((a 10))
(setq a 42))
In both forms above in the source code there are symbols and a
is written like a symbol and using the function READ
to read that source returns a symbol a
in some list. But the setq
operation does NOT set the symbol value of a
to 42
. Here the LET
and the DEFUN
introduce a VARIABLE a
that we write with a symbol. Thus the SETQ
operation then sets the variable value to 42
.
Lexical binding
So, if we look at:
(defvar foo nil)
(defun bar (baz)
(setq foo 3)
(setq baz 3))
We introduce a global variable FOO
.
In bar the first SETQ
sets the symbol value of the global variable FOO
. The second SETQ
sets the local variable BAZ
to 3
. In both case we use the same SETQ
and we write the variable as a symbol, but in the first case the FOO
donates a global variable and those store values in the symbol value. In the second case BAZ
denotes a local variable and how the value gets stored, we don't know. All we can do is to access the variable to get its value. In Common Lisp there is no way to take a symbol BAZ
and get the local variable value. We don't have access to the local variable bindings and their values using symbols. That's a part of how lexical binding of local variables work in Common Lisp.
This leads for example to the observation, that in compiled code with no debugging information recorded, the symbol BAZ
is gone. It can be a register in your processor or implemented some other way. The symbol FOO
is still there, because we use it as a global variable.
Various uses of symbols
A symbol is a data type, a data structure in Lisp.
A variable is a conceptual thing. Global variables are based on symbols. Local lexical variables not.
In source code we write all kinds of names for functions, classes and variables using symbols.
There is some conceptual overlap:
(defun foo (bar) (setq bar 'baz))
In the above SOURCE code, defun
, foo
, bar
, setq
and baz
are all symbols.
DEFUN
is a symbol providing a macro.
FOO
is a symbol providing a function.
SETQ
is a symbol providing a special operator.
BAZ
is a symbol used as data. Thus the quote before BAZ
.
BAR
is a variable. In compiled code its symbol is no longer needed.