2010-05-30 12 views
6

ich vorbei in Befehlszeilenargumente zu meinem Lisp-Programm und sie werden so formatiert, wenn sie meine Hauptfunktion getroffen:Anruffunktion auf eine Zeichenfolge basiert

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

Ich habe eine Punktfunktion (die zwei Vektoren nimmt als Argumente) und möchte es direkt aus dem Argument aufrufen, aber das ist nicht möglich, weil etwas wie (funcall (zweite Argumente) ...) "Punkt" und nicht Punkt als Funktionsname erhält.

Ich habe versucht, Variationen dieser Funktion:
(defun remove-quotes (s)
(setf (aref s 0) '""))

ohne Erfolg, bevor Sie feststellen, dass die Zitate nicht wirklich ein Teil des Strings waren. Gibt es einen einfachen Weg dies zu tun, oder sollte ich nur jeden String überprüfen und dann die entsprechende Funktion aufrufen?

Antwort

8

"1 1 1" ist eine Zeichenfolge aus fünf Zeichen: 1, Leerzeichen, 1, Leerzeichen und 1. Die doppelten Anführungszeichen sind nicht Teil der Zeichenfolge.

("1 1 1" "Punkt" "2 2 2") ist eine Liste von drei Strings.

Es gibt keine "Zeichen oben. Die" werden verwendet, um Zeichenfolgen in s-Ausdrücken zu begrenzen.

Wenn Sie eine Punktfunktion haben, müssen Sie uns sagen, welche Art von Eingabedaten es erwartet. Erwartet es zwei Listen von Zahlen? Dann müssen Sie die Zeichenfolge "1 1 1" in eine Liste von Zahlen konvertieren.

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

Um die Funktion DOT aus der Zeichenkette "dot" zu erhalten, suchen Sie zuerst das Symbol DOT und dann die Symbolfunktion.

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

Suche-Symbol Man könnte auch das Paket angeben muß, wenn es ein spezielles Paket ist, wo das Symbol befindet.

eine Liste mit einem Vektor Konvertierung dann der Block nächsten Gebäude ist.

Also müssen Sie die Argumente für Ihre Funktion in Vektoren konvertieren (wahrscheinlich zuerst in Listen umwandeln, wie ich oben gezeigt habe). Dann müssen Sie die Funktion finden (siehe oben). Wenn Sie dann die Funktion und die Argumente haben, dann können Sie die Funktion mit FUNCALL oder APPLY aufrufen (was auch immer praktischer ist).

+0

Ich verstehe nicht ganz die Iterationsmethode oben und ich bekomme eine Endlosschleife, wenn ich es zu laufen versuchen – powerj1984

+0

@ powerj1984. : Ich habe UNLESS mit UNTIL ersetzt, sollte jetzt funktionieren –

2

Die Frage ist ein wenig unklar, aber soweit ich es verstehe, wollen Sie, wenn die Liste ("1 1 1" "dot" "2 2 2") als Eingabe gegeben, um den Ausdruck (dot "1 1 1" "2 2 2") auszuwerten. In diesem Fall können Sie dies tun:

(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

Sorry meine Frage ist unklar, das ist sehr ähnlich zu dem, was ich will - dot nimmt zwei Vektoren als Argumente, aber Sie haben mich auf dem richtigen Weg, danke! – powerj1984

2

funcall nicht akzeptiert eine Zeichenfolge als Funktion Bezeichner. Sie müssen es stattdessen ein Symbol geben. Was Sie wahrscheinlich tun möchte, ist:

  1. Konvertieren der Zeichenfolge in Großbuchstaben (Lisp-Symbole sind in der Regel Großbuchstaben, und auch wenn es wie Lisp aussehen kann, ist Groß- und Kleinschreibung, das ist nur, weil der Leser alle Symbole upcases es liest standardmäßig) (string-upcase).
  2. Erstellen oder suchen Sie ein Symbol mit dem angegebenen Namen (intern).Beachten Sie, dass, wenn *package* nicht gemäß dem Paket festgelegt ist, in dem der Name Ihrer Funktion gespeichert ist, müssen Sie den Paketnamen als zweites Argument an intern übergeben.

Zum Beispiel (für eine Funktion dot in Paket mit dem Namen cl-user:

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