【问题标题】:Reorder function arguments in Lisp在 Lisp 中重新排序函数参数
【发布时间】:2010-10-23 09:51:32
【问题描述】:

我对一个运算符“swap-arg”感兴趣,它以 1) n 个变量的函数 f 和 2) 索引 k 作为输入,然后返回相同的函数,除了第一个和第 k 个输入变量交换。例如(用数学表示法):

(swap-arg(f,2))(x,y,z,w) = f(z,y,x,w)

现在我的第一个想法是使用rotatef实现这个,如下所示,

(defun 交换参数 (f k) (lambda (L) (f (rotatef (nth k L) (car L)))))

但是,这似乎不太优雅,因为它在输入上使用了 rotatef。此外,它是 O(n),如果重复应用以重新索引所有内容,实际上可能是 O(n^2)。

这似乎是人们已经考虑过的常见问题,但我找不到任何东西。像这样交换输入的好方法是什么?有没有人们使用的标准方法?

【问题讨论】:

  • 你的函数 f 不是 n 个变量。它在您的示例中作为单个参数函数调用。
  • 我的设置方式我猜你是对的,它需要一个列表作为参数。有人会这样称呼它, (f (x y z w)) 我不会坚持这样称呼它,交换文字参数的东西,例如 (f x y z w) -> (f z y x w) 也会很好。
  • 如果 X 是一个函数,你可以这样调用它。如果没有,你会得到一个错误。

标签: input lisp arguments swap


【解决方案1】:

使用应用:

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

另一种方法是为这样的函数构建源代码,在运行时编译并返回它。如果这些函数不经常创建但经常调用,那将很有用。

【讨论】:

  • 这基本上就是我试图在 OP 中编写的内容,除了没有错误。 (:问题仍然存在 - 由于调用 n'th,它是 O(N),并且还在输入上使用 rotatef 会改变它们(如果我理解正确的话)。
  • @mazemaster255:使用 FUNCALL 调用时不会更改输入。它可能在使用 APPLY 调用时。如果您想避免这种情况,请使用 COPY-LIST 创建一个新的。当然它在运行时会很慢。请参阅我的答案的最后一段以获取替代方案。
【解决方案2】:

为了完整起见,函数也可以采用关键字(命名)参数,使用此函数可以使用其关键字参数的任何顺序调用。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-07-03
    • 2013-09-24
    • 1970-01-01
    相关资源
    最近更新 更多