Funktion des idiomatischen Modus in Clojure

8

Ich lerne Clojure und hätte gerne Ratschläge zum idiomatischen Gebrauch. Als Teil eines kleinen Statistikpakets habe ich eine Funktion, um den Modus eines Datensatzes zu berechnen. (Hintergrund: Der Modus ist der gebräuchlichste Wert in einer Menge von Daten. Es gibt fast ein Dutzend veröffentlichte Algorithmen, um ihn zu berechnen. Der hier verwendete ist aus "Fundamentals of Biostatistics" 6. Ausgabe von Bernard Rosner.)

%Vor%

Es gibt ein paar Dinge, über die ich Fragen habe:

  1. Das Argument. Die Funktion akzeptiert eine einzelne Sequenz. Ist es idiomatischer, eine variable Anzahl von Argumenten wie die Additionsfunktion zu akzeptieren?
  2. Code Geruch. Es scheint, als wäre das "Let" etwas komplizierter als es sein sollte - so viele variable Zuweisungen. Habe ich irgendwelche offensichtlichen (oder nicht so offensichtlichen) Verwendungen der Sprache oder der Bibliothek verpasst, die diese Methode prägnanter machen?

Vielen Dank im Voraus für die Hilfe.

    
clartaq 21.10.2009, 14:45
quelle

4 Antworten

4

Hier ist mein Beispiel:

  1. Es gibt viele Core-Clojure-Funktionen, die Sequenzen als Argumente verwenden, während andere mehrere Argumente verwenden. Daher gibt es meiner Meinung nach keine echte idiomatische Methode. Wenn Sie bereits Ihre Daten in einer Sequenz haben, würde ich eine Seq als Argument verwenden, da es Ihnen einen Aufruf zum Anwenden erspart.

  2. Ich würde keine Funktion schreiben, die in einigen Fällen einen Wert und in anderen eine Werteliste zurückgibt, weil der aufrufende Code immer den Rückgabewert prüfen muss, bevor er verwendet wird. Stattdessen würde ich einen einzelnen Modus als Seq mit nur einem Element zurückgeben. Aber Sie haben möglicherweise Ihre Gründe, abhängig von dem Code, der diese Funktion aufruft.

Ansonsten würde ich die Mode-Funktion wie folgt umschreiben:

%Vor%

Anstatt eine Funktion f zu definieren, können Sie die Identity-Funktion verwenden (es sei denn, Ihre Daten enthalten logisch falsche Werte). Aber das brauchst du nicht einmal. Ich finde die Modi auf eine andere Art und Weise, die für mich besser lesbar ist: Die Map-Amap fungiert als eine Folge von Map-Einträgen (Schlüssel-Wert-Paaren). Zuerst filtere ich nur diejenigen Einträge, die den Wert mx haben. Dann ordne ich die Schlüsselfunktion auf diesen zu und gebe mir eine Folge von Schlüsseln.

Um zu prüfen, ob es irgendwelche Modi gibt, schleife ich nicht mehr über die Karte. Stattdessen vergleiche ich nur die Anzahl der Modi mit der Anzahl der Karteneinträge. Wenn sie gleich sind, haben alle Elemente die gleiche Häufigkeit!

Hier ist die Funktion, die immer eine seq zurückgibt:

%Vor%     
Christian Berg 21.10.2009, 17:26
quelle
5

Meiner Meinung nach ist es ein Zeichen,% ce_de% zu verwenden, wenn man eine Funktion einer Sammlung zuordnet und die Liste dann sofort auf ein Element herunterrechnet.

%Vor%

In diesem Fall würde ich das reduce fn schreiben, um eine einzelne Sammlung als Argument zu nehmen, wie Sie es getan haben. Der einzige Grund, warum ich mir vorstellen kann, mehrere Argumente für eine Funktion wie diese zu verwenden, ist, wenn Sie wörtliche Argumente sehr oft eingeben müssen.

Also, wenn z.B. Dies ist für ein interaktives REPL-Skript, und Sie werden oft mode wörtlich eingeben, dann sollten Sie die Funktion mehrere Argumente nehmen lassen, um Sie davor zu bewahren, die zusätzliche (mode [1 2 1 2 3]) im Funktionsaufruf die ganze Zeit einzugeben. Wenn Sie vorhaben, viele Zahlen aus einer Datei zu lesen und dann den Modus dieser Zahlen zu verwenden, dann nehmen Sie die Funktion ein einzelnes Argument, das eine Sammlung ist, so dass Sie sich die ganze Zeit über [] sparen können. Ich vermute, dass Ihr häufigster Anwendungsfall der letztere ist. Ich glaube, dass apply auch Overhead hinzufügt, den Sie vermeiden, wenn Sie einen Funktionsaufruf haben, der ein Collection-Argument annimmt.

Ich stimme anderen zu, dass Sie apply eine Ergebnisliste zurückgeben sollten, auch wenn es nur eine gibt; Es wird dein Leben leichter machen. Vielleicht benennen Sie es um mode , während Sie gerade dabei sind.

    
Brian Carper 21.10.2009 18:00
quelle
4

Hier ist eine nette, übersichtliche Implementierung von mode :

%Vor%

Dies nutzt die folgenden Fakten:

  • Die Funktion frequencies gibt eine Zuordnung von Werten zurück - & gt; Frequenzen
  • Sie können eine Map als eine Folge von Schlüssel / Wert-Paaren behandeln
  • Wenn Sie diese Sequenz nach Wert sortieren (das second -Objekt in jedem Paar), dann repräsentiert das letzte Element in der Sequenz den Modus

BEARBEITEN

Wenn Sie den Mehrfachmodus bearbeiten möchten, können Sie ein zusätzliches partition-by einfügen, um alle Werte mit der maximalen Häufigkeit beizubehalten:

%Vor%     
mikera 19.08.2012 05:13
quelle
2

Sieht gut aus für mich. Ich würde das

ersetzen %Vor%

mit

%Vor%

(Ich weiß nicht, warum etwas wie not-nil? nicht in clojure.core ist; es ist etwas, was man jeden Tag braucht.)

  

Wenn es einen einzigen eindeutigen Modus gibt, wird dieser zurückgegeben. Wenn mehrere Modi vorhanden sind, werden sie als Liste zurückgegeben. Wenn es keinen Modus gibt, dh alle Elemente sind in gleicher Häufigkeit vorhanden, wird nil zurückgegeben. "

Man könnte darüber nachdenken, einfach jedes Mal eine Seq zurückzugeben (ein Element oder leer ist in Ordnung); Andernfalls müssen die Fälle nach dem aufrufenden Code unterschieden werden. Indem Sie immer einen seq zurückliefern, wird Ihr Ergebnis auf magische Weise als Argument für andere Funktionen dienen, die eine seq. Erwarten.

    
pmf 21.10.2009 17:13
quelle

Tags und Links