Apple Swift ein F# Klon?

Am 2. Juni hat Apple an der WWDC14 ihre neue Funktionale Programmiersprache präsentiert. Apple’s neue Programmiersprache Swift scheint auf den ersten Blick nahezu ein F# Klon zu sein. Die Syntax von Swift sieht abgesehen von den { } zu verwechseln ähnlich aus wie F#. Wie kommt das? Aus sicherer Quelle ist zu erfahren, dass bei Apple ein ehemaliger Microsoft Mitarbeiter aus dem F# Team für Swift verantwortlich ist. Nun haben jetzt alle dieser drei verbreiteten Plattformen den Schritt in die Funktionale Zukunft gemacht.
  • Microsoft, .Net, Mono :   C#  ->  F#
  • Oracle, JEE / JVM :         Java  ->  Scala
  • Apple, Cocoa, iOS /OSX :   Objective-C  ->  Swift
Interessant ist auch das Erscheinungsdatum der Version 1.0 von wegen Ausgereiftheit und Bekanntheit. Ideal ist es, wenn die Programmiersprache mit sich selber implementiert ist (Bootstrapping, Rekursiver Kompiler, Selbst-Compiler) und der Quellcode offen verfügbar ist (Open Source), denn so hat man die Möglichkeit beim Erlernen der Sprache eine grosse Codebasis zu entdecken und zu studieren. Und man kann sicher sein, dass die Programmiersprache funktioniert, d.h. korrekt ist, denn der Compiler selbst ist ein nicht trivialer Test der kompletten Sprache. Bei F# ist beides gegeben, im Gegensatz zu Scala, das in Java implementiert ist und* Swift das wie bei Apple üblich wohl Closed Source bleiben wird. Mit Roslyn hat Microsoft genau dies für C# und VB.Net vor ein paar Monaten nachgeholt.
  • F# (2005) implementiert in F# (Open Source)
  • Scala (2003) implementiert in Java* Scala (Open Source) 1      2     3       
  • Swift (2014) implementiert in ? (Objective-C or Swift?) (Closed Source)
Den Schritt in die Funktionale Zukunft schon geplant? *) Korrektur: Dank an Soc88 (er hat Wikipedia Scala Eintrag korrigiert)

Die Strukturierung von F# Quellcode

F# Code ist sehr kompakt, weil unnötiges und redundantes entfällt. Kurz gesagt, keine ; { } und keine Typen Deklaration. So, nun im Detail alles der Reihe nach:

Keine ;

Das Ende einer Code-Zeile mit ; abzuschliessen ist in F# nicht nötig. Man kann, sieht dann aber aus wie umgewandelter C# oder C++ Code. ; werden verwendet um Aufzählungen von Records, Listen, Arrays etc. zu trennen. Wobei man auch hier, bei nur einem Element pro Zeile den ; nicht zu schreiben braucht.
1: 
2: 
3: 
4: 
5: 
6: 
7: 
let xs = [ 1; 2; 3 ] 
let xs = 
       [ 
        1
        2
        3
       ]

Keine {}

F# Code kommt ohne Code Blöcke aus die in geschweifte Klammern { } gefasst sind. Die Struktur ergibt sich aus der sauberen Einrückungen mittels Tab oder Space (white-space aware code). Die meisten Codierrichtlinen geben ja heutzutage genau eine solche Code Formatierung vor, zusätzlich zu den {} Klammern was redundant ist. Also wieso nicht die Klammer weglassen. Mag sein, dass das für manchen am Anfang etwas komisch aussieht, aber man gewöhnt sich so schnell daran. Kommen in F# doch { } vor, dann handelt sich um einen Record Type oder Computation Expressions

Wie geht denn das ohne { } Code-Blocks ?

Bei gut gestaltetem Code achtet man darauf, dass die Code-Blocks korrekt eingerückt sind. Also z.B.
 1: 
 2: 
 3: 
 4: 
 5: 
 6: 
 7: 
 8: 
 9: 
