我定义的cond函数无法正常工作(LISP)

时间:2013-09-05 23:18:09

标签: list lisp common-lisp atomic conditional-statements

我正在尝试定义自己的函数,以使我的hw2更容易,但它不起作用。你能看看它并告诉我我错过了什么吗?

    (DEFUN testAL(x)
        COND ( ( ATOMP(x) ) 'this-is-an-atom )
             ( ( LISTP(x) ) 'this-is-a-list )
             ( T 'this-is-neither ) )

我希望这个条件函数接受输入X并输出它是原子,列表还是两者都没有。问题是,当我输入NIL时,我收到一个错误:尝试获取未绑定变量`COND'的值。

家庭作业2包含以下问题:

  

以下哪一项是原子,哪些列出,哪两个都没有?

     

一个。零

     

湾(例如10 3)

     

℃。 (a b)

     

d。 64

     

即Ť

     

F。 (没有像家一样的地方)

     

克。 '(+ 3 5 6)

1 个答案:

答案 0 :(得分:6)

您的括号不在正确的位置。除非引用,括号是函数应用程序的开头。

它以未绑定的变量cond开头。它不是特殊形式(cond (predicate consequent) (predicate2 consequent2)),因为它不是以左括号开头的。

仅从缩进中我猜你打算写:

(DEFUN testAL (x)
    (COND ((ATOM x) 'this-is-an-atom)
          ((LISTP x) 'this-is-a-list)
          (T 'this-is-neither)))

(testal 'test)    ; ==> THIS-IS-AN-ATOM
(testal '(a b c)) ; ==> THIS-IS-A-LIST

我删除了x周围的额外括号,因为(x)表示应用函数x,而x表示变量xx位于(+ x 3)之后,+是要应用的函数,x是其操作数之一。

我将atomp更改为atom。由于atom是50年代第一个LISP定义的第一个原语之一,因此它没有像大多数其他谓词那样的后缀p

编辑:多次匹配

你可能只有几个cond(或if,因为你每个人只有一个测试)并且做副作用,比如(print "THIS-IS-AN-ATOM"),因为你的基本情况永远不会触发(没有任何东西都没有CL中的list和atom)。这可能是简单的解决方案。

(DEFUN testAL (x)
    (if (ATOM x) (print 'this-is-an-atom))
    (if (LISTP x) (print 'this-is-a-list)))

(testal '()) ; ==> THIS-IS-A-LIST (but prints both)

对于更实用的方法,我会使用更高阶函数来保持代码可测试并提供执行副作用的打印功能。请注意,对于初学者来说,这可能不那么容易阅读:

;; a list of pairs of predicate and their desription
(defparameter *type-predicates-and-description* 
                '((douglasp . this-is-the-answer-to-everything)
                  (floatp . this-is-a-floating-pont-number)
                  (integerp . this-is-an-integer)
                  (numberp . this-is-a-number)
                  (null . this-is-null)
                  (listp . this-is-a-list)
                  (characterp . this-is-a-character)
                  (stringp . this-is-a-string)))

;; custom made predicate
(defun douglasp (x)
  (and (numberp x) (= x 42)))

;; returns all the types of a particular value  
(defun get-type-info (x)
  "return a list if types thet describes argument"
  (flet ((check-type (acc type-pair)
            "Accumulate description when predicate match"
            (if (funcall (car type-pair) x) 
                (cons (cdr type-pair) acc) 
                 acc))) 
    ;; test x for each type predicate-description        
    (let ((res (reduce #'check-type
                       *type-predicates-and-description* 
                       :initial-value '())))
      ;; check of empty list (no types matched)
      (if (null res) 
          (list 'this-is-neither) 
      res))))

;; test it
(get-type-info '()) ; ==> (THIS-IS-A-LIST THIS-IS-NULL)
(get-type-info 42)  ; ==> (THIS-IS-A-NUMBER 
                    ;      THIS-IS-AN-INTEGER 
                    ;      THIS-IS-THE-ANSWER-TO-EVERYTHING)
(get-type-info #()) ; ==> (THIS-IS-NEITHER)

;; Make a function to do side effects
(defun print-type-info (x)
  (format t "~{~a~^, ~}." (get-type-info x)))

(print-type-info '()) ; ==> NIL
                      ; and prints "THIS-IS-A-LIST, THIS-IS-NULL."