我想弄清楚什么是LISP中的"Atom"?由于lispworks,"atom-任何不是cons的对象"。但这个定义对我来说还不够清楚
例如,在下面的代码中:
(cadr
(caddar (cddddr L)))
L是原子吗?一方面,L不是原子,因为它是cons,因为它就是列表(如果我们谈论的是对象,它与符号L相关联)。另一方面,如果我们谈论"L"本身(不是关于它的内容,而是关于符号"L"),它是一个原子,因为它不是一个cons。
我试着把函数叫做"原子",
(atom L) => NIL
(atom `L) => T
但我仍然不知道。。。求你了,救命!
最后一个问题是:在上面的代码中,"L"是否是原子?
p.S.我之所以问这个问题,是因为我所在大学的LISP课程,在那里我们有一个"简单表达式"的定义——它是一个表达式,是一个或两个原子参数的原子或函数调用。因此,我想知道表达式(cddddr L)
是否简单,这取决于"L"是否是原子参数。
您的Lisp课程对"简单表达式";几乎可以肯定的是,它完全植根于语法。";原子参数";意味着它不是一个复合表达式。它可能与运行时值无关!
因此,我猜,这些都是简单的表达式:
(+ 1 2)
42
"abc"
而这些不是:
(+ 1 (* 3 4)) ;; (* 3 4) is not an atomic parameter
(+ a b c) ;; parameters atomic, but more than two
(foo) ;; not simple: fewer than one parameter, not "one or two"
鉴于最后一个反例,他们可能应该修改自己的定义。
一方面,L不是原子,因为它是cons,因为它就是列表(如果我们谈论的是对象,它与符号L相关联)。
您在这里谈论的是正在执行的代码的含义及其语义。这里的L
代表一个值,它是测试中的一个列表。在运行时,您可以检查值并询问它们的类型。
另一方面,如果我们谈论"L"本身(不是关于它的内容,而是关于符号"L"),它是一个原子,因为它不是一个cons。
在这里,您将了解构成代码语法的值的类型,以及在评估(或编译)之前如何表示代码。您正在操作一个符号树,其中一个是L
。在源代码中,这是一个符号。它本身没有任何意义,只是一个名字。
代码就是数据
Lisp使得使用语言本身的值来表示源代码变得容易,并且可以轻松地在某一点上操作代码片段来构建稍后执行的代码。这通常被称为同源性,认为这是一个有点敏感的词,因为人们并不总是认为这个定义足够精确而有用。另一种说法是";代码是数据";,大多数语言设计者和程序员都会同意这一点。
Lisp代码可以在运行时构建如下(>
是REPL的提示,下面是评估的结果):
> (list 'defun 'foo (list 'l) (list 'car 'l))
(DEFUN FOO (L) (CAR L))
生成的表单恰好是有效的Common Lisp代码,而不仅仅是一个通用的值列表。如果使用(eval *)
对其进行求值,则将定义一个名为FOO
的函数,该函数接受某个列表L
的第一个元素。
注:。在Common Lisp中,星号*
在REPL中绑定到成功返回的最后一个值。
通常你不会构建这样的代码,Lisp阅读器会将字符流变成这样的树。例如:
> (read-from-string "(defun foo (l) (car l))")
(DEFUN FOO (L) (CAR L))
但在REPL中也隐含地调用了reader(这是首字母缩写中的R)。
在这样的符号树中,L
是一个符号。
评价模型
当您在定义函数FOO
之后调用它时,您正在L
绑定到某个值的上下文中评估FOO
的主体。计算符号的规则是查找它所绑定的值,然后返回该值。这是运行时为您实现的代码的语义。
如果您使用的是一个简单的解释器,那么符号L
可能在运行时出现在某个位置,并且会查找其绑定。通常情况下,代码不是这样解释的,在编译过程中,可以以有效的方式对其进行分析和转换。编译的结果可能不再操纵符号,它只是操纵CPU寄存器和内存。
在所有情况下,根据语义的定义,此时询问L
的类型只是询问该类型在其出现的上下文中绑定到L
的任何值。
原子是指任何不是原子的东西
实际上,atom
的定义并不比这更复杂。语言中一个不是cons单元格的值称为原子。这包括数字,字符串,所有的东西。有时,您会评估碰巧是代码的符号树,但随后同样的规则也适用。
简单表达式
p。S.我问这个问题是因为我所在大学的LISP课程,在那里我们有一个"简单表达式"的定义——它是一个表达式,是一个或两个原子参数的原子或函数调用。因此,我想知道表达式(cddddr L)是否简单,这取决于"L"是否是原子参数。
在该课程中,您将编写分析代码的函数。您将得到一个Lisp值,并且必须决定它是否是一个简单表达式。
您对给定值的任何特定解释都不感兴趣,在任何情况下,您都不会遍历该值,查看符号并尝试将其解析为值:您正在检查语法是否是有效的简单表达式。
还要注意的是,你课程中的定义可能与任何特定流行风格的定义有点不同(这不一定是Common Lisp或Scheme,而是一种玩具Lisp方言)。优先遵循课程中的定义。
假设我们有一个谓词,它告诉我们对象是否不是数:
(not-number-p 3) -> NIL
(not-number-p "string") -> T
(let ((foo "another string))
(not-number-p foo)) -> T
(not-number '(1 2 3)) -> T
(not-number (first '(1 2 3)) -> NIL
我们可以将其定义为:
(defun not-number-p (object)
(not (numberp object))
以上与NUMBERP
正好相反。
NUMBERP
->T
如果对象是数字NOT-NUMBER-P
->NIL
如果对象是数字
现在假设我们有一个谓词NOT-CONS-P
,它告诉我们对象是否不是CONS
单元。
(not-cons-p '(1 . 2)) -> NIL
(let ((c '(1 . 2)))
(not-cons-p c)) -> NIL
(not-cons-p 3) -> T
(let ((n 4))
(not-cons-p n)) -> T
(not-cons-p NIL) -> T
(not-cons-p 'NIL) -> T
(not-cons-p 'a-symbol) -> T
(not-cons-p #space) -> T
函数NOT-CONS-P
可以定义为:
(defun not-cons-p (object)
(if (consp object)
NIL
T))
或更短:
(defun not-cons-p (object)
(not (consp object))
函数NOT-CONS-P
在Lisp中传统上称为ATOM
在Common Lisp中,每个不是cons-cell的对象都被称为原子。函数ATOM
是谓词。
参见Common Lisp HyperSpec:Function Atom
您的问题:
(cadr (caddar (cddddr L)))
Is 'L' an atom?
我们怎么会知道呢?CCD_ 28是一个变量。L
的值是多少?
(let ((L 10))
(atom L)) -> T
(let ((L (cons 1 2)))
(atom L) -> NIL
(atom l)
回答了这个问题:
->是L
和原子的值
(atom l)
没有回答这个问题:
->L
是原子吗?L
是变量,并且在函数调用中,L
的值被传递给函数ATOM
。
如果您想询问符号L
是否是原子,则需要引用的符号:
(atom 'L) -> T
(atom (quote L)) -> T
符号是原子。实际上,除了cons细胞外,所有的东西都是原子。