You all know the story: programmer reads other people's code, programmer sees symbol they don't understand, Google fails them because it's difficult to search for non-alphanumeric symbols.
This time it's the @
symbol, which seems to be used to inject the contents of one list into the middle of another. For instance:
`(5 6 7 ,@'(8 9) 10 11)
;=> (5 6 7 8 9 10 11)
I'm comfortable with this usage, but I'm wondering whether I understand the behavior of @
correctly? Does it have other uses? And what causes the error in the following transcript (from CLISP)?
[1]> (list 1 2 3 4 @'(5 6 7))
*** - SYSTEM::READ-EVAL-PRINT: variable @ has no value
Lastly, what exactly is @
? It doesn't seem to be a function:
[3]> (print #'@)
*** - FUNCTION: undefined function @
I'm guessing it's a fundamental syntax like the backquote (`
), or comma (,
). Is this correct? Sorry if this is a duplicate, but once again, as far as I know it's impossible to search for @
.
A Lisp symbol is a data object that has three user-visible components: The property list is a list that effectively provides each symbol with many modifiable named components. The print name must be a string, which is the sequence of characters used to identify the symbol.
LISP expressions are called symbolic expressions or s-expressions. The s-expressions are composed of three valid objects, atoms, lists and strings. Any s-expression is a valid program. LISP programs run either on an interpreter or as compiled code.
#'functionname in Common Lisp Above defines a local variable FOO and a local function FOO . The list statement returns the value of FOO , then the function value of foo using the (function ...) notation, then the same using the short hand notation and then the value of actually calling the function FOO .
In Lisp, every symbol has a property list (plist). When a symbol is created initially its property list is empty. A property list consists of entries where every entry consists of a key called an indicator and a value called a property . There are no duplicates among the indicators.
It's described in the HyperSpec in the section on backquote:
2.4.6 Backquote
If a comma is immediately followed by an at-sign, then the form following the at-sign is evaluated to produce a list of objects. These objects are then “spliced” into place in the template. For example, if
x
has the value(a b c)
, then`(x ,x ,@x foo ,(cadr x) bar ,(cdr x) baz ,@(cdr x)) => (x (a b c) a b c foo b bar (b c) baz b c)
It's worth noting that ,@
isn't always necessary; according to the same documentation:
Anywhere “,@” may be used, the syntax “,.” may be used instead to indicate that it is permissible to operate destructively on the list structure produced by the form following the “,.” (in effect, to use nconc instead of append).
Your intuition is mostly correct when you ask, "so basically @ on its own means nothing and the only real operator is ,@?" @
can be used in other places as a normal letter. That's why you get the error that you mentioned: (list 1 2 3 4 @'(5 6 7))
is simply
(list 1 2 3 4 @ '(5 6 7))
and @
is a variable, but it doesn't have a value here. Compare that with:
(let ((@ 4.5))
(list 1 2 3 4 @ '(5 6 7)))
;=> (1 2 3 4 4.5 (5 6 7))
Sorry if this is a duplicate, but once again, as far as I know it's impossible to search for "@".
Searching for documentation on certain non-alphanumeric characters can be difficult, but I've found a few techniques that can help. E.g., if you go to lispdoc.com, you can search for comma
, and the results there will get you headed toward backquote. (Searching for at-sign didn't help though.) That's not a perfect solution, but it can help sometimes.
,@
should be considered a single entity, and the meaning of ,@
is that the following expressions is spliced into the current quasi-quoted list.
For example you cannot use
`,@x
because the quasi-quoted expression is not a list and ,@
requires a list to be spliced to.
Similarly (in my reading of the standard) you cannot use
`(list ,@5)
because 5
is not a list (however both SBCL and CLISP allow it and expand to (list . 5)
).
Actually the behavior of SBCL and CLISP is acceptable, but it would also be acceptable for a compliant implementation to give an error if ,@
is used with a non-list argument.
CLHS section 2.4.6 last possible expansion for `((,a b) ,c ,@d)
shows that raising an error for a non-list could be acceptable too.
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