2

LISP でキーワード パラメータを使用できます

(member 'a '(a b c) :test #'eq)

ただし、applyを使用してメンバーメソッドを呼び出そうとしたとき

(apply #'member 'a '(a b c) :test #'eq)

次のようなエラーメッセージがあります。

MEMBER: keyword arguments in (:TEST) should occur pairwise
 [Condition of type SYSTEM::SIMPLE-PROGRAM-ERROR]

解決策は

(apply #'member 'a '(a b c) '(:test eq))

キーワード引数がない場合

(apply #'member 'a '((a b c)))

これの背後にあるロジックは何ですか? '(:test #'eq) でエラーが発生するのはなぜですか?

追加した

これが私がこの質問をした理由です。ANSI Common Lispbook page 103 のコードがあります。

(defun our-adjoin (obj lst &rest args)
       (if (apply #'member obj lst args)
           lst
           (cons obj lst)))

私が試し(our-adjoin 'a '(a b c))たところ、結果は返されました(A B C)が、エラーが発生するため、 our-adjoin を として変換することはできません( Apply と Lisp のキーワード引数で(apply #'member 'a '(a b c))求められるように)。

私が考えることができるのは、エラーを発生させない&rest argsようなものを作るために from の値が与えられているということです。(apply #member 'a '(a b c) '())

4

2 に答える 2

5

applyは、最後の引数がリストであることを期待しています。あれは、

(apply #'foo (list 1 2 3)) == (foo 1 2 3)
(apply #'member 'a '(a b c) :test #'eq) == ??? ; is an error - #'eq isn't a list

リストが期待されている (関数) が何であるかはわかりませんが、それが問題applyです。#'eq

funcallあなたは代わりに探しているかもしれませんapply:

(funcall #'foo 1 2 3) == (foo 1 2 3)
(funcall #'member 'a '(a b c) :test #'eq) == (member 'a '(a b c) :test #'eq)

編集:(apply #'member 'a '(a b c))

これは

(member 'a 'a 'b 'c)

もちろんナンセンスです。apply最後の引数を「拡張」すると考えてください。

編集 2:our-adjoinコード

(our-adjoin 'a '(a b c) :test #'eq)
;; is equivalent to
(if (apply #'member 'a '(a b c) (list :test #'eq))
    lst
  (cons obj lst))
;; is equivalent to
(if (member 'a '(a b c) :test #'eq) ...)

(our-adjoin 'a '(a b c))
;; is equivalent to
(if (apply #'member 'a '(a b c) (list)) ...) ; (list) == nil
;; is equivalent to
(if (member 'a '(a b c)) ...)

したがって、あなたの仮説 (同等のものは(apply #'member 'a '(a b c) '())) は正しいです。nil(参考までに、'nil()、 、 に'()違いはありません(list)。)

于 2013-04-29T01:30:58.100 に答える
4

APPLYが提供されているため、計算された引数リストを使用して関数を呼び出すことができます。

APPLY次の構文があります。

apply function &rest args+ => result*
  • 最初のパラメーターは関数です

  • 次に、少なくとも 1 つの複数の引数。最後の引数はリストである必要があります

于 2013-04-29T07:50:26.590 に答える