Debugging von Seq.sumBy

8

Ich habe versucht, mir ein paar F # zu lernen, indem ich die AdventOfCode-Lösungen des letzten Jahres angeschaut habe. Ich bin auf dieses ordentliche Stück Code gestoßen, das ich gar nicht analysieren kann:

%Vor%

Beachten Sie, ich verstehe die vorherige Zeile (in der Verknüpfung):

%Vor%

Dies erzeugt eine Funktion i , die ein integer n übernimmt und die Datei inputN.txt liest und als String zurückgibt. Daher gibt i 1 input1.txt als Zeichenfolge zurück.

Dann leitet |> nur die Zeichenfolge (oder das Array von Zeichen?) als ersten Parameter an die nächste Funktion weiter, die Seq.sumBy

ist

Aber dann fangen die Dinge an zu brechen ...

sumBy scheint einfach genug zu sein:

  

Gibt die Summe der Ergebnisse zurück, die durch Anwenden der Funktion auf jedes Element der Liste generiert wurden.

Aber das IndexOf einer Zeichenkette " (" hat mich verwirrt.

Nun, ich möchte hier eigentlich keine Fische, was ich gerne wissen würde ist das. Als Neuling in dieser Fremdsprache, während ich lerne, mehr Bits von F # zu bearbeiten, wie kann ich dieses Stück Code nehmen und in kleinere Stücke zerlegen, um es zu testen, um herauszufinden, was vor sich geht? Es macht mich verrückt, dass ich die Lösung habe, habe google / so, und ich kann diesen Code immer noch nicht verstehen.

Kann mir jemand kleinere Schnipsel zeigen, damit ich die Antwort selbst herausfinden kann?

    
Joshua Ball 09.12.2016, 19:01
quelle

2 Antworten

7

FSI ist dein Freund. Ich benutze es oft, um zu verstehen, wie Funktionen abgebaut werden können. Wenn Sie den Ausdruck " (".IndexOf in FSI einfügen, sieht es auf den ersten Blick nicht so aus:

%Vor%

Wie Sie bereits herausgefunden haben, ist " (" eine Zeichenfolge und IndexOf ist eine Methode für string . In der Tat gibt es einige Überladungen von dieser Methode, aber nur zwei mit arity 1.

Eine dieser Überladungen nimmt eine char als Eingabe und die andere eine string als Eingabe.

Der Ausdruck " (".IndexOf ist eine Funktion. Es ist die Kurzform von fun x -> " (".IndexOf x .

Sie haben auch bereits festgestellt, dass string implements char seq implementiert. Wenn Sie also das Modul Seq verwenden, sehen Sie sich jedes Element der Sequenz an. In diesem Fall ist jedes Element ein char , also muss die hier verwendete Überladung diejenige sein, die ein char als Eingabe verwendet.

Nachdem Sie nun herausgefunden haben, welche Überladung verwendet wird, können Sie in FSI damit experimentieren:

%Vor%

Offensichtlich sucht die Funktion nach dem Index jeder Eingabe char in " (" , also erhalten Sie jedes Mal, wenn Sie in '(' übergeben werden, 1 (weil es nullindiziert ist), und wenn die Eingabe% ist co_de%, der Rückgabewert ist ' ' . Für alle anderen Werte lautet der Rückgabewert 0 .

Eine Eingabezeichenfolge wie -1 ist auch ein "(foo bar)" . Anstatt eine char seq auszuführen, können Sie versuchen, sie in sumBy zu pipen, um zu verstehen, wie jedes Element übersetzt wird:

%Vor%

Nun übersetzt Seq.map nur, aber Seq.map nimmt alle diese Zahlen und fügt sie zusammen:

%Vor%

Ich kann immer noch nicht erraten, was der Zweck ist, aber dann habe ich nie die Eingabezeichenfolge gesehen ...

    
Mark Seemann 09.12.2016, 19:49
quelle
8

Also können wir das in Stücke brechen.

%Vor%

Sie haben Recht bezüglich des Abschnitts i 1 . Dies liest input1.txt und gibt dir den gesamten Text als string .

Also, der erste Schlüssel hier ist, dass String implementiert IEnumerable<char> ( char seq ), was bedeutet, dass es etwas ist, das aufgezählt werden kann.

Als nächstes schauen wir uns den Teil innerhalb der Parens an:

%Vor%

Der erste Teil ist nur eine Zeichenfolge: " (" und IndexOf ist eine Methode für die Zeichenfolge. Es gibt den nullbasierten Index eines bestimmten Zeichens zurück, oder -1, falls es nicht existiert.

Da es sich um eine Methode handelt, können Sie sie als Funktion verwenden. So kann " (".IndexOf wie folgt aussehen:

%Vor%

--------- Stoppen Sie hier, es sei denn, Sie wollen die vollständige Antwort im Detail erklärt --------

In diesem Fall, wenn das Eingabezeichen ' ' ist, wird 0 zurückgegeben, wenn es '(' ist, wird 1 zurückgegeben, und wenn es etwas anderes ist, wird -1 zurückgegeben.

Das Seq.sumBy nimmt jedes Zeichen der Eingabezeichenfolge und leitet es in diese Funktion ein, und addiert es dann mit dem Ergebnis. Das bedeutet, dass jede Eingabe '(' 1 addiert, jede Eingabe ' ' 0 addiert, und alles andere fügt -1 hinzu (was in diesem Fall ')' Zeichen ist. Eine Zeichenfolge wie diese "()" wird füge 1 hinzu und füge dann -1 hinzu, was zu 0 führt, was mit dem Ziel der Advent-Herausforderung Tag 1 übereinstimmt.

>     
Reed Copsey 09.12.2016 19:43
quelle

Tags und Links