Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Lisp - funcall of function receives too few arguments?

I am trying to figure out the proper usage of funcall. I have this function:

(defun frame-add-slot (frame slot)
  (push (list slot) (rest (assoc frame *frames*))))

and I'm trying to get this other function to call it.

(defun frame-add-subframe (superframe subframe)
  (let ((res (push (list subframe) (rest *frames*))))
    (funcall (frame-add-slot) subframe 'ako))))

However, when I try to pass it two arguments in this fashion, clisp tells me the called function receives too few arguments. What am I doing wrong? *Frames* is my knowledge base. It looks like this:

(setf *frames* '((mammal
                  (eats 
                   (:value meat)
                   (:if-needed (food))))
                 (4-legged-animal
                  (ako
                   (:type mammal)
                   (:default beings))
                  (blood
                   (:type warm-blooded)))
                 (husky
                  (ako
                   (:type dog))
                  (origin
                   (:value alaska)
                   (:default north-america))
                  (roots
                   (:value unknown)))
                 (dog 
                  (ako 
                   (:type 4-legged-animal))
                  (exterior 
                   (:value furry)
                   (:default skin)))
                 (abner
                  (isa 
                   (:type husky)
                   (:default dog))
                  (shape 
                   (:weight 40-lbs)
                   (:height 20-inches)
                   (:color brown))
                  (acts
                   (:demeanor friendly)
                   (:sometimes rough)))
                 (gypsy
                  (isa 
                   (:default dog))
                  (acts
                   (:demeanor unpredictable))
                  (shapes
                   (:weight 45-lbs)
                   (:color black-and-brown)))))
like image 441
Sean Glover Avatar asked Sep 13 '11 07:09

Sean Glover


People also ask

What does Funcall do in Lisp?

funcall applies function to args. If function is a symbol, it is coerced to a function as if by finding its functional value in the global environment.

When would you use a Funcall Lisp?

to indicate the value of a symbol in the value namespace and use it as a function, Lisp requires to use funcall , as in (funcall fn &rest arguments) , for the symbol fn . to indicate the functional value of a symbol or of an expression, Lisp uses the special form (function fn) , which is commonly abbreviated as #' .

What is t in LISP?

LISP uses the self-evaluating symbol nil to mean false. Anything other than nil means true. Unless we have a reason not to, we usually use the self-evaluating symbol t to stand for true.


3 Answers

Can you explain why you need FUNCALL?

FRAME-ADD-SLOT is a normal named function and you can call it as such - without FUNCALL.

(defun frame-add-subframe (superframe subframe)
  (let ((res (push (list subframe) (rest *frames*))))
    (frame-add-slot subframe 'ako))))

Literal data

Later in your code you set *frames* to constant literal data. In your functions you are modifying this constant data. In standard Common Lisp the effect of these modifications is undefined. You need freshly allocated data structures - these can be modified without problems. See for example the function COPY-TREE to recursively make a fresh copy of a deeply nested list. The result of COPY-TREE can be modified.

like image 147
Rainer Joswig Avatar answered Oct 06 '22 01:10

Rainer Joswig


There's several problems with your frame-add-subframe function:

  1. Why are you using funcall in this instance? You should be able to directly call frame-add-slot: (frame-add-slot subframe 'ako)
  2. If the funcall usage is merited, then you'd use it like this: (funcall #'frame-add-slot subframe 'ako)
  3. I presume that instead of specifying 'ako hardcoded, you meant to use res somehow? That variable is unused.
like image 39
Chris Jester-Young Avatar answered Oct 06 '22 01:10

Chris Jester-Young


In (funcall (frame-add-slot) subframe 'ako)))), you are calling frame-add-slot by putting parens around it.

Try (funcall #'frame-add-slot subframe 'ako).

like image 25
Paul Nathan Avatar answered Oct 06 '22 01:10

Paul Nathan