10: 
11: 
12: 
13: 
14: 
// C#
void Bar()
{
    bool b = Foo();
    if b 
    {
        FooTrue1();
        FooTrue2();
    }
    else
    {
        FooFalse();
    }
}
Das selbe in F# ist durch weglassen von ; und { } zu erreichen, bei Einhaltung der korrekten Einrückungen.
1: 
2: 
3: 
4: 
5: 
6: 
7: 
8: 
// F#   
let bar() =
    let b = foo()
    if b then
        FooTrue1()  // Die Einrückung gilt für mehrere Code Zeilen. 
        FooTrue2()       
    else
        FooFalse()
 

Keine Typen Deklaration

Es ist sicher schon aufgefallen, dass bei Funktionen keine Typen angegeben wurden.

Fehlt da dann nicht etwas, wenn im Code die Typen fehlen?

Wie geht das ohne Typen zu deklarieren? Die sogenannte Type-Inferenz findet selbst heraus um welchen Type es sich handeln muss. Man stelle sich vor, man ruft eine API-Funktion auf die data als Parameter entgegennimmt. Diese Funktion verarbeitet int array, somit ist data vom Type int array, also muss man data nicht extra deklarieren. In Visual-Studio oder auch im Blog Code hier, zeigt ein Tooltip über dem jeweiligen Wert oder Funktion dessen Type an, wenn man überprüfen will was es denn nun ist.
Der Code wird dadurch schlanker zu lesen und auch zu schreiben. Wobei Code ja mehr gelesen (Code Review) als geschrieben wird, ist das sehr nützlich, denn Kompakter Code ist schneller zu verstehen!
Kompakter Code, nicht im Sinne von alles auf eine Zeile quetschen, ist schneller zu verstehen, als wenn man Seitenweise lesen muss und sich immer die Typen Deklaration mitdenken muss. Überlassen wir die Typen dem “Compiler”, der prüft diese, und zwar schon vor dem Compilieren, die TypeInference die das erledigt läuft im Editor mit. Passt etwas nicht, wird die Stelle mit der bekannten rote Wellenlinie unterstrichen. Im Tooltip dazu wird erklärt was da nicht passt und was das Problem lösen kann.
Wir kümmern uns darum WAS gemacht wird. Ob alles passt, darum kümmert sich die TypeInference. Es ermöglicht ein abstrakteres Denken, wenn man sich nicht um die Typen Details kümmern muss und spart Entwicklungszeit.
Dies führt zum oft erwähnten positiven Effekt, den man dabei erlebt, dass wenn alles passt, der Code auch gleich erfolgreich kompiliert und meist auch prompt funktioniert. Diese Erfolge motivieren und man will TypeInference nicht mehr missen.

Generische Typen

Selber denkt man eher generisch, also mit generischen Datentypen. Es ist in F# so:
Wenn die Type-Inferenz nicht herausfindet, was es für ein Type sein muss, dann ist der Code automatisch generisch!
Super, man muss also dafür nicht extra überall <T> hinschreiben, das ist dann automatisch so!
1: 
2: 
3: 
4: 
5: 
// C#
void Swap<T>(List<T> list1, List<T> list2)
{
    // code to swap items
}
Und das equivalente generische swap in F#:
1: 
2: 
// F#
let swap (x,y) = (y,x)  // val swap : x:'a * y:'b -> 'b * 'a
und das funktioniert dann auch z.B. mit int List
1: 
2: 
3: 
4: 
let xs = [1; 3]
let ys = [4; 5; 6]
swap (xs,ys)
//val it : int list * int list = ([4; 5], [1; 3])
Auch das Refactoring wird dadurch vereinfacht, man muss die Typen nicht mitschleppen, also lesen und schreiben, umkopieren.
Weil es so einfach ist, braucht man dazu auch keine Refactoringtools! Viele glauben es zu beginn nicht, aber es ist so! Ihr werdet es merken ;-)
Etwas krass ausgedrückt werden Refactoringtool vielfach dazu verwendet, die “nebensächlichen” Teile des Codes zu erzeugen, die man nicht schreiben will. Steht der Code und man muss umbauen, dann müssen all die “nebensächlichen” Teile syntaktisch korrekt verpflanzt werden (Code-Plumbing wie man es auch nennt). Man kann es so sehen:
Die F# Syntax ist so ausgelegt, dass vieles nebensächliche gar nicht vorkommt und so das WAS gemacht wird sofort und klar ersichtlich ist.
Wie z.B.
  • keine “;” am Ende der Codezeile
  • keine { } Code-Blocks
  • keine Typen Deklaration
  • keine Generische Typen Deklaration
