2010-10-23 4 views
3

Меня интересует оператор «swap-arg», который принимает в качестве входного сигнала 1) функцию f из n переменных и 2) индекс k, а затем возвращает ту же функцию, кроме первая и k-я входные переменные заменены. например, (в математической нотации):Аргументы функции порядка порядка в Lisp

(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

Ваша функция f не имеет n переменных. Он вызывается в вашем примере как одна функция аргумента. –

+0

То, как я его настраиваю, думаю, что вы правы, он принимает список в качестве аргумента. Можно было бы назвать это следующим образом: (f (x y z w)) Я не зацикливаюсь на том, чтобы называть его таким образом, что бы заменяло литеральные аргументы, например (f x y z w) -> (f z y x w) было бы хорошо. –

+0

, если X является функцией, вы можете назвать это так. Если нет, вы получите сообщение об ошибке. –

ответ

3

Использование ПРИМЕНЯЮТСЯ:

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

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

+0

Это в основном то, что я пытался писать в OP, за исключением ошибок. (: Проблема все еще сохраняется, но это O (N) из-за вызова n'th, а также использует rotatef на входах, которые меняют их (если я правильно понимаю). –

+0

@ mazemaster255: он не изменит входы, вызванные с помощью FUNCALL.Это может быть вызвано с APPLY.Если вы хотите избежать использования COPY-LIST для создания нового. Уверен, что во время выполнения он будет медленным. См. последний параграф моего ответа для альтернативы. –

+0

Ok , Спасибо за помощь. –

2

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

Смежные вопросы