利用Lisp中的两个名称空间编写测试功能

时间:2019-06-19 08:20:17

标签: scheme lisp common-lisp funcall

我开始学习Lisp并使用Lispworks个人版6.1.1,在评估基本功能时遇到了问题。我能够在Scheme中正确设置它们,但是当我尝试在Lisp中评估它们时它们却无法正常工作。

我在Lisp中知道每个符号都有两个命名空间。因此,我尝试编写用于组成两个过程的简单过程。它可以在Scheme中完美运行,但是在Lisp中,评估存在问题。

方案中的代码可以正常工作并返回2

(define (comp a b)
  (lambda (x)
    (a (b x))))

(define test (comp car cdr))
(test '(1 2 3))

用Lisp重写相同的代码

(defun comp (a b)
  (lambda (x)
    (funcall a (funcall b x))))

(defun test (comp #'car #'cdr))

(funcall test '(1 2 3))

lispworks中的错误是:

  

试图绑定非符号(FUNCTION CAR)

所以当我尝试在听众中评估(defun test (comp #'car #'cdr))时,我会得到

  

在函数(FUNCTION CAR)中用作变量名的非符号TEST

我不明白为什么它不能像这样写。我会很感激

4 个答案:

答案 0 :(得分:6)

defun用于定义带有参数的函数:

defun function-name lambda-list [[declaration* | documentation]] form*

因此它在函数名称后需要一个lambda列表,但是您已经编写了:

(defun test (comp #'car #'cdr))

不遵守此语法。如果要定义一个包含由两个函数组成的函数的变量,则有几种可能性:

  1. 使用特殊变量:

    (defvar test (comp #'car #'cdr))
    
  2. 在表单内使用局部变量:

    (let ((test (comp #'car #'cdr)))
      (funcall test '(1 2 3))
    

您甚至可以将其分配给全局函数名称,例如:

(setf (symbol-function 'test) (comp #'car #'cdr)

,在这种情况下,您可以将名称用作常规函数名称,而无需使用funcall

(test '(1 2 3))

答案 1 :(得分:5)

(defun test (comp #'car #'cdr))

DEFUN会在名称后出现一个lambda列表,并且您的lambda列表格式错误,因为#'car不是符号,而是读为(function car)

您可能想做的就是将函数test定义为carcdr的组合; (comp ...)将返回适当的函数对象,但是defun不允许使用值代替lambda-list。

您可以这样做:

(setf (symbol-function 'test)
      (comp #'car #'cdr))

答案 2 :(得分:1)

具有本地功能:

CL-USER 1 > (flet ((comp (a b)
                     (lambda (x)
                       (funcall a (funcall b x)))))
              (let ((test (comp #'car #'cdr)))
                (flet ((test (x)
                         (funcall test x)))
                  (test '(1 2 3)))))
2

CL-USER 2 > (labels ((comp (a b)
                       (lambda (x)
                         (funcall a (funcall b x))))
                     (test (x)
                       (funcall (comp #'car #'cdr) x)))
              (test '(1 2 3)))
2

答案 3 :(得分:0)

另一个建议:

(defun comp (a b)
  (lambda (x)
     (funcall a (funcall b x))))

(defun mytest (x &key test)  ;; a "test" key is common
   (funcall test x))

(mytest '(1 2 3) :test (comp #'car #'cdr))

(defun comp (x a b)
  (funcall a (funcall b x)))

(defun test (x a b)
  (comp x a b))

(test '(1 2 3) #'car #'cdr)