Positives Fazit:
Wer weniger schreibt, macht weniger Fehler. Wer weniger lesen muss, findet Fehler eher. Wer weniger lesen muss, arbeitet sich schneller ein. Weniger Code, weniger Bugs. Weniger Code, weniger Code Review. Weniger Code, Entwickler schneller eingearbeitet.
Ja und es geht nicht hauptsächlich darum : “Wer weniger schreibt, ist schneller fertig.” … es ist nett wenn das auch noch so ist ;-)
val xs : int listFull name: StrukturierungvonFQuellcode.xs
type bool = System.BooleanFull name: Microsoft.FSharp.Core.bool
Multiple items module Listfrom Microsoft.FSharp.Collections——————– type List<‘T> = | ( [] ) | ( :: ) of Head: ‘T * Tail: ‘T list interface IEnumerable interface IEnumerable<‘T> member Head : ‘T member IsEmpty : bool member Item : index:int -> ‘T with get member Length : int member Tail : ‘T list static member Cons : head:’T * tail:’T list -> ‘T list static member Empty : ‘T listFull name: Microsoft.FSharp.Collections.List<_>

Interpretation der F# Ausdrücke

  In F# ist alles mit Ausdrücken (expressions) aufgebaut, wo andere Sprachen Statements (statements) verwenden. Diese Ausdrücke werden in folgender Reihenfolge ausgewertet:
