Lisp中的变量和符号是否不同?

Tho*_*son 4 lisp

numberp是Lisp中的谓词,并按(numberp 1)预期返回T. 但是如果我只输入numberp控制台,它会提示变量名是未定义的.

这两个有什么区别?

Rai*_*wig 12

这个问题已经有点不对了.

我们在讨论Common Lisp中的不同内容:

  • 符号:这是Lisp中的数据结构.符号是具有名称,值,函数,包等的数据对象.

在Common Lisp中,符号可以同时具有值​​和函数(或宏).

  • 一个变量是用于Lisp代码的值的识别符

DEFVAR和DEFPARAMETER定义了顶级变量.还有LAMBDA,DEFUN,LET,LET*等定义的局部变量.

(defun foo (i-am-a-variable) ...)

(defparameter *i-am-a-global-variable* ...)
Run Code Online (Sandbox Code Playgroud)
  • 命名函数是Lisp代码中函数的标识符.命名函数由DEFUN,DEFGENERIC和DEFMETHOD在顶层引入.还有FLET和LABELS定义的本地命名函数.

例:

(defun i-am-a-function (foo) ...)

(flet ((i-am-a-function (foo) ...)) ...)
Run Code Online (Sandbox Code Playgroud)

为了进一步复杂化,函数名称和变量名称是源代码中的符号.

例:

(type-of (second '(defun foo () nil)))  -->  SYMBOL
Run Code Online (Sandbox Code Playgroud)

我们来看看函数和变量:

(defun foo ()
  (let ((some-name 100))
    (flet ((some-name (bar) (+ bar 200)))
       (+ some-name (some-name some-name)))))
Run Code Online (Sandbox Code Playgroud)

上面的代码使用了一个变量和一个在源代码中具有相同符号的函数.由于函数和变量具有自己的命名空间,因此不存在冲突.

(+ some-name (some-name some-name))
Run Code Online (Sandbox Code Playgroud)

上面意味着我们将变量添加到变量的函数调用结果中.

这具有实际效果,您可以执行以下操作:

(defun parent (person) ...)

(defun do-something (parent)
   (parent parent))
Run Code Online (Sandbox Code Playgroud)

您不必担心您的本地变量名称将影响全局(或本地)函数.它们只是位于不同的名称空间中.

在Scheme中只有一个命名空间,我们必须编写

(define (foo lst) (list 'a lst 'n))
Run Code Online (Sandbox Code Playgroud)

在Common Lisp中我们可以写:

(defun foo (list) (list 'a list 'n))
Run Code Online (Sandbox Code Playgroud)

在Common Lisp中,不需要编写lst而不是list- 因为局部变量list和全局函数之间没有冲突list.

访问其他命名空间

要获取存储在变量中的函数对象,可以使用FUNCTION.

(let ((my-function (function numberp)))
  (funcall my-function 10))
Run Code Online (Sandbox Code Playgroud)

(function foo)可写得更短#'foo.

FUNCALL 调用一个函数对象.

OTOH,如果你想从函数命名空间中的变量存储一个函数对象,那么只有一种方法:

(setf (symbol-function 'foo) my-function)
Run Code Online (Sandbox Code Playgroud)

对象实际上也是一个函数而不是其他东西(数字,字符串......)也是必要的.否则你会看到一个错误.

这样做的副作用是Common Lisp永远(foo bar)不必检查FOO中是否真的是一个函数.它不可能是函数或未定义的函数.


sep*_*p2k 8

函数和变量存在于Common Lisp中的不同命名空间中.

因此,当您在预期函数的位置使用名称时(即在正在评估的列表的头部),它会查找具有该名称的函数(或宏).如果在期望变量的位置使用相同的名称,它将查找具有该名称的变量.

在您的情况下,有一个名为numberp的函数,但不是名为numberp的变量,因此第二种情况会导致错误.

  • 可能很高兴添加它来获取实际函数`numberp`而不调用它,CL中的语法是`#'numberp`. (2认同)