在Common Lisp

时间:2016-12-05 23:35:59

标签: lambda scheme common-lisp

我偶然发现了解释Y Combinator的this文章。代码在Scheme中,但我正在尝试使用Common Lisp。

但是,我在从Scheme到Common Lisp的翻译时遇到了麻烦。 Scheme对函数和(其他)变量使用单个命名空间,但Common Lisp对函数和变量使用不同的命名空间。如何解决这个差异,以获得有效的Common Lisp代码?

方案代码

这是教程中的一些Scheme代码。

在开始时,作者定义了阶乘函数:

(define (factorial n)
  if (= n 0)
    1
    (* n (factorial (- n 1)))))

并将其翻译成:

(define factorial
  (lambda (n)
    (if (= n 0)
      1
      (* n (factorial (- n 1))))))

因为(根据作者的说法)这就是Scheme所做的事情:

  

Scheme简单地将第一个定义转换为第二个定义   在评估它之前。所以Scheme中的所有函数都是lambda   表达式。

Common Lisp

我试图重写Common Lisp中的上述片段,以模仿从第一种形式到第二种形式的过渡。但是CL中没有define,也没有一个名称空间。所以我试图欺骗它。

重写Common Lisp中的第一个Scheme定义很简单:

(defun factorial (n)
    (if (= n 0)
        1
        (* n (factorial (- n 1)))))

但是(对我而言)将其翻译成第二个定义有点棘手。我翻译成这样:

(setf (symbol-function 'factorial)
  (lambda (n)
    (if (= n 0)
      1
      (* n (factorial (- n 1))))))

这是一个不好的方法吗(或者有更好的方法)?它似乎工作,但编译器给我一个样式警告:未定义的函数:factorial。

3 个答案:

答案 0 :(得分:3)

在某些方面,它更像是这样:

(setf (symbol-function 'factorial)
      (labels ((factorial (n)
                 (if (= n 0)
                     1
                   (* n (factorial (- n 1))))))
        #'factorial))

LABELS定义了本地函数factorial。在本地函数factorial的定义中,对factorial的任何调用都是针对该函数的。然后我们从labels表达式返回此函数。因此,您可以定义递归函数,其中递归调用不是未定义的函数。

如果你看一下Common Lisp实现,你可以看到DEFUN经常扩展为非可移植的构造,比如名为lambda的函数。此外,DEFUN还具有编译时副作用。

答案 1 :(得分:2)

公共列表中的转换毫无意义。

CL defun通常不仅仅是(setf fdefinition)

您可以通过评估(macroexpand-1 '(defun foo (a b c) (bar c a b)))

来了解这一点

真正的问题是 - 你为什么要这样做?

答案 2 :(得分:2)

如果我理解正确,你问题的主旨就是在"Lisp-1" and a "Lisp-2"之间进行翻译。

Scheme是一个“Lisp-1” - 它为函数和变量都有一个命名空间。另一方面,Common Lisp是一个“Lisp-2” - 它有函数和变量的独立命名空间。

在方案中,你可以写

(define foo (lambda (...) ...))

然后调用foo,如:

(foo ...)

我们也可以在Common Lisp中以完全相同的方式定义foo,但如果我们尝试使用该语法调用 foo,您的程序将崩溃。这是因为foo位于变量名称空间中,而不是 function 名称空间。

我们可以使用funcall来调用foo

来解决此问题
(funcall foo ...)

这是一个简短的介绍。 Common Lisp Cookbook上的Functions页面提供了您可能会觉得有用的其他详细信息。