von links nach rechts von oben nach unten
Also nichts ungewöhnliches, genau wie die Deutsche Sprache geschrieben wird. D.h. alles was verwendet wird ist oberhalb oder in anderen Modulen (oder Assemblies) definiert. Die einzige Ausnahme ist bei type member, also Klassen Member, deren Reihenfolge willkürlich sein kann. Wieder mit der Ausnahme, dass der namenlose Konstruktor (also der, der nicht New heisst) als erstes kommt. In einem Projekt sind die Sourcefiles auch strikt hierarchisch geordnet. Also das unterste kann die oberen mit open (analog C# using) einbinden, nicht umgekehrt.

Was macht man, wenn es scheinbar nicht möglich ist so strikt zu strukturieren?

Wie geht das bei zirkulären Abhängigkeiten (circular dependency)? Für Typen- type und Funktions- let Definitionen innerhalb eines Moduls gibt es das and Konstrukt, das jeweils die abhängigen type oder let Schlüsselworte ersetzt. Dies erlaubt es wechselseitig Anhängige Definitionen zu bilden. So sind zirkuläre Definitionen möglich (ohne Vorausdeklarationen und Mutation).

Wieso ist das so strikt und stur?

Einerseits ist es so, dass es für den Compiler und vor allem für die Type Inferenz so sicher einfacher ist. Das könnte man als Nachteil sehen, dass man gezwungen wird den Aufbau so zu machen. Die Erkenntnis ist aber, dass ein so aufgebautes Software System sehr klar ist. Hierarchisch strikt durchschaubar. Keine Spagetti-hafte Kreuz Abhängigkeiten zwischen den Modulen. Was hier detailliert analysiert wird.
Zirkuläre Abhängigkeit von Komponenten verhindert die Schichten-Bildung (Layering) und ist somit schlechter testbar, wartbar, erweiterbar und wiederverwendbar.

Abhilfe für zirkuläre Abhängigkeiten

Die Tricks sind:
  • Die Datentypen von den Funktionen trennen. Was genau die Umkehrung vom Objektorientierten Design ist, also die Memberfunktionen aus den Klassen reissen und die herausfallenden mutierenden Zustände vermeiden. Diese Funktionen generisch machen und so deren Wiederverwendbarkeit ermöglichen. Was bei Funktionaler Programmierung typischerweise der Fall ist, weil die Daten immutable sind, funktioniert das einfach so.
Daten sind Programmiersprachen unabhängig, Objekt Klassen nicht. Man denke an die Speicherung.
  • Abstrahieren der Datentypen, möglichst alle Funktionen für generische Typen auslegen. Was in F# automatisch passiert, wenn man keinen Type spezifiziert.
Werte sind die Besten Interfaces.

Nicht aufgeben

Also wenn man etwas versucht das mit der strikten Hierarchischen Struktur nicht klar kommt, dann sollte man sich genau überlegen was es ist, das nicht in diese Form passt. Meist zeigt sich, dass es auch anders geht. Und so kommt es automatisch zu guten einfachen Designs.
Der Vorteil ist, dass man den Code so wie ein Buch lesen kann und die Reihenfolge ist logisch aufbauend auf schon bekanntem. Man muss nicht im Code oder den Komponenten herum springen um ihn zu lesen und zu verstehen.
Man kann es vom Kleinen zum Grossen lesen, oder umgekehrt beim Grossen beginnen um sich einen Überblick zu verschaffen und dann in die Details gehen. Man weiss wo man starten kann. Dies ermöglicht einem neuen Teammitglied den schnellen Einstieg in eine vorhandene Code-Basis. Man muss nicht erst Design Dokumentation lesen, falls solche vorhanden ist und sich mit dieser anfreunden oder erlernen.

Beispiel zu wechselseitig Anhängigen Typen

Die in diesem Beispiel voneinander abhängigen Typen sind Person und Ortschaft, da eine Person ein Wohnsitz hat und eine Ortschaft Einwohner hat.
 1: 
 2: 
 3: 
 4: 
 5: 
 6: 
 7: 
 8: 
 9: 
10: 
11: 
12: 
13: 
14: 
15: 
16: 
17: 
18: 
19: 
20: 
21: 
22: 
23: 
24: 
25: 
26: 
27: 
28: 
29: 
30: 
31: 
32: 
33: 
34: 
35: 
36: 
37: 
38: 
39: 
40: 
41: 
42: 
43: 
44: 
// Datentypen (Records)
type Person =
    { name      : string
      wohnort   : Ortschaft  
    }
and Ortschaft =
    { name      : string
      einwohner : Person list
    }

// Funktionen
let getPerson name ort =
    { Person.name = name; 
      wohnort = { Ortschaft.name = ort; einwohner = [] } 
    }

let lebtInOrtschaft ortschaftName person = 
    person.wohnort.name = ortschaftName

let einwohnerVon ortschaftName personen =
    personen |> List.filter (lebtInOrtschaft ortschaftName) 

let getEinwohnerZahl (ort : Ortschaft) =
    ort.einwohner.Length

let getOrtschaft ort personen =
    { name      = ort
      einwohner = personen |> einwohnerVon ort 
    }

// Aufbau der Datenstruktur
let Fritz  = getPerson "Fritz" "Zürich"
let Hans   = getPerson "Hans"  "Genf"  
let Max    = getPerson "Max"   "Genf"  

let Personen = [ Fritz; Hans; Max ] 

let Genf   = getOrtschaft "Genf"    Personen
let Zurich = getOrtschaft "Zürich"  Personen

let Ortschaften = [Genf; Zurich]

// Anwendung
List.map getEinwohnerZahl Ortschaften   // = [2; 1]
Aufgabe : Max zieht um von Genf nach Zürich. Wie bekommt man das hin, weil ja alles unveränderlich (immutable) ist? Lösung : Alle Veränderungen werden in diesem Beispiel hier mit angehängtem ' an den Wertenamen markiert. Das ist reine Dekoration, man könnte auch immer eine 2 anhängen. Wichtig ist, es entsteht ein neuer Wert, hier mit neuem Namen.
1: 
2: 
3: 
4: 
5: 
6: 
7: 
let Max'         = { Max with wohnort = Zurich }
let Personen'    = [ Fritz; Hans; Max' ] 
let Genf'        =  getOrtschaft "Genf"   Personen'
let Zurich'      =  getOrtschaft "Zürich" Personen'
let Ortschaften' = [ Genf'; Zurich' ]

