numberp
是Lisp中的谓词,(numberp 1)
按预期返回T.但是,如果我只在控制台中键入numberp
,则会提示变量名称未定义。
这两个有什么区别?
答案 0 :(得分:12)
这个问题已经有点不对了。
我们在讨论Common Lisp中的不同内容:
在Common Lisp中,符号可以同时包含值和函数(或宏)。
DEFVAR和DEFPARAMETER定义了顶级变量。还有LAMBDA,DEFUN,LET,LET *和其他人定义的局部变量。
(defun foo (i-am-a-variable) ...)
(defparameter *i-am-a-global-variable* ...)
示例:
(defun i-am-a-function (foo) ...)
(flet ((i-am-a-function (foo) ...)) ...)
要进一步复杂化,函数名称和变量名称是源代码中的符号。
示例:
(type-of (second '(defun foo () nil))) --> SYMBOL
让我们看一下函数和变量:
(defun foo ()
(let ((some-name 100))
(flet ((some-name (bar) (+ bar 200)))
(+ some-name (some-name some-name)))))
上面的代码使用了源代码中具有相同符号的变量和函数。由于函数和变量都有自己的命名空间,因此没有冲突。
(+ some-name (some-name some-name))
高于此意味着我们将变量添加到变量函数调用的结果中。
这具有实际效果,您可以执行以下操作:
(defun parent (person) ...)
(defun do-something (parent)
(parent parent))
您不必担心本地变量名称会影响全局(或本地)函数。它们只是位于不同的名称空间中。
在Scheme中只有一个命名空间,我们必须编写
(define (foo lst) (list 'a lst 'n))
在Common Lisp中我们可以写:
(defun foo (list) (list 'a list 'n))
在Common Lisp中,不需要编写lst
而不是list
- 因为局部变量list
和全局函数list
之间没有冲突。 / p>
访问其他命名空间
要获取存储在变量中的函数对象,可以使用FUNCTION
。
(let ((my-function (function numberp)))
(funcall my-function 10))
(function foo)
可缩短为#'foo
。
FUNCALL
调用一个函数对象。
OTOH,如果你想从函数名称空间中的变量存储一个函数对象,那么只有一种方法:
(setf (symbol-function 'foo) my-function)
对象实际上也是一个函数而不是其他东西(数字,字符串......)也是必要的。否则你会看到一个错误。
这样做的副作用是Common Lisp永远不必检查在(foo bar)
中FOO是否真的是一个函数。它不可能不是函数或未定义。
答案 1 :(得分:8)
函数和变量存在于Common Lisp中的不同命名空间中。
因此,当您在预期函数的位置使用名称时(即在正在评估的列表的头部),它会查找具有该名称的函数(或宏)。如果在期望变量的位置使用相同的名称,它将查找具有该名称的变量。
在你的情况下,有一个名为numberp的函数,但不是名为numberp的变量,所以第二种情况会导致错误。
答案 2 :(得分:0)
Scheme(一个Lisp方言,可以这么说)和Common Lisp之间的区别之一是,在Scheme中,有一个名称空间用于变量和函数,而在CL中,有两个单独的名称空间。 因此,在Scheme中,“define”设置这个唯一的名称到值的关联,而在CL中,有值的“define”和函数关联的“defun”。
所以,在CL中你可以:
(define foo ...something...)
(defun foo ...somethingElse...)
让读者感到困惑。
在Scheme中,只有一个:
(define foo something)
如果这个好或坏,过去几乎是宗教纠纷......