Ich weiß nicht, ob es irgendwo einen Wettbewerb gibt, aber eventuell könnte ich eine weitere ausgefallene Variante einreichen, die wieder einmal die Primzahlen (allerdings nur in den alleruntersten Regionen) "berechnet". Das Besondere dabei, ich habe sie vollständig mit LINQ umgesetzt:
int Obergrenze = 200;
var prims = from z in Enumerable.Range(2, Obergrenze-1)
let c = (from z1 in Enumerable.Range(2, Convert.ToInt32(Math.Sqrt(z))) where z % z1 == 0 select z1).Count()
where c == 0
select z;
Console.WriteLine("Anzahl Prims: {0}", prims.Count());
Es kann sein, dass es noch elegantere Varianten gibt (es gibt mit Sicherheit einfachere), aber es ist schon faszinierend, dass dieses kleine Beispiel ohne die übliche for-Schleife und if-Entscheidung auskommt (zugegeben, es lässt sich ein wenig schwerer debuggen und man tüffelt im Allgemeinen eine Weile bis es wirklich funktioniert).
Die VB.NET-Variante unterscheidet sich nur geringfügig. Die folgende Variante stammt übrigens aus einem der zahlreichen C#->VB.NET-Konverter, die man im Web findet:
Dim Obergrenze As Integer = 200
Dim prims = From z In Enumerable.Range(2, Obergrenze - 1) _
Let c = (From z1 In Enumerable.Range(2, Convert.ToInt32(Math.Sqrt(z))) Where z Mod z1 = 0 Select z1).Count() _
Where c = 0 Select z
Die Konvertierung ging sehr schnell, nur kam der Converter nicht damit klar, dass sich die LINQ-Anweisung über mehrere Zeile erstreckt, so dass noch ein wenig Nachbearbeitung erforderlich war. Mit SharpDevelop wäre das nicht passiert, der wirklich geniale Codekonventierer fügt z.B. auch die erforderlichen Zeilenumbruchzeichen ein.
LINQ ist eine tolle Sache, funktionale Programmierung auch, wenngleich sie nicht für alles eingesetzt werden kann und sollte (man gelangt ansonsten schnell zu einem Punkt, wo man bereits einen if-Befehl als"unanständig" empfindet, was natürlich nicht die richtige Einstellung ist).
Da ich mich gerade ein wenig mit F# beschäftige (Oliver Sturms Vortrag auf der letzten Basta! hatte mich dazu inspiriert - Oliver ist nach Oliver Pocher sicher der meistge - und besuchte Mann im Web, auf seiner Homepage hat er die Vortragsfolien zu seinem F#-Vortrag leider nicht versteckt), habe ich mich noch an einer F#-Varianten versucht. Hier ist das Ergebnis. Zuerst "konventionell":
let mutable IsNoPrim = false
let mutable j = 2
for i = 2 to 100 do
j <- 2
while j < i do
if i % j = 0 then IsNoPrim <- true
j <- j + 1
if not IsNoPrim then printfn "<%i>" i
IsNoPrim <- false
Diese Variante enthält zwar zu 100% syntaktisch korrekten F#-Code, hat aber mit funktionaler Programmierung nichts zu tun und würde in C# und VB-.NET praktisch in identischer Form umgesetzt werden. Lediglich das "mutable"-Schlüsselwort wäre dort ein wenig ungewöhnlich, denn weder der C#- noch der VB.NET-Compiler haben etwas dagegen, einer Variablen einen neuen Wert zuzuweisen.
Bei folgender typischen F#-Varianten geht es bereit ein wenig mehr "ab":
let Obergrenze = 100
let Zahlen = [1..Obergrenze]
let MaxTestwert = System.Convert.ToInt32(System.Math.Sqrt(System.Convert.ToDouble(Obergrenze)))
let CheckPrim n =
not ( {2 .. MaxTestwert} |> Seq.filter (fun d -> n % d = 0) |> Seq.nonempty )
let prims = [2 .. 25] |> List.filter CheckPrim
printfn "%A" prims
F# kennt einige Sprachelemente, die ich vorher schon der PowerShell kannte - etwa den Bereichsoperator ([1..Obergrenze] und natürlich die Argumentpipeline (|>), durch die z.B. ein komplettes Array einer Filterfunktion zugeführt werden kann. Warum es funktioniert, habe ich zwar noch nicht zu 100% verstanden, aber es funktioniert. Seq.nonempty stammt aus der FSharp.PowerPack.dll, auf die noch ein Verweis gesetzt werden muss.
F# ist mit Sicherheit eine faszinierende Sprache, aber nicht leicht zu lernen. Aber ich empfehle es jedem Entwickler im .NET-Bereich, der Zeit und die erforderliche innere Ruhe hat. Bereits das kleine "Tutorial", das als Projektvorlage angeboten wird, gibt einen guten Überblick. Es gibt ein gutes Wikibook und natürlich jede Menge Beispiele und Tutorials bei MSDN. Wer einen gründlichen Überblick wünscht, lädt sich die knapp 200 Seiten starke "Language Specification" herunter.
F# gibt es für VS 2005/2008 und ist fester Bestandteil von VS 2010. Und es gibt sogar eine Version für Mono. Den Download für VS 2008 (May 2009 CTP) gibt es hier. Wer nur die Express Editionen besitzt, lädt sich die "freie" VS 2008 Shell herunter, zu der F# ebenfalls nachträglich dazu installiert werden kann. Auch SharpDevelop besitzt eine F#-Projektvorlage, aber keine Intellise-Unterstützung (auf die man aber auch verzichten kann).
Ich bin gespannt, ob es ein F# Express geben (ich gehe einmal davon aus) - wenn in knapp 2 Wochen die Beta 2 freigegeben wird, wissen wir unter Umständen mehr.
PS: Die Slides von Oliver Sturms F#-Vorträgen gibt es doch (man muss nur danach suchen) - hier ist der Link http://www.sturmnet.org/blog/2009/09/22/slides-and-samples-from-basta-2009