List.map getEinwohnerZahl Ortschaften' // = [1; 2]
Jetzt könnte man meinen dies sei Speicherverschwendung, immer alles neu aufzubauen?
Der Code spezifiziert Was gemacht wird, nicht das Wie. Es wird intern nicht alles neu Aufgebaut, nur die Änderungen. Die Liste ist eine spezielle Funktionale Datenstruktur, die weil ja alles immutable ist, intern auf die bereits existenten unveränderlichen Daten verweist. Somit ist die Liste natürlich auch Thread-Safe.
Siehe auch Vorteile Funktionale Datenstruktur und Chris Okasaki’s 1998 Buch “Purely functional data structures” und Chris Okasaki’s Blog Grob gesagt nur die neue Mutation, also der Max' benötigt zusätzlichen Speicher. Ein Vorteil ist so auch, dass man die ganze History immer vorhanden ist. Gewisse Anwendungsbereiche leben davon, wie z.B. Source Control, Bankkonten. Da wird die ganze Geschichte aufbewahrt und nicht einfach die Speicherstelle Kontostand verändert. Dieses Beispiel konkurriert natürlich nicht mit speziell dafür (was immer genau die Anforderungen sind?) ausgelegten Datenstrukturen. Und F# kann auch Daten ändern, siehe ref und mutable, dazu später mehr.
Erinnern wir uns, das Beispiel zeigt wie man wechselseitig abhängige Typen definiert, erzeugt und handhabt.
type Person = {name: string; wohnort: Ortschaft;}Full name: InterpretationderFAusdrücke.Person
Person.name: string
Multiple items val string : value:’T -> stringFull name: Microsoft.FSharp.Core.Operators.string ——————– type string = System.String Full name: Microsoft.FSharp.Core.string
Person.wohnort: Ortschaft
type Ortschaft = {name: string; einwohner: Person list;}Full name: InterpretationderFAusdrücke.Ortschaft
Ortschaft.name: string
Ortschaft.einwohner: Person list
type ‘T list = List<‘T>Full name: Microsoft.FSharp.Collections.list<_>
val getPerson : name:string -> ort:string -> PersonFull name: InterpretationderFAusdrücke.getPerson
val name : string
val ort : string
val lebtInOrtschaft : ortschaftName:string -> person:Person -> boolFull name: InterpretationderFAusdrücke.lebtInOrtschaft
val ortschaftName : string
val person : Person
val einwohnerVon : ortschaftName:string -> personen:Person list -> Person listFull name: InterpretationderFAusdrücke.einwohnerVon
val personen : Person list
Multiple items module Listfrom Microsoft.FSharp.Collections ——————– type List<‘T> = | ( [] ) | ( :: ) of Head: ‘T * Tail: ‘T list interface IEnumerable interface IEnumerable<‘T> member Head : ‘T member IsEmpty : bool member Item : index:int -> ‘T with get member Length : int member Tail : ‘T list static member Cons : head:’T * tail:’T list -> ‘T list static member Empty : ‘T list Full name: Microsoft.FSharp.Collections.List<_>
val filter : predicate:(‘T -> bool) -> list:’T list -> ‘T listFull name: Microsoft.FSharp.Collections.List.filter
val getEinwohnerZahl : ort:Ortschaft -> intFull name: InterpretationderFAusdrücke.getEinwohnerZahl
val ort : Ortschaft
property List.Length: int
val getOrtschaft : ort:string -> personen:Person list -> OrtschaftFull name: InterpretationderFAusdrücke.getOrtschaft
val Fritz : PersonFull name: InterpretationderFAusdrücke.Fritz
val Hans : PersonFull name: InterpretationderFAusdrücke.Hans
val Max : PersonFull name: InterpretationderFAusdrücke.Max
val Personen : Person listFull name: InterpretationderFAusdrücke.Personen
val Genf : OrtschaftFull name: InterpretationderFAusdrücke.Genf
val Zurich : OrtschaftFull name: InterpretationderFAusdrücke.Zurich
val Ortschaften : Ortschaft listFull name: InterpretationderFAusdrücke.Ortschaften
val map : mapping:(‘T -> ‘U) -> list:’T list -> ‘U listFull name: Microsoft.FSharp.Collections.List.map
val Max’ : PersonFull name: InterpretationderFAusdrücke.Max’
val Personen’ : Person listFull name: InterpretationderFAusdrücke.Personen’
val Genf’ : OrtschaftFull name: InterpretationderFAusdrücke.Genf’
val Zurich’ : OrtschaftFull name: InterpretationderFAusdrücke.Zurich’
val Ortschaften’ : Ortschaft listFull name: InterpretationderFAusdrücke.Ortschaften’

