2010-05-30 16 views
6

estoy pasando en los argumentos de línea de comandos para mi programa Lisp y que tienen un formato como éste cuando llegan a mi función principal:función de Llamada basado en una cadena

("1 1 1" "dot" "2 2 2") 

Tengo una función de puntos (que tiene dos vectores como argumentos) y quisiera llamarlo directamente desde el argumento, pero esto no es posible porque algo así como (funcall (second args) ...) recibe "dot" y no dot como el nombre de la función.

me trataron variaciones de esta función:
(defun remove-quotes (s)
(setf (aref s 0) '""))

en vano, antes de darse cuenta de que las cotizaciones no eran realmente una parte de la cadena. ¿Hay una manera simple de hacerlo, o debería simplemente verificar cada cadena y luego llamar a la función apropiada?

Respuesta

8

"1 1 1" es una cadena de cinco caracteres: 1, espacio, 1, espacio y 1. Las comillas dobles no son parte de la cadena.

("1 1 1" "punto" "2 2 2") es una lista de tres cadenas.

No hay "caracteres arriba. Los" se usan para delimitar cadenas en s-expresiones.

Si tiene una función de punto, necesita decirnos qué tipo de datos de entrada espera. ¿Espera dos listas de números? Luego debe convertir la cadena "1 1 1" en una lista de números.

(with-input-from-string (in "1 1 1") 
    (loop for data = (read in nil in) 
    until (eq data in) 
    collect data))) 

Para obtener el DOT función desde el "punto" primera cadena encontrar el símbolo de punto y luego obtener su función de símbolo.

(symbol-function (find-symbol (string-upcase "dot"))) 

Para encontrar-símbolo que pueda ser necesario especificar también el paquete, si hay un paquete especial en el que el símbolo está en.

la conversión de una lista a un vector es entonces el siguiente bloque de construcción.

Por lo tanto, debe convertir los argumentos para su función en vectores (probablemente primero los convierta en listas como mostré anteriormente). Entonces necesitas encontrar la función (ver arriba). Si tiene entonces la función y los argumentos, puede llamar a la función usando FUNCALL o APPLY (lo que sea más conveniente).

+0

yo no entiendo muy bien el método de iteración arriba y consigo un bucle infinito cuando intento ejecutarlo – powerj1984

+0

@ powerj1984. : He reemplazado UNLESS con UNTIL. Debería funcionar ahora. –

2

La pregunta es un poco confusa, pero por lo que yo entiendo, cuando se le da la lista ("1 1 1" "dot" "2 2 2") como entrada para evaluar la expresión (dot "1 1 1" "2 2 2"). En ese caso se puede hacer esto:

(defun apply-infix (arg1 f arg2) 
    (apply (intern (string-upcase f)) (list arg1 arg2))) 
(defun apply-list-infix (lst) 
    (apply 'apply-infix lst)) 

(apply-list-infix '("1 1 1" "dot" "2 2 2")) 
+0

Lo siento, mi pregunta no es clara, eso es muy similar a lo que quiero - dot toma dos vectores como argumentos pero me tienes en el camino correcto, ¡gracias! – powerj1984

2

funcall no acepta una cadena como un indicador de la función. Necesitas darle un símbolo en su lugar. Lo que usted probablemente querrá hacer es:

  1. convertir la cadena en mayúsculas (símbolos Lisp son caso por lo general superior, y aunque pueda parecer que Lisp es sensible a las mayúsculas, eso es sólo porque el lector upcases todos los símbolos se lee por defecto) (string-upcase).
  2. Crea o encuentra un símbolo con el nombre de pila (intern).Tenga en cuenta que, si *package* no está configurado de acuerdo con el paquete en el que vive el nombre de su función, debe proporcionar el nombre del paquete como el segundo argumento al intern.

Por ejemplo (para una función llamada dot en el paquete cl-user:

(funcall (intern (string-upcase "dot") 'cl-user) ...) 
Cuestiones relacionadas