3x89g2
3x89g2

Reputation: 257

Clisp error message: an object cannot start with #\). What does this mean?

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

Answers (3)

coredump
coredump

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.

Error message

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 read-table and how Lisp reads lists of expressions

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.

Quote and recursive reading

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

Rainer Joswig
Rainer Joswig

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

amalloy
amalloy

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

Related Questions