我通过小 lisper 工作。函数纬度?检查列表的所有元素是否都是原子

San*_*kar 1 lisp recursion common-lisp

(defun lat
  (lambda (l)
    (cond ((null l) t)
          ((atom (car l))(lat (cdr l))
          (t nil))))
Run Code Online (Sandbox Code Playgroud)

该函数接受一个列表作为参数。它是一个递归函数,用于检查列表中的每个元素。不管是不是原子。如果每个元素都是一个原子,那么它返回真否则假。

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

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

Syl*_*ter 5

就像 Hal Abelson 在 SICP 视频中将 Scheme 称为“lisp”一样,本书也是这样做的,但是书中的语言是 Scheme 的前身,而不是 Common Lisp。当你看到:

(define name 
  (lambda (arg ...) 
    body ...)
Run Code Online (Sandbox Code Playgroud)

这与 CL 中的相同:

(defun name (arg ...)
  body ...)
Run Code Online (Sandbox Code Playgroud)

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

(setf (fdefinition 'name)
  (lambda (arg ...)
    body ...))
Run Code Online (Sandbox Code Playgroud)

这可能不会发生,因为您始终可以使用defun,但是如果您从函数返回一个函数,您可以这样做,或者您必须依赖funcallapply使用返回值:

;; This is a function that creates a function
(defun get-counter (from step)
  (lambda ()
    (let ((tmp from))
      (incf from step)
      tmp)))
Run Code Online (Sandbox Code Playgroud)

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

(setf (fdefinition 'evens) (get-counter 0 2))
(evens) ; ==> 0
(evens) ; ==> 2
Run Code Online (Sandbox Code Playgroud)

或者在函数中,您将其绑定到普通变量,并且需要funcallapply

(defparameter *odds* (get-counter 1 2))
(funcall *odds*)
; ==> 1
Run Code Online (Sandbox Code Playgroud)

你更倾向哪个?

(list (funcall *odds*) (evens))
; ==> (3 4)
Run Code Online (Sandbox Code Playgroud)

这 ?在lat?indicated predicate 和 CL ap 中最后做同样的事情。你的函数应该latp返回nil或者t它根本不应该返回一个函数。因此:

(defun latp (list)
  (cond ((null list) t)
        ((atom (car list)) (latp (cdr list)))
        (t nil)))
Run Code Online (Sandbox Code Playgroud)

这当然是一样的:

(defun latp (list)
  (or (null list)
      (and (atom (car list))
           (latp (cdr list)))))
Run Code Online (Sandbox Code Playgroud)

与使用名称list作为参数的Scheme 不同,它不会影响对 的函数调用list