Aonna
Aonna

Reputation: 45

Undefined function called with () arguments

I'm dealing with this problem. I'm writing a function that returns true if the condition below are met. The input is a list and there are two valid operations: foo and baz

(foo a b c ... ) 

is valid, so the list starting with foo followed by words letters or numbers is valid, as many you want.

(baz a) 

so baz followed by words letters, numbers is valid. I can also combine them:

(foo (baz a) b 42 hello) it is valid 

(baz (foo a hello 42)) it is valid

also a list with just an element is valid: (a) (hello) (42)

if i use other operators it is not valid: like

(pizza a b c) or (foo (dog a b) a)

so the first element of each bracket must be a valid operator


(defun ok-operation (x)
  (cond ((eq (car x) 'foo) (ok-list (cdr x)) T)
        ((eq (car x) 'baz) (ok-list (cdr x) T))))

(defun ok-list (x)
  (cond ((atom (car x)) (ok-list (cdr x)) T)
        (t (ok-operation (cdr x) )))

The most common errors are:

Undefined function List called with arguments ()

and

variable atom is not bound

Upvotes: 1

Views: 460

Answers (3)

user5920214
user5920214

Reputation:

I am not quite clear from the question what the actual semantics you are after is. However here is an implementation (almost certainly not suitable as a homework answer!) of a style of solution to this kind of recursive-descent problem which I'm quite fond of. It's kind of entertaining to work out how hard doing something like this would be in more fashionable object systems.

As a note to people who know CLOS: I tend to put methods which are either trivial or trivial default cases in the defgeneric form: that's probably not the usual style, but I like it as it means you can see all the simple cases which you never change in the generic function definition and you're less likely to omit some critical fallback case.

For added value: what's the bug in this code and how do you fix it?

(defgeneric form-ok-p (form)
  ;; This is the entry point
  (:documentation
   "Is a form OK?")
  (:method ((form number))
   ;; numbers are OK
   t)
  (:method ((form symbol))
   ;; symbols are OK
   ;;
   ;; This seems to be the case from the example but the text says
   ;; 'letters' which would more naturally mean strings or perhaps
   ;; characters.  So, well, this might need to be made more complicated.
   ;; Note this means that (form-ok-p '()) is true.
   t)
  (:method ((form t))
   ;; defaultly forms are not OK
   nil))

    (defmethod form-ok-p ((form cons))
  ;; a cons is OK if it is OK as an operator with arguments
  (destructuring-bind (operator . args) form
    (and (listp args)
         ;; check the arguments are a proper list (this could also be
         ;; done in an around method on operator-ok-p and that might
         ;; be cooler).  This considers that if ARGS is not a proper
         ;; list then the form is not OK, but isn't an error: it might
         ;; be appropriate to actually consider this case an error, so
         ;; (form-ok-p '(foo . a)) would raise an error.  (The
         ;; deficiency in this code is here).
         (loop for tail on args
               unless (or (null tail) (consp tail))
               do (return nil)
               finally (return t))
         (operator-ok-p operator args))))

(defgeneric operator-ok-p (op args)
  ;; Methods on this GF can assume that ARGS is a proper list
  (:documentation
   "Is an operator with some arguments OK?")
  (:method (op args)
   ;; defaultly, no it's not
   nil))

(defmethod operator-ok-p ((op (eql 'foo)) args)
  ;; (foo ...) is OK if all its args are OK
  (every #'form-ok-p args))

(defmethod operator-ok-p ((op (eql 'bar)) args)
  ;; (bar ...) is OK if there is one arg and it's OK
  (and (null (rest args))
       (form-ok-p (first args))))

Upvotes: 1

Rainer Joswig
Rainer Joswig

Reputation: 139261

It would be great if you post an interaction which can be reproduced.

Your code - as you have posted - does not work. for example:

(defun ok-operation (x)
  (cond ((eq (car x) 'foo)
         (ok-list (cdr x))  ; this value is not used?
                            ;  thus the call is not having an effect
         T)
        ((eq (car x) 'baz)
         (ok-list (cdr x) T))  ; this value is not used?
   )  ; here a parenthesis is missing

Upvotes: 0

Sylwester
Sylwester

Reputation: 48745

(list) in ok-operation and ok-list does not do anything with the argument list since you are calling it. Instead you are calling the function list with zero arguments. It returns the empty list () and (car ()) ; ==> ()

list is part of the common-lisp package so the only way you get that error is if you are creating this in a function package that doesn't import common-lisp. Regardless I think you wanted it to be (car list) which takes the car of the variable list.

You have 3 parts in the cond clauses. Eg in ok-operations if (eq (car list) 'foo) it will first execute (ok-list (cdr list)) and since you don't use the returned value is just for effect and then always return T. If you want two conditions to be true you can use (and expression-1 expression-2) or you could just let the return of the second expression be the result by removing the final T.

atom is a standard function in common-lisp package as well.

The error messages are strange. It makes me question if you're running your code in a standard Common Lisp implementation. All languages with the same syntax are called Lisp so make sure it's Common Lisp your implementation is compatible with and not one of the vast other kinds of lisp dialects out there.

Upvotes: 0

Related Questions