Clojure-Variablen und Schleifen

7

Beim googlen habe ich festgestellt, dass die Verwendung von while loops oder die Verwendung von Variablen nicht empfohlen wird.

Nun habe ich einen sehr einfachen Algorithmus implementiert, der Zeichen aus einem Eingabestream liest und entsprechend analysiert: Wenn die Eingabe 10:abcdefghej ist, wird 10 analysiert und dann die nächsten 10 Bytes nach dem Doppelpunkt gelesen.

Das Ding, mit dem ich irgendwie verloren bin, ist, wie ich das umgestalten kann, so dass es nicht auf Variablen beruht.

%Vor%

Ich verstehe auch, dass die einzige Möglichkeit, Variablen zu deklarieren, das Schlüsselwort with-local-vars ist. Ist es nicht unpraktisch, am Anfang alle Variablen in einem Block zu definieren, oder fehlt mir ein entscheidender Punkt?

    
Hamza Yerlikaya 28.06.2009, 03:31
quelle

4 Antworten

10

Ein bisschen spät zu dieser Party, nehme ich an, aber das Problem ist viel einfacher, wenn Sie die Zeichenfolge nur als eine Folge von Zeichen behandeln und Clojures Sequenz-Handling-Primitive verwenden:

%Vor%

Eine Zusammenfassung:

  • Konvertieren Sie den hässlichen, nebenwirkungsvollen Eingabestream in eine langsame Folge von Zeichen, sodass wir vorgeben können, dass es nur eine Zeichenfolge für den Rest dieses Vorgangs ist. Wie Sie sehen können, werden tatsächlich keine Zeichen mehr aus dem Stream gelesen, als zur Berechnung des Ergebnisses notwendig sind.
  • Teilen Sie die Zeichenfolge in zwei Teile: die ersten halben Zeichen vor dem ersten Doppelpunkt und die zweite Hälfte, was noch übrig ist.
  • Verwenden Sie das Destrukturieren, um diese Teile an die lokalen Namen before und after zu binden, und streichen Sie die : aus, während wir dabei sind, indem Sie sie an eine unbenutzte lokale Komponente mit dem Namen colon für die Beschreibung binden.
  • Lies before , um seinen numerischen Wert zu erhalten
  • Nimm so viele Zeichen aus after und zerquetsche sie alle zu einer Zeichenkette mit (apply str)

Svantes Antwort ist ein hervorragendes Beispiel dafür, wie man mit Clojure loop-isch Code schreibt; Ich hoffe, dass meins ein gutes Beispiel dafür ist, die eingebauten Funktionen so zusammenzustellen, dass sie genau das tun, was Sie brauchen. Sicherlich lassen beide die C-Lösung alles andere als "sehr einfach" aussehen!

    
amalloy 04.09.2011, 09:50
quelle
18

Was Sie schreiben, ist C-Code mit lisp-artiger Syntax (nichts für ungut). Einen Stil zu definieren, indem man nicht tut ist sehr definierend, aber es ist nicht sehr hilfreich, wenn man nicht weiß, "wie, sonst wie?"

Übrigens, ich weiß nicht, was indicator tun soll.

So würde ich dieses Problem angehen:

  1. Das Problem besteht aus zwei Teilen: Finden Sie die Anzahl der zu lesenden Zeichen und lesen Sie dann diese vielen Zeichen. Daher würde ich zwei Funktionen schreiben: read-count und read-item , wobei letztere die erstere verwendet.

    %Vor%
  2. read-item muss zuerst die Anzahl der zu lesenden Zeichen bestimmen. Dazu verwendet es die bequeme Funktion read-count , die wir ebenfalls definieren.

    %Vor%
  3. Das Schleifen wird in Clojure im Allgemeinen am besten gehandhabt, indem loop und recur verwendet werden. loop bindet auch Variablen wie let . acc soll die gelesenen Elemente ansammeln, beachten Sie jedoch, dass es nicht an Ort und Stelle geändert wird, sondern jede Iteration neu gebunden wird.

    %Vor%
  4. Nun müssen wir etwas in dieser Schleife tun: bind c an das nächste Zeichen, aber return acc , wenn count 0 ist. (zero? count) ist dasselbe wie (= count 0) . Ich habe die if -Form für diejenigen, die damit nicht vertraut sind, kommentiert.

    %Vor%
  5. Jetzt brauchen wir nur noch die Funktion read-count . Es verwendet eine ähnliche Schleife.

    %Vor%
  6. Testen Sie es auf der REPL, debuggen, refactor. Liefert .read wirklich Zeichen zurück? Gibt es eine bessere Möglichkeit, eine ganze Zahl zu analysieren?

Ich habe das nicht getestet, und ich bin etwas behindert, weil ich weder Erfahrung noch tiefe Kenntnisse von Clojure habe (ich benutze meistens Common Lisp), aber ich denke, dass es zeigt, wie man sich dieser Art von Problem in einer "Lispy" nähert "Weise. Beachten Sie, wie ich Variablen nicht deklarieren oder ändern kann.

    
Svante 28.06.2009 12:25
quelle
6

Idomatic Clojure eignet sich sehr gut zum Arbeiten mit Sequenzen. In C tendiere ich dazu, in Begriffen von Variablen zu denken oder den Zustand einer Variablen mehrmals zu ändern. In Clojure denke ich in Sequenzen. In diesem Fall würde ich das Problem in drei Abstraktionsschichten aufteilen:

  • Den Stream in eine Bytefolge umwandeln.
  • wandelt die Bytefolge in eine Zeichenfolge um
  • übersetzt die Zeichenfolge in eine Folge von Strings.

stream zu Bytes:

%Vor%

Bytes zu Zeichen

%Vor%

Zeichenfolgen [chars]

%Vor%

Dies wird träge bewertet, so dass jedes Mal, wenn die nächste Zeichenkette benötigt wird, diese aus dem Eingabestrom gezogen und konstruiert wird. Sie könnten dies beispielsweise in einem Netzwerkstream verwenden, ohne den gesamten Stream zuerst puffern zu müssen oder sich darum sorgen zu müssen, dass der Code, der von diesem Stream gelesen wird, sich Gedanken darüber macht, wie er aufgebaut ist.

ps: ich bin im Moment nicht an meiner REPL, also bitte editieren, um irgendwelche Fehler zu beheben:)

    
Arthur Ulfeldt 01.02.2010 23:33
quelle
3

Ich lerne Clojure selbst, also nimm das nicht als Guru-Rat, sondern als Rat eines Kommilitonen.

Clojure ist eine funktionale Programmiersprache. Funktionale Programmierung bedeutet keine Schleifen, keine Variablen und keine Nebenwirkungen. Wenn Sie jemals von diesen drei Regeln abweichen, brauchen Sie sehr gute Gründe dafür und gültige Gründe sind ziemlich selten.

Sie sind offensichtlich ein sehr geübter Programmierer, also schauen Sie sich diese Informationen an und Sie sollten hoffentlich eine bessere Vorstellung davon bekommen, wie sich funktionales Design von objektorientiertem Design unterscheidet.

Ссылка

Auch würde ich empfehlen, einen Clojure-Code anzuschauen, hier ist ein Beispielprogramm, auf dem gehostet wird github.com wurde geschrieben, um Teil eines clojure Screencast-Tutorials zu sein.

Ссылка

Das Screencast-Tutorial, für das der Code gedacht war, kann hier gefunden werden, ist aber nicht kostenlos:

Ссылка

(Ich bin sowieso nicht mit peepcode.com verbunden).

Viel Glück mit Clojure!

    
Alex Combas 28.06.2009 11:14
quelle

Tags und Links