2009-03-10 20 views
13

¿Alguien me puede decir cómo trabajar con los parámetros almacenados en el valor especificado por & resto.Common Lisp: Trabajando con & parámetros de reposo

He leído mucho y parece que los autores solo saben cómo enumerar todos los parámetros.

(defun test (a &rest b) b) 

Esto es agradable de ver, pero no realmente tan útil.

Lo mejor que he encontrado hasta ahora es utilizar primero, segundo, y así sucesivamente para obtener el parámetro que está buscando.

(defun test (a &rest b) 
    (first b)) 

me di cuenta de que este método deja de funcionar en la décima parámetro, pero la especificación (por lo que he leído) soporta un mínimo de 50. Aunque son escasas las probabilidades de que voy a utilizar 50 parámetros, que Me gustaría saber cómo acceder a todos.

Gracias

Respuesta

6

el primer, segundo y así sucesivamente funciones de acceso son "sólo" funciones de utilidad en la parte superior del CAR/CDR o NTH. Así que, supongo, la respuesta a su pregunta específica es "use NTH o ELT" (o cree sus propias funciones específicas de acccessor).

Si lo desea, puede definir un undécimo como:

(defun XI (lista) (lista enésima 10))

me parece, sin embargo, que en su mayoría utilizo & argumentos REST cuando hay 0 o más cosas con las que quiero hacer algo, sin preocuparme realmente por la posición específica de un argumento dado en la lista RESTO &. Eso generalmente implica usar LOOP, DO o DOLIST para recorrer los argumentos y hacer algo con cada uno; la familia MAP o (ocasionalmente) REDUCE.

8

El parámetro de descanso es solo una lista. Puede manejarlo usando operaciones de lista normales.

(defun test (a &rest b)) 
    (dolist (s b) 
    (when (> s 1) 
     (print s) 
     (do-something-else b))) 
+0

Es una lista dentro de la función, pero pasar una lista como & rest podría no darle el comportamiento que desea (contrario a los parámetros [] de, por ejemplo, el lenguaje C#). Es bastante fácil para un principiante (como yo) cometer este error: suponga que su función es recursiva con un parámetro & rest. Luego, durante la recursión no puede pasar una lista como & rest param, debe usar apply # 'yourfun ... – PawelP

+1

@PawelP Si necesita pasar una lista, simplemente use el param de función normal para pasar esa lista. y los parámetros de descanso son solo una manera fácil de invocar la función con un número variable de parámetros sin envolverlos en una lista usted mismo en cada sitio de llamadas. – Marko

+0

Lo que fue engañoso para mí fue el hecho de que * inside * la función, & rest param es accedida como una lista, sin embargo no se puede pasar directamente como un & rest param recursivamente (porque estarías pasando una lista y es probablemente no sea lo que quieres). Creo que no soy el único principiante que cayó en esta trampa. Parece que LISP hace un "empaquetado" entre bastidores en la invocación de funciones (hace una lista de los parámetros que se analizan como & rest) Por supuesto que su explicación es correcta, no estoy disputando eso. – PawelP

5

En realidad, la función es útil. Solo tienes que probarlo

CL-USER 1 > (defun test (a &rest b) b) 
TEST 

CL-USER 2 > (test 1 2 3 4) 
(2 3 4) 

por lo que ver que B es sólo una lista de los argumentos. Entonces cada lista y operación de secuencia se aplica. No hay nada mágico Hay funciones de acceso al enésimo elemento, funciones para eliminar elementos, etc ..

En el Lisp Común hyperspec las funciones relevantes son los siguientes:

14. The Conses Dictionary

17. The Sequences Dictionary

Para un Lisp básica tutorial de revisar el libro de Touretzky:

Common Lisp: A Gentle Introduction to Symbolic Computation

El libro se puede descargar en PDF y Postscript. Enseña Basic Lisp básico.

+0

Gracias por el enlace a la introducción suave. He recorrido los primeros dos capítulos y tengo que decir que realmente me gustaría que este fuera el primer libro de programación que leí. Está muy bien hecho. – BlueBadger

3

También es posible usar desestructuración-bind:

(defun my-function (&rest arguments) 
    (destructuring-bind (a b &rest c) arguments 
    (format nil "~A,~A followed with ~A" a b c))) 

CL-USER> (my-function 1 2 "Give" 'me "more" 'arguments!!) 
==> "1,2 followed with (Give ME more ARGUMENTS!!)" 
0

Yo simplemente una iterate recursiva para pasar por todos ellos, supongo dolist es mejor, pero me gusta usar la antigua usanza