i am currently learning common lisp and stumbled upon a question i could not answer my self:
(defun find-all (item seq &rest keyword-args &key (test #'eql)
test-not &allow-other-keys)
(if test-not
(apply #'remove item seq
:test-not (complement test-not) keyword-args)
(apply #'remove item seq
:test (complement test) keyword-args)))
The function is used to find every element in seq matching item according to a test function. Sadly I dont understand why the function 'apply' was used here. Shouldn't it be possible to just invoke remove without apply? A warnings says: "The function has an odd number of arguments in the keyword portion" if I invoke remove without apply.
I hope you can help me, Thanks in advance!
REMOVE and FIND-ALL
REMOVEtakes a bunch of keyword arguments: from-end, test, test-not, start, end, count and key.Now in the function
FIND-ALLyou want to modify just one: either test or test-not and then callREMOVE.How to write the parameter list of FIND-ALL
Now you have basically three options to write the parameter list of
FIND-ALL, since it is basically the same asREMOVEwith only one argument changed.list every keyword argument with their defaults and later pass them on with the necessary changed to
REMOVE.list only a rest arguments list, manipulate this argument list and pass the new one via
APPLYtoREMOVE.mix of 1. and 2. like in the example above. List only the required arguments and the keyword arguments to modify plus a rest list of the other keyword arguments provided at call time. Call
REMOVEviaAPPLY.How good are the three possibilities?
Now 1. has the advantage that you get to see a full parameter list for
FIND-ALLand that it does not need to cons an argument list. Lisp can check some of that. But you really need to copy all arguments in your parameter list and later in the calls toREMOVE. Possible but not that great.Then 2. has the disadvantage of not having a visible parameter list for
FIND-ALL, but it might be easier to write with a few functions to manipulate argument lists. 3. is relatively easy to write, but also lacks the full parameter list.Your example
Thus in your example it is version 3 of above:
If you want to pass an existing list of arguments as part of the arguments to the function, then you need
APPLY. That's why it is used there.APPLYcalls a function with the arguments taken from a list.