Переупорядочить аргументы функции в Лиспе - PullRequest
3 голосов
/ 23 октября 2010

Мне интересен оператор swap-arg, который принимает в качестве входных данных 1) функцию f из n переменных и 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) на практике, если его применять повторно для переиндексации всего.

Это похоже на общую проблему, которую люди уже рассмотрели, но я не былсмог найти что угодно.Какой хороший способ поменять входные данные, как это?Есть ли стандартный метод, которым пользуются люди?

Ответы [ 2 ]

3 голосов
/ 23 октября 2010

Используя 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)

Другой способ сделать это - создать исходный код для такой функции, скомпилировать его во время выполнения и вернуть. Это было бы полезно, если бы эти функции создавались не часто, а вызывались часто.

2 голосов
/ 23 октября 2010

Просто для полноты функции могут также принимать ключевые (именованные) аргументы, при этом функция может вызываться с любым порядком своих ключевых аргументов.

...