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
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?
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:
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:
Nun übersetzt Seq.map
nur, aber Seq.map
nimmt alle diese Zahlen und fügt sie zusammen:
Ich kann immer noch nicht erraten, was der Zweck ist, aber dann habe ich nie die Eingabezeichenfolge gesehen ...
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:
--------- 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.