2010-05-30 9 views
6

sto passando in argomenti della riga di comando per il mio programma Lisp e sono formattati come questo, quando hanno colpito la mia funzione principale:la funzione di chiamata in base a una stringa

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

Ho una funzione di punti (che prende due vettori come argomenti) e vorrei chiamarlo direttamente dall'argomento, ma ciò non è possibile perché qualcosa come (funcall (second args) ...) riceve "dot" e non dot come nome della funzione.

Ho provato variazioni di questa funzione:
(defun remove-quotes (s)
(setf (aref s 0) '""))

inutilmente, prima di capire che le citazioni non erano veramente una parte della stringa. C'è un modo semplice per farlo, o dovrei semplicemente controllare ogni stringa e poi chiamare la funzione appropriata?

risposta

8

"1 1 1" è una stringa di cinque caratteri: 1, spazio, 1, spazio e 1. Le virgolette doppie non fanno parte della stringa.

("1 1 1" "punto" "2 2 2") è un elenco di tre stringhe.

Non ci sono "caratteri sopra." Vengono utilizzati per delimitare le stringhe nelle espressioni s.

Se si dispone di una funzione punto è necessario dirci che tipo di dati di input si aspetta. Si aspetta due liste di numeri? Quindi devi convertire la stringa "1 1 1" in una lista di numeri.

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

Per ottenere la funzione DOT dal "dot" stringa prima trovare il simbolo del punto e quindi ottenere la sua funzione di simbolo.

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

per Find-simbolo uno potrebbe essere necessario specificare anche il pacchetto, se v'è un pacchetto speciale in cui il simbolo è in.

Conversione di un elenco per un vettore, allora è il blocco di costruzione successiva.

Quindi è necessario convertire gli argomenti della funzione in vettori (probabilmente prima convertendoli in elenchi come mostrato sopra). Quindi devi trovare la funzione (vedi sopra). Se hai la funzione e gli argomenti, puoi chiamare la funzione usando FUNCALL o APPLY (qualunque cosa sia più conveniente).

+0

io non capisco il metodo di iterazione sopra e ottengo un ciclo infinito quando si tenta di eseguire – powerj1984

+0

@ powerj1984. : Ho sostituito UNLESS con UNTIL. Dovrebbe funzionare ora. –

2

La domanda è un po 'oscura, ma per quanto ho capito, quando viene fornito l'elenco ("1 1 1" "dot" "2 2 2") come input per valutare l'espressione (dot "1 1 1" "2 2 2"). In questo caso si può fare questo:

(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

Mi spiace che la mia domanda non sia chiara, che è molto simile a quello che voglio: dot prende due vettori come argomenti, ma tu mi hai messo sulla buona strada, grazie! – powerj1984

2

funcall non accetta una stringa come una funzione designatore. Devi invece dargli un simbolo. Quello che probabilmente vuole fare è:

  1. Convertire la stringa in maiuscolo (simboli Lisp sono casi di solito superiore, e anche se può sembrare Lisp è case-insensitive, questo è solo perché il lettore upcases tutti i simboli che legge per impostazione predefinita) (string-upcase).
  2. Creare o trovare un simbolo con il nome specificato (intern).Si noti che, se *package* non è impostato in base al pacchetto in cui risiede il nome della propria funzione, è necessario fornire il nome del pacchetto come secondo argomento a intern.

Per esempio (per una funzione denominata dot nel pacchetto cl-user:

(funcall (intern (string-upcase "dot") 'cl-user) ...) 
Problemi correlati