【问题标题】:why defun is not the same as (setq <name> <lambda>)?为什么 defun 和 (setq <name> <lambda>) 不一样?
【发布时间】:2012-06-28 02:07:45
【问题描述】:

我对 defun 宏的工作原理感到困惑,因为

(defun x () "hello")

将创建函数 x,但符号 x 仍然是未绑定的。

如果我将一些 lambda 绑定到 x,那么 x 将有一个值,但它不会被解释器视为如下形式的函数:

(x)

我认为这与 defun 应该在全局环境中定义函数这一事实有关,但我不确定它究竟是什么意思。为什么我不能在当前环境下对其进行影子?

如果某些 lambda 绑定到符号,是否有任何方法强制解释器将符号视为函数?例如:

(setq y (lambda () "I want to be a named function"))
(y)

P.S.:我正在使用 SBCL。

【问题讨论】:

    标签: lisp common-lisp sbcl


    【解决方案1】:

    Common Lisp 对函数和值有不同的命名空间。

    您在函数命名空间中使用DEFUNFLETLABELS 等定义函数。

    如果要获取函数对象作为值,请使用FUNCTION

    (defun foo (x) (1+ x))
    
    (function foo)   ->  #<the function foo>
    

    或更短:

    #'foo    ->   #<the function foo>
    

    如果你想调用一个函数,那么你写(foo 100)

    如果要将函数作为值调用,则需要使用FUNCALLAPPLY

    (funcall #'foo 1)
    

    您可以传递函数并调用它们:

    (defun bar (f arg)
      (funcall f arg arg))
    
    (bar #'+ 2)  ->  4
    

    在 DEFUN 的情况下:

    不是(setf (symbol-value 'FOO) (lambda ...))

    更像(setf (symbol-function 'foo) (lambda ...))

    请注意,这两个命名空间使您可以编写:

    (defun foo (list)
      (list list))
    
    (foo '(1 2 3))  ->  ((1 2 3))
    

    内置函数LIST和变量LIST之间没有冲突。由于我们有两个不同的命名空间,我们可以将同一个名称用于两种不同的目的。

    还要注意,在局部函数的情况下,不涉及符号。命名空间不一定与符号相关联。因此,对于局部变量,无法通过符号名称进行函数查找。

    【讨论】:

      【解决方案2】:

      Common Lisp 为每个符号有多个槽,包括一个值槽和一个函数槽。当您使用语法(x) 时,common lisp 会查找x 的函数槽绑定。如果要调用值绑定,请使用funcallapply

      http://cl-cookbook.sourceforge.net/functions.html

      【讨论】:

      • 搞笑!我认为 perl 对 $foo, @foo, %foo, foo 很特别。
      • @Dmitry 在 POSIX shell 中,变量$testtest 命令/函数无关。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2018-07-07
      • 2013-05-28
      • 2012-02-14
      • 2012-04-03
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多