2010-10-23 7 views
3

Je m'intéresse à un opérateur, "swap-arg", qui prend en entrée 1) une fonction f de n variables, et 2) l'indice k, puis retourne la même fonction sauf avec les première et kième variables d'entrée permutées. par exemple (en notation mathématique):Réorganiser les arguments de la fonction en Lisp

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

Maintenant, ma première idée est de mettre en œuvre ce en utilisant rotatef comme suit,

 
(defun swap-args (f k) 
    (lambda (L) (f (rotatef (nth k L) (car L))))) 

Cependant, cela semble inélégante, car il utilise rotatef sur l'entrée. En outre, c'est O (n), et pourrait être O (n^2) en pratique s'il est appliqué à plusieurs reprises pour réindexer tout.

Cela semble être un problème commun que les gens auraient déjà envisagé, mais je n'ai rien trouvé. Quel est un bon moyen d'échanger des entrées comme ça? Existe-t-il une méthode standard que les gens utilisent?

+0

Votre fonction f n'est pas de n variables. Il est appelé dans votre exemple comme une fonction à un seul argument. –

+0

La façon dont je l'ai configuré je suppose que vous avez raison, il prend une liste comme argument. On pourrait appeler cela comme suit, (f (x y z w)) Je ne suis pas bloqué sur l'appel de cette façon, quelque chose qui permute les arguments littéraux, par exemple (f x y z w) -> (f z y x w) serait bon aussi. –

+0

Si X est une fonction, vous pouvez l'appeler comme ça. Sinon, vous obtenez une erreur. –

Répondre

3

En utilisant POSTULER:

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

Exemple:

CL-USER 5 > (funcall (create-swapped-arg-function #'list 2) 0 1 2 3 4 5 6) 
(2 1 0 3 4 5 6) 

Une autre façon de le faire serait de construire le code source pour une telle fonction, la compilation lors de l'exécution et le retourner. Cela serait utile si ces fonctions ne sont pas souvent créées, mais appelées souvent.

+0

C'est essentiellement ce que j'essayais d'écrire dans l'OP, sauf sans les bugs. (: Le problème reste quand même - c'est O (N) dû à l'appel de n'th, et utilise aussi rotatef sur les entrées qui les changeraient (si je comprends bien) –

+0

@ mazemaster255: Cela ne changerait pas le Quand il est appelé avec FUNCALL, il peut être appelé avec APPLY Si vous voulez éviter d'utiliser COPY-LIST pour en créer un nouveau, bien sûr, il sera lent à l'exécution Voir le dernier paragraphe de ma réponse pour une alternative –

+0

Ok , Merci pour l'aide. –

2

Juste pour l'exhaustivité, les fonctions peuvent également prendre des arguments de mots-clés (nommés), en utilisant ceci la fonction peut être appelée avec n'importe quel ordre de ses arguments de mot-clé.