views:

78

answers:

2

I'm pretty new to lisp; I was wondering if anyone here could help me out.

I have the following code snippet:

(defun write-lookup (binding-list pattern fact)
(cond
        ; No bindings have been stored
        ; Return the binding list with a new one!
        ((not binding-list) (cons (cons pattern fact) nil))

        ; A list of bindings is being stored
        (cond

            ; The current binding matches
            ((equal (caar binding-list) pattern)
                ; Return the binding-list if value matches, nil else
                (if (compare pattern fact) binding-list nil))

            ; Recursively search the rest of the list for the binding
            ((cdr binding-list) (write-lookup (cdr binding-list) pattern fact))

            ; The list doesn't have the binding.
            ; Return the binding-list with the added pattern
            ( T (cons (cons pattern fact) binding-list)))))

When I try to run it, I get the following:

*** - SYSTEM::%EXPAND-FORM: (EQUAL (CAAR BINDING-LIST) PATTERN) should be a
  lambda expression

Could someone please point out my error? Thanks!

+1  A: 

Your nested use of cond looks suspect. You could try the following form using if:

(defun write-lookup (binding-list pattern fact)
        ; No bindings have been stored
        ; Return the binding list with a new one!
  (if (not binding-list)
      (cons (cons pattern fact) nil)
    (cond
                                        ; The current binding matches
     ((equal (caar binding-list) pattern)
                                        ; Return the binding-list if value matches, nil else
      (if (compare pattern fact) binding-list nil))

                                        ; Recursively search the rest of the list for the binding
     ((cdr binding-list) (write-lookup (cdr binding-list) pattern fact))

                                        ; The list doesn't have the binding.
                                        ; Return the binding-list with the added pattern
     (T (cons (cons pattern fact) binding-list)))))

Sorry for the slight change of formatting; emacs like to put comments over to the right.

Burton Samograd
I think the convention for this level of comments is `;;`, which Emacs is happy to indent to the same place as your code.
Ken
+4  A: 

First you need to indent your code properly:

(defun write-lookup (binding-list pattern fact)
  (cond
        ; No bindings have been stored
        ; Return the binding list with a new one!
   ((not binding-list) (cons (cons pattern fact) nil))

        ; A list of bindings is being stored
   (cond

            ; The current binding matches
    ((equal (caar binding-list) pattern)
                ; Return the binding-list if value matches, nil else
     (if (compare pattern fact) binding-list nil))

            ; Recursively search the rest of the list for the binding
    ((cdr binding-list) (write-lookup (cdr binding-list) pattern fact))

            ; The list doesn't have the binding.
            ; Return the binding-list with the added pattern
    (T (cons (cons pattern fact) binding-list)))))

A typical Lisp editor will do that for you on a keystroke.

Now you can easily spot that a T clause is missing for the first COND. Let me add it:

(defun write-lookup (binding-list pattern fact)
  (cond
        ; No bindings have been stored
        ; Return the binding list with a new one!
   ((not binding-list) (cons (cons pattern fact) nil))

        ; A list of bindings is being stored
   (t (cond

            ; The current binding matches
       ((equal (caar binding-list) pattern)
                ; Return the binding-list if value matches, nil else
        (if (compare pattern fact) binding-list nil))

            ; Recursively search the rest of the list for the binding
       ((cdr binding-list) (write-lookup (cdr binding-list) pattern fact))

            ; The list doesn't have the binding.
            ; Return the binding-list with the added pattern
       (T (cons (cons pattern fact) binding-list))))))

I would also move the comment out of the code:

(defun write-lookup (binding-list pattern fact)
  (cond ((not binding-list)                          ; No bindings have been stored
         (cons (cons pattern fact) nil))             ; Return the binding list with a new one!
        (t                                           ; A list of bindings is being stored
         (cond ((equal (caar binding-list) pattern)  ; The current binding matches
                (if (compare pattern fact)           ; Return the binding-list if value matches, nil else
                    binding-list
                  nil))   
               ((cdr binding-list)                   ; Recursively search the rest list for the binding
                (write-lookup (cdr binding-list) pattern fact))
               (T                                    ; The list doesn't have the binding.
                (cons (cons pattern fact)            ; Return the binding-list adding the pattern
                      binding-list)))))) 
Rainer Joswig
Thanks! The missing T was the culprit.
chrishaum
Does the nested COND do anything? It looks like bringing the clauses from the nested COND out to the level of the clauses of the primary COND would produce identical results.
Vatine
@Vatine, that's a good observation. I didn't want to rewrite the code, but that would be one thing. Also (cons foo nil) = (list foo), ...
Rainer Joswig