Lisp - funcall функции получает слишком мало аргументов? - PullRequest
4 голосов
/ 13 сентября 2011

Я пытаюсь выяснить правильное использование funcall. У меня есть эта функция:

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

и я пытаюсь заставить эту функцию вызывать ее.

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

Однако, когда я пытаюсь передать ему два аргумента таким образом, clisp говорит мне, что вызываемая функция получает слишком мало аргументов. Что я делаю неправильно? *Frames* это моя база знаний. Это выглядит так:

(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)))))

Ответы [ 3 ]

8 голосов
/ 13 сентября 2011

Можете ли вы объяснить, почему вам нужно FUNCALL?

FRAME-ADD-SLOT является нормальной именованной функцией, и вы можете вызывать ее как таковой - без FUNCALL.

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

Литеральные данные

Позже в вашем коде вы устанавливаете *frames* в постоянные литеральные данные. В своих функциях вы изменяете эти постоянные данные. В стандартном Common Lisp эффект этих модификаций не определен. Вам нужны недавно выделенные структуры данных - они могут быть изменены без проблем. См., Например, функцию COPY-TREE для рекурсивного создания новой копии глубоко вложенного списка. Результат COPY-TREE можно изменить.

5 голосов
/ 13 сентября 2011

Есть несколько проблем с вашей frame-add-subframe функцией:

  1. Почему вы используете funcall в этом случае? Вы должны быть в состоянии напрямую позвонить frame-add-slot: (frame-add-slot subframe 'ako)
  2. Если использование funcall заслуживает внимания, вы можете использовать его следующим образом: (funcall #'frame-add-slot subframe 'ako)
  3. Я предполагаю, что вместо указания 'ako в жестком коде, вы хотели как-то использовать res? Эта переменная не используется.
4 голосов
/ 13 сентября 2011

В (funcall (frame-add-slot) subframe 'ako)))) вы вызываете frame-add-slot, ставя вокруг него скобки.

Попробуйте (funcall #'frame-add-slot subframe 'ako).

...