Reorder function arguments in Lisp
I'm interested in an operator, "swap-arg", that takes as input 1) a function f of n variables, and 2) index k, and then returns a the same function except with the first a开发者_开发问答nd kth input variables swapped. eg (in mathematical notation):
(swap-arg(f,2))(x,y,z,w) = f(z,y,x,w)
Now my first idea is to implement this using rotatef as follows,
(defun swap-args (f k) (lambda (L) (f (rotatef (nth k L) (car L)))))
However, this seems inelegant since it uses rotatef on the input. Also, it's O(n), and could be O(n^2) in practice if applied repeatedly to reindex everything.
This seems like a common problem people would have already considered, but I haven't been able to find anything. What's a good way to swap inputs like this? Is there a standard method people use?
Using APPLY:
(defun create-swapped-arg-function (f k)
"Takes as input a function f of n variables and an index k.
Returns returns a new function with the first and kth input variables swapped,
which calls the function f."
(lambda (&rest args)
(apply f (progn
(rotatef (nth k args) (first args))
args))))
Example:
CL-USER 5 > (funcall (create-swapped-arg-function #'list 2) 0 1 2 3 4 5 6)
(2 1 0 3 4 5 6)
Another way to do it would be to build the source code for such a function, compile it at runtime and return it. That would be useful if these functions are not created often, but called often.
Just for completeness, functions can also take keyword (named) arguments, using this the function can be called with any order of its keyword arguments.
精彩评论