Reputation: 257
Please see this example. I am using GNU CLISP 2.49.
(defparameter *pudding-eater* 'henry')
;; output:
READ from
#<INPUT CONCATENATED-STREAM #<INPUT STRING-INPUT-STREAM> #<IO TERMINAL-STREAM>>: an
object cannot start with #\)
(defparameter *pudding-eater* 'henry)
;; output:
*PUDDING-EATER*
I do understand that it is the double quotes that are causing the problem. What I do not understand is that, what does an object cannot start with #\)
mean? Where did I start with #\)
? I was expecting some error message like umatched parenthesis
.
Upvotes: 3
Views: 4073
Reputation: 38789
As other answers pointed out, #\(
is the syntax to represent the (
character. See section 2.4.8 Sharpsign. First the reader sees #
, then dispatches on the next character, \
(backslash) which is used to read character objects. Your error message is thus saying that )
was unexpected in your input.
I was expecting some error message like umatched parenthesis.
This is basically what the error is saying, and other implementations like SBCL produce the message you expect. I am working from Emacs:
CL-USER> )
... enters the debugger with unmatched close parenthesis
and a backtrace.
Let's see why. Using GET-MACRO-CHARACTER
, we ask our Common Lisp implementation to return the function associated with the #\)
character:
CL-USER> (get-macro-character #\))
SB-IMPL::READ-RIGHT-PAREN
NIL
In Emacs, the resulting value is a shown as a presentation, which allows us to inspect it. You can also point the name of the function, and if your installation of SBCL allows it (e.g. you installed from source), you can go to the definition with M-.:
(defun read-right-paren (stream ignore)
(declare (ignore ignore))
(simple-reader-error stream "unmatched close parenthesis"))
The same with CLISP produces the error you see. We can also do:
CL-USER> (get-macro-character #\))
#<SYSTEM-FUNCTION SYSTEM::RPAR-READER>
NIL
However the source definition for that system function is not so clear (if you are curious see the non-official mirror), but it is not surprising that another error message is displayed.
The behavior depends on which functions is bound in the current readtable to the character being read.
All implementations signal an error in that case, because when you reach a point where you have to lookup into the readtable for a closing parenthesis, the input is necessarily badly formed. It is the job of a function like READ-DELIMITED-LIST
, called from the function associated with the opening parenthesis, a.k.a. #\(
, to read until it find the corresponding closing parenthesis. Note that if you look-up the reader for #\(
in SBCL, it does not use read-delimited-list
, but a different, specialized version. It is a little bit too long to post it here.
In your case, you also have quote. How does quote behave?
(defun read-quote (stream ignore)
(declare (ignore ignore))
(list 'quote (read stream t nil t)))
It builds a list starting with quote
and containing a sub-expression obtained by calling READ
recursively. This is just as above, when I entered a closing parenthesis at the REPL prompt. Since we are not currently in the context of an open parenthesis, we encounter the #\)
character, look it up in the readtable and signal an error.
Upvotes: 3
Reputation: 139241
You write
'henry')
'
is a terminating macro char in Common Lisp.
Terminating means:
if it appears while parsing a token, it terminates that token.
So the second quote character terminates the token before, here henry
.
We have: quote, henry, quote, closing parenthesis.
The quote character is a macro character, which specifically causes another object to be read. 'some-object
is read as (QUOTE some-object)
. some-object
can be any data: a number, a string, a list, a symbol, ...
Thus a new object is being read and textual representations of objects can not start with a closed parenthesis. Closed parentheses are used to end lists or cons cells.
If you wanted a closing parenthesis in a symbol, you would need to escape it:
CL-USER 3 > '\)
\)
CL-USER 4 > '|)|
\)
CL-USER 5 > '|)woaaah(|
|)woaaah(|
Upvotes: 2
Reputation: 91837
Your extra quote character after 'henry
is the start of another object, which would make sense in a context like:
(defparameter *pudding-eater* 'henry '(a b c))
(if defparameter took that many arguments, anyway)
But, the next character after your quote is a close-paren. The Common Lisp notation for displaying a character (rather than a symbol, string, etc) is a #\
prefix, followed by the character.
So, the error message is not saying anything about the \
or #
characters, only )
, and it's telling you you have one where it expected more expressions instead of the end of the current one (because you started an expression by adding that '
character).
Upvotes: 5