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)
就像 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,但是如果您从函数返回一个函数,您可以这样做,或者您必须依赖funcall或apply使用返回值:
;; 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)
或者在函数中,您将其绑定到普通变量,并且需要funcall或apply:
(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。