Warum F#

  Mit über 30 Jahren Erfahrung in der Programmierung und Softwareentwicklung habe ich sehr vieles gesehen, gemacht und gelernt. Jahrzehnte lang war die Objektorientierte Entwicklung das A und O. Aber der Fortschritt stockte doch irgendwie, wenn man Software mit Elektronik vergleicht. Software Entwicklung dauerte typischerweise immer länger als geplant. Die Software Qualität von Fehlverhalten bis hin zu Anwenderfreundlichkeit lässt immer noch zu wünschen übrig. Die Aufwände trotz der viel gelobten Wiederverwendung von Objektorientiertem Code wurden nie kleiner.
Das kann doch nicht sein. Wo ist der Fortschritt geblieben? Stecken wir in einer Sackgasse?
Wie in “Über mich" beschrieben, ich suchte und fand etwas in Vergessenheit geratenes, die Funktionale Programmierung (FP), die schon älter ist als die Objektorientierte.
Und ich glaube es ist der Schlüssel, vieles einfach und besser zu machen und aus dem Sackgassen Dilemma auszubrechen und die Produktivität und Qualität von Software massiv zu erhöhen.
Der Grund wieso man jetzt immer öfter von FP hört ist, weil es die Beste Lösung für die Skalierbarkeit der immer wachsenden Prozessor Anzahl in Computern ist. Also die Asynchrone- und Parallele-Programmierung. So dass die Software die vorhandenen Hardware Ressourcen korrekt und effizient Nutzen kann und so dem Anwender das bieten was er erwartet. Meine Erfahrung zeigt mir, die praxisorientierte Programmiersprache dazu mit sofortigem praktischem Nutzen und ohne viel verwirrende Sprachkonstrukte, ist F# für .NET.
  • Voll kompatibel mit der kompletten .NET Umgebung.
  • Und es gibt Sicherheit und ist durchschaubar, denn F# ist Open Source.
  • Baut auf lange bewährtem auf und ist keine reine Microsoft Erfindung.
Der Stammbaum : Die Abstammung von F#
ML (1973) -> SML (1984) -> Caml (1987) -> OCaml (1996) – – -> F# (2007)
F# ist sehr stark an OCaml orientiert und z.T. auch Syntax kompatibel, also OCaml ist CAML mit objektorientiertem Zusatz, der wohl im OO-Hype Zeitalter dazu genommen wurde. Quelle: Programmiersprachen Stammbaum Die anderen aktuellen FP Sprachen und ihre Einflüsse sind z.B.
  • F# 1.0 (2007) : Objective CAML, C#, Haskell
  • Scala 1.0 (2003) : Java, Pizza, ML, Haskell, Smalltalk, Erlang
  • Haskell 1.0 (1987) : APL, LISP, Miranda, ML
Quelle: Wikipedia Was Entwickler überzeugen wird folgt Stück für Stück in technischen Blogs.

Über mich

Mein Name ist Roman Bossart, in diesem Blog hier schreibe ich über Software Entwicklung mit Funktionaler Programmierung.

Ich bin Gründer und Inhaber von Bossart Analytics – Calibration Model und beschäftige mich mit Machine Learning und Software Entwicklung und lebe in der Schweiz nahe St. Gallen.

