我对一个运算符“swap-arg”感兴趣,它接受输入1)n个变量的函数f,和2)索引k,然后返回一个相同的函数,除了第一个和第k个输入变量交换。例如(用数学符号表示):
(swap-arg(f,2))(x,y,z,w) = f(z,y,x,w)
现在我的第一个想法是使用rotatef实现这个,如下所示,
(defun swap-args (f k) (lambda (L) (f (rotatef (nth k L) (car L)))))
然而,这似乎不优雅,因为它在输入上使用了rotatef。此外,它是O(n),如果反复应用以重新索引所有内容,实际上可能是O(n ^ 2)。
这似乎是人们已经考虑过的常见问题,但我找不到任何东西。交换这样的输入有什么好方法?人们使用标准方法吗?
答案 0 :(得分:3)
使用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))))
示例:
CL-USER 5 > (funcall (create-swapped-arg-function #'list 2) 0 1 2 3 4 5 6)
(2 1 0 3 4 5 6)
另一种方法是为这样的函数构建源代码,在运行时编译它并返回它。如果这些函数不是经常创建的,而是经常调用的,那将非常有用。
答案 1 :(得分:2)
为了完整性,函数也可以使用关键字(命名)参数,使用此参数可以使用其关键字参数的任何顺序调用该函数。