Clisp错误消息:对象无法以#\)开头。这是什么意思?

时间:2017-01-20 07:57:26

标签: common-lisp quote clisp

请看这个例子。我正在使用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*

我明白这是造成问题的双引号。我所做的明白,an object cannot start with #\)是什么意思?我从哪里开始#\)?我期待一些错误消息,如umatched parenthesis

3 个答案:

答案 0 :(得分:4)

'henry之后的额外引号字符是另一个对象的开头,这在以下情况下是有意义的:

(defparameter *pudding-eater* 'henry '(a b c))

(如果defparameter采取了那么多论点,无论如何)

但是,你引用之后的下一个字符就是密切关注。用于显示字符(而不是符号,字符串等)的Common Lisp表示法是#\前缀,后跟字符。

因此,错误消息没有说明\#字符,只有),而且它告诉您有一个预期更多表达式而不是结束的字符当前的一个(因为你通过添加'字符来启动表达式。)

答案 1 :(得分:3)

正如其他答案所指出的,#\(是表示(字符的语法。见2.4.8 Sharpsign部分。首先,读者看到#,然后调度下一个字符\(反斜杠),用于读取字符对象。因此,您的错误消息表明您的输入中)意外。

错误消息

  

我期待一些错误消息,比如umatched括号。

这基本上就是错误所说的,而像SBCL这样的其他实现会产生您期望的消息。我在Emacs工作:

CL-USER> )

...使用unmatched close parenthesis和回溯进入调试器。

让我们看看为什么。使用GET-MACRO-CHARACTER,我们要求Common Lisp实现返回与#\)字符关联的函数:

CL-USER> (get-macro-character #\))
SB-IMPL::READ-RIGHT-PAREN
NIL

在Emacs中,结果值显示为演示文稿,它允许我们检查它。您也可以指出该函数的名称,如果您的SBCL安装允许它(例如,您从源代码安装),您可以使用 M - 。

进入定义。
(defun read-right-paren (stream ignore)
  (declare (ignore ignore))
  (simple-reader-error stream "unmatched close parenthesis"))

与CLISP相同会产生您看到的错误。我们也可以这样做:

CL-USER> (get-macro-character #\))
#<SYSTEM-FUNCTION SYSTEM::RPAR-READER>
NIL

然而,该系统功能的源定义并不是那么清晰(如果您好奇,请参阅非官方mirror),但显示另一条错误消息并不奇怪。

读表以及Lisp如何读取表达式列表

行为取决于当前readtable中哪些函数绑定到正在读取的字符。 在这种情况下,所有实现都会发出错误信号,因为当您到达必须查找右括号的可读表的点时,输入必然是错误的。这是READ-DELIMITED-LIST之类函数的作用,从与左括号相关联的函数调用,a.k.a。#\(,直到找到相应的右括号为止。 请注意,如果您在SBCL中查找了#\(的阅读器,则它不会使用read-delimited-list,而是使用不同的专用版本。在这里发布它有点太长了

引用和递归阅读

在您的情况下,您也有报价。引用如何表现?

(defun read-quote (stream ignore)
  (declare (ignore ignore))
  (list 'quote (read stream t nil t)))

它构建一个以quote开头并包含通过递归调用READ获得的子表达式的列表。当我在REPL提示符下输入右括号时,就像上面一样。由于我们目前不在开括号的上下文中,因此我们会遇到#\)字符,在readtable中查找并​​发出错误信号。

答案 2 :(得分:2)

你写

'henry')

'是Common Lisp中的终止宏字符

终止意味着:

  

如果在解析令牌时出现,它会终止该令牌。

所以第二个引号字符在此之前终止了令牌henry

我们有:引用,亨利,引用,右括号。

引号字符是<​​em>宏字符,它特意导致另一个对象被读取。 'some-object被视为(QUOTE some-object)some-object可以是任何数据:数字,字符串,列表,符号......

因此正在读取新对象,并且对象的文本表示不能以闭括号开头。封闭括号用于结束列表或缺陷单元。

如果您想在符号中使用右括号,则需要将其转义:

CL-USER 3 > '\)
\)

CL-USER 4 > '|)|
\)

CL-USER 5 > '|)woaaah(|
|)woaaah(|