Unter folgenden Links finden Sie weitere Informationen:
Kontakt
Impressum
Twitter
StackOverflow


Warum blogge ich

Ich schreibe dies einerseits für mich als Zusammenfassung und als Dank an die motivierende innovative F# Community und für alle die, die an der neuen “Software Revolution” vorne dabei sein und teilnehmen wollen. Ich glaube die Softwareentwicklung macht nun endlich nach Jahrzehnten einen grossen Schritt in die richtige Richtung. Wir brechen aus, aus der OO-dominierten Sackgasse. Viele Sprachen haben funktionale Aspekte aufgenommen. Wer dies gut findet, der findet und erkennt noch viel mehr Möglichkeiten und Denkansätze, wenn er eine reine Sprache einsetzt, die ihre Funktionalen Wurzeln im Stammbaum seit 1973 weiterpflegt. Ich habe es erlebt und möchte diese Erfahrung und Wissen mit euch teilen.

Viele bloggen während sie etwas lernen, mit der Motivation ihre neuen Teil-Erkenntnisse stückweise zu dokumentieren. Dieser Blog ist eine Zusammenfassung von mir, der viele Teil-Lern-Puzzles schon hinter sich hat. Dies ergibt den Vorteil keine Abwege und Sackgassen-Erkenntnisse zu enthalten. Ein abgestimmtes Gesamtbild das sich auf die wichtigsten Fakten konzentriert und alle Kernpunkte und deren Essenz beleuchtet alles ganz pragmatisch und praxistauglich.

Das schöne ist, wenn man (fast) von Anfang an dabei ist und beobachtet wie das Aufkommen und Ausbreiten der F# Sprache, deren Anwender, Anwendungen und Tools, Bibliotheken und Open-Frameworks voranschreitet, dass man alles stückweise mitbekommt und die Zeit hat alles was neu ist zu lesen und auszuprobieren. Somit hat man einen nahezu kompletten Überblick was es gibt. Startet man heute ist so vieles schon da und man weiß nicht recht womit man starten soll. Also kein systematischer Aufbau, kein roter Faden den man folgen kann und so ohne Umweg die neue Welt von F# entdecken kann.

Dies will ich hier tun und beschreibe den geradlinigen Weg, der die typischen Problempunkte schon zu beginn anspricht und klarstellt, so dass der Einstieg und Anwendung glatt und scharf# geschliffen ohne Unfälle von statten geht.


Wer schreibt hier?

Damit Ihr wisst, von wem die Texte und Tipps stammen, wie ich geprägt bin, und wie und warum ich F# gefunden habe und nicht mehr loslasse.

