Zum Inhalt springen

F-Sharp

aus Wikipedia, der freien Enzyklopädie
Dies ist eine alte Version dieser Seite, zuletzt bearbeitet am 23. November 2009 um 04:16 Uhr durch Generalpd (Diskussion | Beiträge) (Codebeispiele nun mit OCamL-SyntaxHighlighting). Sie kann sich erheblich von der aktuellen Version unterscheiden.

F# ist eine funktionale Programmiersprache von Microsoft für das .NET-Framework. F# ist mit den Sprachen OCaml und ML verwandt, die Syntax der Sprachen ähneln sich daher stark. Viele Programme, die ungewöhnliche Konstrukte und F#-/Caml-spezifische Bibliotheken vermeiden, können ohne Änderung mit F# und mit Caml kompiliert werden.

Neben den Bestandteilen der funktionalen Programmierung sind in F# objektorientierte sowie imperative Sprachkonstrukte enthalten.

Ursprünglich wurde F# als Forschungsprojekt von Microsoft Research entwickelt, derzeit wird es von Microsofts Entwicklungsabteilung fortgeführt. F# soll als Teil des zukünftigen Visual Studio 2010 erstmals offiziell unterstützt und mit ausgeliefert werden.[1] Außerdem ist es auch als Erweiterung zu Visual Studio 2008 erhältlich. [2]

Einige Sprachmerkmale

In F# gibt es keine Variablen, wie in anderen Programmiersprachen. Es gibt nur Funktionen, die immer denselben Rückgabewert haben. Diese werden in F# mit dem Schlüsselwort let deklariert und definiert.


    let pi = 3.1415927


F# bietet Typableitung, d.h. Typen von Ausdrücken werden automatisch ermittelt. Beispielsweise bekommt pi automatisch den Typ des Gleitkommazahl-Literals zugewiesen.

let ist dabei keine Variablenzuweisung, sondern eine Deklaration, d.h. der Quelltext


    let pi = 3.1415927
    let pi = 10.0


kann nicht kompiliert werden, da der Wert pi zweimal innerhalb desselben Gültigkeitsbereichs deklariert wird. Soll der Wert einer Variablen im Programmablauf änderbar sein, muss dies bereits bei der Deklaration kenntlich gemacht werden:


    let x = ref 0 // x hat den Typ 'int ref', also ein Wert vom Typ int, der im Programmablauf
                  // geändert werden kann.
    let printX = print_any !x
    do x := 5     // An dieser Stelle im Programm wird der ursprüngliche Wert von x geändert.
    do printX


gibt 5 aus. Das in den beiden unteren Zeilen verwendete Schlüsselwort do leitet Ausdrücke ohne Rückgabewert ein (Aktionen).

Funktionen werden wie andere Werte mit let deklariert:


    let square x = x*x


Funktionen können Funktionen als Parameter erwarten (siehe Funktion höherer Ordnung):


    let do_twice f x = f(f x)


Die Anweisung


    do print_any (do_twice square 5)


gibt 625 (das Quadrat des Quadrats von 5) aus. Die Funktion do_twice kann mit Hilfe des Kompositionsoperators und nach eta-Reduktion auch als


    let do_twice f = f>>f


geschrieben werden.

Im obigen Beispiel wird für square der Typ int -> int ermittelt, d.h. square ist eine Funktion, die einen Parameter vom Typ int erwartet und einen Wert vom Typ int zurückgibt. Für do_twice erhält man den Typ ('a -> 'a) -> 'a -> 'a, d.h. do_twice ist eine Funktion, die als ersten Parameter einen Wert vom Typ ('a -> 'a) (eine Funktion mit einem Parameter vom Typ 'a und einem Rückgabewert vom Typ 'a) bekommt, als zweiten Parameter einen Wert vom Typ 'a, und einen Wert vom Typ 'a zurückgibt. 'a hat hier die Rolle einer Typvariable (grob vergleichbar mit Generic- oder Template-Parametern in Java/C++, siehe Polymorphie (Programmierung)).

F# ermöglicht Closures und verwendet Currying:


    let f x y = x+y
    let g = f 2


In der zweiten Definition wird der erste Parameter der Funktion f an den Wert 2 gebunden. Das Ergebnis dieser partiellen Funktionsanwendung ist eine neue Funktion mit nur noch einem Argument. Die Auswertung des Ausdrucks


    g 5


liefert als Ergebnis 7.

F# unterstützt mehrere Argumente/Rückgabewerte (offizieller Titel: Multiple Arguments und Multiple Returns):


    let f (a,b,c) = (a+b, b+c, a+b)


F# bietet Pattern Matching:


    // Ein Element vom Typ Baum ist entweder ein ''Ast'' und enthält zwei Elemente vom Typ ''Baum'',
    // oder es ist ein ''Blatt'' und enthält einen int-Wert
    type Baum = Ast of Baum * Baum | Blatt of int 
 
    let rec baumSumme x =
      match x with 
        | Ast(l,r) -> baumSumme l + baumSumme r
        | Blatt(x) -> x


F# ist objektorientiert. Beispiel für eine Klassendeklaration:


    type MyData = 
      class 
        val first : int
        val mutable second : int
        new(a,b) = { first=a; second=b }
        member x.First = x.first
        member x.Second
          with get() = x.second
          and set(v) = x.second <- v
        member x.Next() = x.first <- x + 1
        member x.Reset(v) = x.first <- 0; x.second <- 0
      end


F# ist konform mit der Common Language Infrastructure. Somit kann in F# auf Typen zugegriffen werden, die in anderen .NET-Sprachen geschrieben sind, und umgekehrt. Nullzeiger werden nur für die Interaktion mit .NET benötigt.

Compiler und Interpreter

F#-Code wird kompiliert, hierbei entsteht Zwischencode in der Common Intermediate Language (CIL), genau wie bei Programmen, die in C# oder VB.NET geschrieben wurden. Tatsächlich wird das gute Zusammenspiel mit anderen Programmiersprachen der .NET-Familie von Microsoft als einer der großen Vorteile von F# dargestellt.

Abgesehen vom F#-Compiler (fsc) gibt es auch einen F#-Interpreter (fsi), der F#-Code interaktiv ausführt. Eingaben im Interpreter sind mit ;; abzuschließen, wodurch auch mehrzeilige Eingaben ermöglich werden.

Beispiel

Folgendes Beispiel gibt „Hello World“ aus.


    let main = System.Console.WriteLine("Hello World\n")


Die folgende Funktion implementiert die rekursive Ackermannfunktion:


    let rec ack m n =
      if m = 0 then n + 1
      else if n = 0 then ack (m - 1) 1
      else ack (m - 1) (ack m (n - 1))


Einzelnachweise

  1. Don Syme's WebLog on the F# Language and Related Topics: F# to ship as part of Visual Studio 2010
  2. F# at Microsoft Research http://research.microsoft.com/en-us/um/cambridge/projects/fsharp/default.aspx