我通过小lisper工作。功能lat?检查列表的所有元素是否都是原子

时间:2017-12-22 05:14:27

标签: recursion lisp common-lisp

(defun lat
  (lambda (l)
    (cond ((null l) t)
          ((atom (car l))(lat (cdr l))
          (t nil))))

该函数将列表作为参数。它是一个递归函数,用于检查列表中的每个元素。是否是原子。如果每个元素都是一个原子,则返回true,否则返回false。

以下是显示的错误 在编译LAT时:

Bad lambda list : (LAMBDA (L)
                    (COND ((NULL L) T) ((ATOM # #)) (T NIL)))
   [Condition of type CCL::COMPILE-TIME-PROGRAM-ERROR]

1 个答案:

答案 0 :(得分:4)

就像Hal Abelson所说的Scheme" lisp"在SICP视频中,本书也是如此,但本书中的语言是Scheme的前身,而不是Common Lisp。当你看到:

(define name 
  (lambda (arg ...) 
    body ...)

这与CL中的相同:

(defun name (arg ...)
  body ...)

原因是在Scheme中它对于运算符和操作数绑定都是相同的命名空间。像Common Lisp这样的lisp-2可以像这样拆分它:

(setf (fdefinition 'name)
  (lambda (arg ...)
    body ...))

这可能不会发生,因为您总是可以使用defun,但是如果您从函数返回函数,则可以执行此操作,或者您必须依赖funcall或{{ 1}}使用返回的值:

apply

使用此功能时,您可能希望全局绑定它:

;; This is a function that creates a function
(defun get-counter (from step)
  (lambda ()
    (let ((tmp from))
      (incf from step)
      tmp)))

或者在函数中,它将它绑定到常规变量,需要(setf (fdefinition 'evens) (get-counter 0 2)) (evens) ; ==> 0 (evens) ; ==> 2 funcall

apply

您更喜欢哪一个?

(defparameter *odds* (get-counter 1 2))
(funcall *odds*)
; ==> 1

?在(list (funcall *odds*) (evens)) ; ==> (3 4) inidicated谓词和CL中p a p在最后做同样的事情。您的函数lat?假设返回latpnil,因此根本不应返回函数。因此:

t

这当然与:

相同
(defun latp (list)
  (cond ((null list) t)
        ((atom (car list)) (latp (cdr list)))
        (t nil)))

与使用名称(defun latp (list) (or (null list) (and (atom (car list)) (latp (cdr list))))) 的Scheme不同,因为参数不会影响对list的函数调用。