Schreiben von idiomatischem Funktionscode in Clojure [1], wie würde man eine Funktion schreiben, die eine Zeichenkette durch Whitespace teilt, aber zitierte Phrasen intakt hält? Eine schnelle Lösung ist natürlich, reguläre Ausdrücke zu verwenden, aber dies sollte ohne sie möglich sein. Auf den ersten Blick scheint es ziemlich schwer zu sein! Ich habe eine ähnliche in Imperativ-Sprachen geschrieben, aber ich würde gerne sehen, wie ein funktionaler, rekursiver Ansatz funktioniert.
Eine schnelle Überprüfung, was unsere Funktion tun sollte:
%Vor%Es macht mir nichts aus, wenn sich der Abstand zwischen den Anführungszeichen ändert (so dass man zuerst einfaches Teilen durch Leerzeichen verwenden kann).
%Vor%[1] Diese Frage könnte im allgemeinen beantwortet werden, aber ich denke, dass ein funktioneller Ansatz in Clojure leicht in Haskell, ML usw. übersetzt werden kann.
Hier ist eine Version, die einen Lazy Seq von Wörtern / zitierten Strings zurückgibt:
%Vor%Ein Testlauf:
%Vor%Wenn einzelne Anführungszeichen in der Eingabe nicht korrekt übereinstimmen, wird alles aus dem letzten Anführungszeichen als ein "Wort" genommen:
%Vor%Update: Eine andere Version als Antwort auf den Kommentar von edbond, mit besserem Umgang mit Zitatzeichen in Wörtern:
%Vor%Ein Testlauf:
%Vor% Diese Lösung ist in Haskell, aber die Hauptidee sollte auch in clojure gelten.
Zwei Parserzustände (innerhalb oder außerhalb von Anführungszeichen) werden durch zwei gegenseitig rekursive Funktionen repräsentiert.
Hier ist eine Clojure-Version. Dies bläst wahrscheinlich den Stack für sehr große Eingaben. Ein Regex oder echter Parser-Generator wäre viel prägnanter.
%Vor%Ihre Eingaben:
%Vor% Es war Brian möglich, Trampoline zu benutzen, damit der Stapelraum nicht ausging. Grundsätzlich make slurp-word
und parse*
return Funktionen, anstatt sie auszuführen und dann parse
ändern, um trampoline
Benutze Regex:
%Vor%Das erste Zeichen in Regex ist das Zeichen, mit dem Sie die Zeichenfolge teilen wollen - hier ist es mindestens ein Leerzeichen.
Und wenn Sie das Anführungszeichen ändern möchten, ändern Sie einfach jedes 'zu etwas anderem wie /".
EDIT: Ich habe gerade gesehen, dass du explizit erwähnt hast, dass du Regex nicht benutzen willst. Entschuldigung!
Oh mein Gott, die gegebenen Antworten scheinen meine zu übertrumpfen, jetzt da ich die Tests erfolgreich hatte. Jedenfalls poste ich es hier, um ein paar Kommentare über die Idiomatisierung des Codes zu erbitten.
Ich skizzierte eine haskellische Pseudo:
%Vor%Okay, schlecht benannt. Dort
pl
verarbeitet die Wörter nicht zitiert pli
(i wie in inner) verarbeitet die zitierten Phrasen p
ist die bereits verarbeitete (done) Information w:ws
ist die zu verarbeitende Information Ich habe das Pseudo so übersetzt:
%Vor%Nicht sehr Clojuresque, die Details. Ich bin auch auf Regexp beim Teilen und Entfernen der Anführungszeichen angewiesen, deshalb sollte ich deswegen einige Downvotes verdienen.
Tags und Links clojure functional-programming recursion