Seit Ende der 80-er Jahre entwickle ich Software objektorientiert (ADA, PASCAL, C++, C#) und 2009 habe habe ich F# für mich entdeckt.

Es kam so, ich war 2008 von LINQ (mit C#) so begeistert, dass ich mich eines Tages fragte woher es kommt. Dabei bin ich auf Microsoft Research gestossen, aus dieser Schmiede kam es. Und was noch viel interessanter war, diese Leute arbeiten an einer neuen Sprache, es war Microsoft F#, May 2009 Community Technology Preview die man sich zum Visual-Studio 2010 Beta dazu installieren konnte. Meine Begeisterung steigerte sich mit F#, denn durch das interaktive Ausprobieren, konnte man schnell Vorschritte beim Erlernen machen. Nicht erst ein Testprogramm schreiben zu müssen, um seine Code Fragmente auszuprobieren. Und es kam noch besser, es ist ja nicht nur die Sprache selbst, es ist auch das ganze .Net Framework, dass man so auch interaktiv Ausprobieren kann. Dies war früher nie möglich in C#, heute mit LINQPad und Konsorten geht das ja.

Ich kann so heute ganz glücklich auf mehrere produktive Jahre Erfahrung mit exklusiver F# Entwicklung zurückblicken.


F#, d.h. die Funktionale Programmierung, die ich vom Prinzip und Anwendung bereits seit 1984 von LISP kannte, konnte ich nun auch auf das .NET Framework anwenden, das ich schon seit 2002 (.NET 1.0) kenne. Im Gegensatz zu LISP macht F# nicht soviel Klammerungen nötig, was mir ganz gut gefällt.

Und das aller Beste an F# ist, man hat FP + OOP + .NET + interaktiv, in Script-Form und in kompilierter Form. Der Code ist kompakt, leserlich, wenig fehleranfällig und beschränkt sich auf das was man tun will. Und dies alles auch noch als Open Source (ja der komplette Compiler! Spaßeshalber von jemandem einmal als FOSLYN bezeichnet mit Anspielung auf ROSLYN) auf allen wesentlichen Plattformen wie Windows, Mac, Linux, Android, iOS (iPhone/iPad), JS/HTML5, GPU, FreeBSD.


Pro-Tip : Also wenn ihr auf LINQ, LINQPad oder PowerShell nicht verzichten könnt, dann müsst ihr unbedingt (zwangsmäßig) F# ausprobieren! Denn da kommt alles und noch viel mehr zusammen und alles ist aus einem Guss. Ich schreibe das hier, weil niemand später sagen soll, “Das hätte man mir doch früher sagen sollen! Da hätte ich mir viel Zeit und Mühe gespart.” So ich habe es gesagt / geschrieben.

Über den Blog

Funktionale Software Entwicklung mit F# und .Net

Willkommen auf einer der wenigen deutschsprachigen Webseiten über die Programmiersprache F# (F-Sharp, FSharp, #fsharp, .fs, .fsx, #F, FScharp, F-Scharf).

Worum geht es hier?

Wer sich für Funktionale Programmierung interessiert wird auf Aussagen treffen wie, es ist sehr mathematisch, abstrakt und komplex (Kategorientheorie). Dies wirkt meist abschreckend. Das muss aber nicht sein.

Dieser Blog will anhand der Programmiersprache F# zeigen, dass es bei Funktionaler Programmierung (FP) um mehr geht, also auch im Kleineren, die einfachen Dinge wie die Bausteine für Muster und Wiederverwendung und übergeordnet in der funktionalen Denkweise Probleme zu lösen, grossartige Möglichkeiten und Vorteile vorhanden sind.

Jeder der denkt, dass Funktionale Programmierung nur das herumreichen von Anonymen Funktionen (Lambda-Funktion) ist, die es auch in anderen Sprachen gibt, der irrt. Es ist nicht nur die Programmierung (Syntax) die funktional erfolgt, es geht auch um den Funktionalen Design, der ganz andere Denkmuster enthält als ein Objektorientierter (OO) Design.

Und weil hier eine Mehrzweck (Multi-Purpose) Programmiersprache wie F# verwendet wird, es nicht nur einzig um Funktional geht, sondern gezeigt wird, das ein guter Mix aus FP und OO Techniken einfach möglich ist. Der Nutzen von beiden Welten (FP, OO) soll in der Praxis, also basierend auf .Net (oder Mono) gezeigt werden.

Der Blog ist gedacht als eine Ein- und Weiterführung in die Funktionale Programmierung mit F#, für C#, VB.Net, C++ oder Java Entwickler, etc.

Bitte klickt doch im Fragebogen rechts Eure Programmiersprache(n) an, so könnt ihr das aktuelle Ergebnis der Umfrage sehen, Danke.
1: 
printf "HalloF#" // Die Code Beispiele werden unterstützt durch Tooltips 

Warum in Deutsch?

  • Weil man es auch automatisch übersetzen lassen kann (translate to English).
  • Weil sich Wissen und Erfahrungen besser in der Muttersprache weitergeben lassen.
  • Weil es schon genügend englischsprachige Webseiten und Literatur zum Thema F# gibt.

Was nicht?

  • Es wird hier nicht das F# Referenz Handbuch auf Deutsch übersetzt zu lesen geben.
  • Es werden hier nicht alle Fachbegriffe stur eingedeutscht.
  • Dies ist keine Microsoft Seite, denn F# ist Open Source!
val printf : format:Printf.TextWriterFormat<‘T> -> ‘TFull name: Microsoft.FSharp.Core.ExtraTopLevelOperators.printf