F#, Funktionale Programmierung mit .NET, Teil 4
19. August 2008 – 20:51 von AndreasIn diesem Teil wird das Thema List Comprehensions behandelt:
List Comprehensions
List Comprehensions erleichtern einem das Erzeugen, Konvertieren und allgemein das Arbeiten mit “Collections”. Eine List Comprehension wird in F# mit zwei Punkten verwendet “..”. Links und Rechts zwischen diesen Punkten werden die oberen und unteren Grenzwerte angegeben (also [ STARTWERT .. ENDWERT ] ). So kann z.B. mit
-
let numList = [ 0 .. 10 ]
folgende Liste erzeugt werden:
[ 0; 1; 2; 3; 4; 5; 6; 7; 8; 9; 10 ]
Der Compiler übernimmt somit die Berechnung der dazwischen liegenden Elemente. In diesem Beispiel ist das nachfolgende Element immer um 1 größer als das davor Liegende. Die Schrittweite ist also bei default 1.
Die Verwendung von List Comprehensions ist aber auch bei alphanumerischen Zeichen möglich:
-
let alphaList = [ ‘A’ .. ‘D’ ]
In alphaList stehen dann folgende Elemente:
[ ‘A’; ‘B’; ‘C’; ‘D’ ]
Ich habe aber auch die Möglichkeit die Schrittweite selbst zu beeinflussen, indem ich diese einfach mit angebe: [ STARTWERT .. SCHRITTWEITE .. ENDWERT ]
An einem konkreten Beispiel sieht dies so aus:
-
let numList = [ 10 .. -1 .. 0 ]
Die erzeugte Liste enthält dann folgende Elemente:
[ 10; 9; 8; 7; 6; 5; 4; 3; 2; 1; 0 ]
List Comprehensions können auch in Schleifen verwendet werden, um eine neue Liste mit Hilfe einer anderen zu erstellen.
Am einfachsten ist dies anhand eines Beispiels zu sehen. Hier wird die Liste [ 2; 4; 6; 8; 10; 12; 14; 16; 18; 20 ] aus der Liste [ 1; 2; 3; 4; 5; 6; 7; 8; 9; 10 ] erzeugt:
-
let doubles =
-
[ for x in 1 .. 10 -> x + x ]
Hierbei ist schön zu sehen, dass man die List Comprehension einfach in die for-Schleife einbauen kann, welche dann die zu erstellenende Liste kreiert.
Es besteht auch die Möglichkeit Bedingungen mit dem Schlüsselwort “when” einzubauen. In folgendem Beispiel verwenden wir dies, um im Bereich von 1 bis 10 eine Liste mit allen geraden Zahlen aufzubauen:
-
let evennumbers =
-
[ for x in 1 .. 10 when x % 2 = 0 -> x ]
Zum Abschluss auch für dieses Thema eine kleine (mit Hilfe der List Comprehensions) zu lösende Aufgabe:
Schreibt eine Funktion “create_matrix”, welche als Paramater die Zeilen, Spalten und einen Initialwert enthält (also “let create_matrix(rows,cols,initvalue) = …” ). Die Funktion gibt eine Liste zurück, welche wiederum für jede Zeile der Matrix wiederum eine Liste enthält.
Wird die Funktion folgendermaßen aufgerufen: “create_matrix(3,4,0)” so sollte folgende Liste (welche die 3×4-Matrix repräsentiert) erstellt und zurückgegeben werden: [ [ 0; 0; 0; 0]; [ 0; 0; 0; 0]; [ 0; 0; 0; 0] ].
Außerdem wäre es schön wenn ihr noch eine Funktion printmatrix schreiben würdet, welche die Matrix formatiert auf der Konsole ausgibt:
-
printmatrix(create_matrix(3,4,0))
Ausgabe:
Matrix:
[0; 0; 0; 0]
[0; 0; 0; 0]
[0; 0; 0; 0]
Eure Lösungen könnt ihr wie immer als Kommentar auf diesen Blogeintrag posten. Ich freue mich auf eure Einreichungen. Meine Lösung gibt es wie immer zu einem späteren Zeitpunkt als Blogeintrag. Aber jetzt seit erst einmal ihr gefragt;)…

5 Responses to “F#, Funktionale Programmierung mit .NET, Teil 4”
OK, leider nicht ganz so geworden wie ich das wollte. Leider habe ich im moment kein F# zur Hand. Deshalb habe ich eine Lösung in Erlang geschrieben und versucht diese in F# zu übertragen. create_matrix müsste funktionieren aber wenn print_matrix läuft würde mich das wirklich wundern.
-module(matrix).
-export([create/3,print/1,print2/1]).
create(Y,X,D) -> [[D||_<-lists:seq(1,X)]||_ io:format(”~p~n”,[H]);
print([H| T]) -> io:format(”~p~n”,[H]), print(T).
print2(L) -> lists:foreach(fun(Z) -> io:format(”~p~n”,[Z]) end, L).
% Ich konnte mich nicht für eine print-Methode entscheiden. Was meint ihr? Welche ist eleganter?
Und nun versucht in F# zu übertragen:
let create_matrix(rows,cols,initvalue) = [for x in 1..rows -> [for y in 1..cols -> initvalue ]]
Soweit ja noch recht einfach … aber jetzt kommts
let print_matrix(matrix : List) =
List.iter (
fun list ->
print_string “[”
List.iter print_int list
print_string “]”
) matrix
By nougad on Aug 22, 2008
Oh man, anscheinend mag kein Kommentarsystem meinen Code nicht. Hälfte wurde Zensiert. Naja RTFS… da steht das meiste drinnen.
(Außer der Satz… der wurde komplett raus gelöscht:)
Leider hat Erlang nicht die schöne Punkt-Notation wie Ruby oder F#. Deshalb mit lists:seq/2
By nougad on Aug 22, 2008
Was soll man dazu noch sagen;-): Top! Geht alles (auch print_matrix)! Und das ohne einen F# Compiler zum Testen zu haben!
Der Erlang-Teil ist echt gewöhnungsbedürftig. Aber wenn man genau hinschaut wird es klar! Danke für die Erlang-Lösung:-)!
By Andreas on Aug 22, 2008
OK, ich habe gerade gesehen das der Code keinerlei Sinn mehr ergibt, so wie er oben steht. Deshalb hier nochmal extern: http://sprunge.us/CbaS?erlang
By nougad on Aug 22, 2008