什么是LISP中的原子

  • 本文关键字:LISP lisp common-lisp
  • 更新时间 :
  • 英文 :


我想弄清楚什么是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细胞外,所有的东西都是原子

最新更新