F Sharp
Az F# egy a .NET keretrendszerhez kapcsolódóan kifejlesztett, több programozási irányelv szerint is alkalmazható (többelvű), szigorúan típusos programozási nyelv. Alapjául az ML és OCaml nyelv szolgált, valamint kialakítására hatással volt még a C#, Python, Haskell, Scala valamint Erlang nyelv is. Elsősorban funkcionális programozási nyelvnek szánták, de alkalmazható az imperatív és objektumorientált elveknek megfelelően is.

Történet

Fejlesztése 
A munkálatokat a kezdetektől Don Syme a Microsoft kutatási részlegének (Microsoft Research) munkatársa igazgatja, 2013-tól együttműködésben az F# Software Foundationnel.
A nyelv alapjai és korai verziói még zárt fejlesztési folyamatban készültek a Microsoft és annak Cambridge-i kutatási részlege közreműködésével. A számos fejlesztő mellett kiemelt szerepe van a projektben Andrew Kennedynek, aki nagyban hozzájárult a .NET keretrendszer alapjaival való összehangolásban és a mértékegységek implementálásával. Ennek a folyamatnak a során készült el a nyelv Microsoft Visual Studio integrációja is.

Napjainkban a nyelv további fejlesztése már nyílt módon folyik. A nyílt forrású fordító az F# Software Foundation gondozásában készült el.

Verziók

Áttekintés

Funkcionális programozás 
Az F# szigorúan típusos nyelv, jellemzően pedig típuskikövetkeztetés segítségével dolgozhatunk. Így a programozónak nem kell a típusokat a kódban előre megadnia, azok futás időben kerülnek meghatározásra. Ugyanakkor a nyelv lehetőséget biztosít a típus explicit megadására is, amely indokolt lehet néhány ritka esetben.

A nyelvben azonosítók segítségével adunk nevet a kifejezéseknek, amik kiértékelésük alapján kapják meg az értéküket. Fontos megjegyezni, habár ez hasonlít az imperatív nyelveknél megszokott értékadáshoz, valójában okkal nevezzük ezeket azonosítónak és nem változónak, ugyanis a kiértékelést követően az azonosító értéke többé már nem változtatható meg (kivételt képez ez alól néhány későbbi láthatósághoz kapcsolódó eset, valamint imperatív programozási paradigma alkalmazása esetén vannak lehetőségek felüldefiniálásra). Ugyanakkor lehetőség van kifejezésként megadni az F#-ban elérhető függvényeket és programozási struktúrákat is, beleértve az if, valamint a try szerkezeteket és egyéb ciklus szervezéseket. Az ilyen azonosítókat a let kulcsszó segítségével definiálhatjuk.

Egy egyszerű példa a let használatára:
let x = 4 + 2 // az x azonosító ''immutable'' (azaz nem változtatható meg)
A kiértékelés után az x nevű azonosító értéke 6 lesz.

Egy másik példa, ezúttal függvény definiálására:
let osszead x y = x + y
let eredmeny = osszead 4 6
A kiértékelés után az eredmeny nevű azonosító értéke 10 lesz.

Az utóbbi példában jól látható, hogy F#-ban miként lehet a matematikában használatos függvény megadáshoz hasonlóan definiálni.

 
F#-ban a visszatérési érték nélküli funkciók és kifejezések unit típusúak, amely a C# és C++ nyelvek void típusára emlékeztethet.

Az F# a következő elemi típusokat támogatja: byte, sbyte, int16, uint16, int32, uint32, int64, uint64, obj, float32, float64

Új típusokat a type kulcsszóval határozhatunk meg. A funkcionális programozáshoz a nyelv a rendezett n-es (tuple), rekord, diszkriminánsos unió, lista és option típusokkal szolgál.

A rendezett n-es (tuple) egy olyan egyszerű adattípus, amellyel n darab értéket csoportosíthatunk, ahol n ≥ 0 és értékek akár különböző típusúak is lehetnek. A tuple elemeinek száma viszont mindig előre meghatározott lesz a definiálásakor és a futtatás végéig változatlan is marad, ezért az előre nem definiálható elemszámú adathalmazok tárolására nem alkalmas. Helyette a lista vagy tömb típus lehet a megfelelő választás.
Jól hasznosítható, amennyiben egy egyszerűbb függvénynek több visszatérési értéke van. Ilyenkor az adott függvény visszatéréseként használva szükségtelenné teszi új osztályok deklarálását. Bonyolultabb struktúrájú visszatérési értékekkel rendelkező függvényeknél viszont célszerűbb a rekord típust használni.

Példa egy tuple megadására:

let tuple = (42, "Hello world!")
Ezen a rendezett n-es szerkezeten belül az első érték int ,míg a második string típusúnak lesz értelmezve.

A rekord valójában egy olyan rendezett n-esnek tekinthető szerkezet, amely névvel ellátott elemekkel rendelkezik: { Nev:string; Kor:int }. Valamint abban is különböznek, hogy a rekordot előre deklarálni kell a type konstrukcióval:
type Termek = { Nev:string; Ertek:int }  // a rekord típus deklarációja
let t = { Nev="Teszt"; Ertek=42; }       // meghatározzuk a 'Termek' értékét

A with kulcsszóval másolatot készíthetünk egy rekordról. Mivel a rekord immutable tulajdonságú, azaz a tagjai nem módosíthatóak, ezért gyakran kell másolatot készítenünk róla, amiben egy vagy több elemén változtatást hajtunk végre:
let t2 = { t with Nev="Teszt2" }  // a fenti példa után készítünk egy másolatot egy más 'Nev' értékkel

A diszkriminánsos unió típust olyan adattípusok reprezentálása használhatjuk, melyben a tárolt adatok opcionálisak. Hasonló, mint a C++ nyelvben használt unió típus, vagy a Visual Basic variant típusa. Itt viszont a deklarálásnál meg kell határoznunk úgynevezett eseteket, amelyeken belül minden típust is definiálnunk kell.

Egy egyszerű példa amelyben egy alakzatot deklarálunk ezzel a szerkezettel:
type Shape =
| Circle of float                 // a kör sugara
| EquilateralTriangle of double   // a szabályos háromszög oldalhossza
| Square of double                // a négyzet oldalhossza
| Rectangle of double * double    // a téglalap a és b oldalának hosszai

Amint az látható, itt 4 esetről beszélhetünk: kör (Circle), szabályos háromszög (EquilateralTriangle), négyzet (Square) és téglalap (Rectangle). (A 3.1-es verziótól már nevet is adhatunk az egyes eseteken belül a mezőknek, viszont ez nem kötelező.)

Ha ki akarjuk számítani a fent definiált alakzatok területét, akkor a mintaillesztés módszeréhez (match) kell fordulnunk:
let pi = 3.141592654

let area myShape =
    match myShape with
    | Circle radius -> pi * radius * radius
    | EquilateralTriangle s -> (sqrt 3.0) / 4.0 * s * s
    | Square s -> s * s
    | Rectangle (h, w) -> h * w

let radius = 15.0
let myCircle = Circle(radius)
printfn "Kör területe, amelynek sugara %f: %f" radius (area myCircle)

let squareSide = 10.0
let mySquare = Square(squareSide)
printfn "Négyzet területe, amelynek oldalhossza %f: %f" squareSide (area mySquare)

let height, width = 5.0, 10.0
let myRectangle = Rectangle(height, width)
printfn "Téglalap területe amelynek egyik oldala %f, másik oldala pedig %f: %f" height width (area myRectangle)

A fenti kód futtatása a következő eredményt hozza:
Kör területe, amelynek sugara 15.000000: 706.858347
Négyzet területe, amelynek oldalhossza  10.000000: 100.000000
Téglalap területe amelynek egyik oldala 5.000000, másik oldala pedig 10.000000: 50.000000

Imperatív programozás 
Az F# nyelv támogatja az imperatív programozási paradigmát is.

A használható szerkezetek a teljesség igénye nélkül:
 for ciklus
 while ciklus
 tömbök deklarálása […, …]
 asszociatív tömbök, ún. szótárak deklarálása dict […] vagy System.Collections.Generic.Dictionary<_,_>

Az azonosítók és mezők / elemek megjelölhetők mutable tulajdonsággal, aminek hatására ezeknek az értéke később felülírható:
let mutable x = 1  // definiáljuk az 'x' azonosítót kezdeti '1' értékkel
x <- 3             // felülírjuk az 'x' értékét '3'-al

Hasonló megoldás, amennyiben például egy rekord típus adott elemét szeretnénk felülírni:
type Termek = { 
    Megnevezes: string
    mutable Darabszam: int
}

let egyTermek = { Megnevezes = "Fapapucs"; Darabszam = 100 }
egyTermek.Darabszam <- egyTermek.Darabszam - 1

Ezen felül az F# elérhetővé teszi az összes CLI típust és objektumot, amelyek például a System.Collections.Generic névtéren belül vannak definiálva.

Objektumorientált programozás 
Az F# nyelvben a többi CLI nyelvhez hasonlóan van lehetőség a CLI típusok és objektumok használatára.

Az osztályok az objektumorientált F# egyik legfontosabb építőelemei. Az osztályok a C# osztályokhoz hasonló tulajdonságokkal rendelkeznek: származhatnak ősosztályokból, elrejthetik a belső állapotukat, lehet konstruktoruk és megvalósíthatnak interfészeket is.

Például itt egy osztály definíció, konstruktorral, amely nevet és egy kor értéket vár, valamint két tulajdonságot definiál:
type Szemely(nev : string, kor : int) =
    member x.Nev = nev
    member x.Kor = kor

Az osztály alapértelmezetten publikus. A hozzáférési módosító megadására a type kulcsszó után van lehetőség.

Források

További információk 
 F# dokumentáció a Microsoft oldalán (angol)
 F# fejlesztői csoport a Github oldalán (angol)
 F# kódrészletek (angol)

Funkcionális programozási nyelvek
Imperatív programozási nyelvek
Objektumorientált programozási nyelvek
Microsoft
Az F # egy a\ .NET keretrendszerhez kapcsolódóan kifejlesztett , több programozási irányelv szerint is alkalmazható ( többelvű ) , szigorúan típusos programozási nyelv . Alapjául az ML és OCaml nyelv szolgált , valamint kialakítására hatással volt még a C # , Python , Haskell , Scala valamint Erlang nyelv is . Elsősorban funkcionális programozási nyelvnek szánták , de alkalmazható az imperatív és objektumorientált elveknek megfelelően is . Történet Fejlesztése A munkálatokat a kezdetektől Don Syme a Microsoft kutatási részlegének ( Microsoft Research ) munkatársa igazgatja,tól együttműködésben az F # Software Foundationnel . A nyelv alapjai és korai verziói még zárt fejlesztési folyamatban készültek a Microsoft és annak Cambridge-i kutatási részlege közreműködésével . A számos fejlesztő mellett kiemelt szerepe van a projektben Andrew Kennedynek , aki nagyban hozzájárult a\ .NET keretrendszer alapjaival való összehangolásban és a mértékegységek implementálásával . Ennek a folyamatnak a során készült el a nyelv Microsoft Visual Studio integrációja is . Napjainkban a nyelv további fejlesztése már nyílt módon folyik . A nyílt forrású fordító az F # Software Foundation gondozásában készült el . Verziók Áttekintés Funkcionális programozás Az F # szigorúan típusos nyelv , jellemzően pedig típuskikövetkeztetés segítségével dolgozhatunk . Így a programozónak nem kell a típusokat a kódban előre megadnia , azok futás időben kerülnek meghatározásra . Ugyanakkor a nyelv lehetőséget biztosít a típus explicit megadására is , amely indokolt lehet néhány ritka esetben . A nyelvben azonosítók segítségével adunk nevet a kifejezéseknek , amik kiértékelésük alapján kapják meg az értéküket . Fontos megjegyezni , habár ez hasonlít az imperatív nyelveknél megszokott értékadáshoz , valójában okkal nevezzük ezeket azonosítónak és nem változónak , ugyanis a kiértékelést követően az azonosító értéke többé már nem változtatható meg ( kivételt képez ez alól néhány későbbi láthatósághoz kapcsolódó eset , valamint imperatív programozási paradigma alkalmazása esetén vannak lehetőségek felüldefiniálásra ) . Ugyanakkor lehetőség van kifejezésként megadni az F#-ban elérhető függvényeket és programozási struktúrákat is , beleértve az if , valamint a try szerkezeteket és egyéb ciklus szervezéseket . Az ilyen azonosítókat a let kulcsszó segítségével definiálhatjuk . Egy egyszerű példa a let használatára : let x =+ / / az x azonosító ''immutable'' ( azaz nem változtatható meg ) A kiértékelés után az x nevű azonosító értékelesz . Egy másik példa , ezúttal függvény definiálására : let osszead x y = x + y let eredmeny = osszead6 A kiértékelés után az eredmeny nevű azonosító értékelesz . Az utóbbi példában jól látható , hogy F#-ban miként lehet a matematikában használatos függvény megadáshoz hasonlóan definiálni . F#-ban a visszatérési érték nélküli funkciók és kifejezések unit típusúak , amely a C # és C++ nyelvek void típusára emlékeztethet . Az F # a következő elemi típusokat támogatja : byte , sbyte , int16 , uint16 , int32 , uint32 , int64 , uint64 , obj , float32 , float64 Új típusokat a type kulcsszóval határozhatunk meg . A funkcionális programozáshoz a nyelv a rendezett n-es ( tuple ) , rekord , diszkriminánsos unió , lista és option típusokkal szolgál . A rendezett n-es ( tuple ) egy olyan egyszerű adattípus , amellyel n darab értéket csoportosíthatunk , ahol n ≥és értékek akár különböző típusúak is lehetnek . A tuple elemeinek száma viszont mindig előre meghatározott lesz a definiálásakor és a futtatás végéig változatlan is marad , ezért az előre nem definiálható elemszámú adathalmazok tárolására nem alkalmas . Helyette a lista vagy tömb típus lehet a megfelelő választás . Jól hasznosítható , amennyiben egy egyszerűbb függvénynek több visszatérési értéke van . Ilyenkor az adott függvény visszatéréseként használva szükségtelenné teszi új osztályok deklarálását . Bonyolultabb struktúrájú visszatérési értékekkel rendelkező függvényeknél viszont célszerűbb a rekord típust használni . Példa egy tuple megadására : let tuple = " Hello world ! " ) Ezen a rendezett n-es szerkezeten belül az első érték int,míg a második string típusúnak lesz értelmezve . A rekord valójában egy olyan rendezett n-esnek tekinthető szerkezet , amely névvel ellátott elemekkel rendelkezik : { Nev: string ; Kor: int } . Valamint abban is különböznek , hogy a rekordot előre deklarálni kell a type konstrukcióval : type Termek = { Nev: string ; Ertek: int } / / a rekord típus deklarációja let t = { Nev=" Teszt " ; Ertek=42 ; } / / meghatározzuk a 'Termek' értékét A with kulcsszóval másolatot készíthetünk egy rekordról . Mivel a rekord immutable tulajdonságú , azaz a tagjai nem módosíthatóak , ezért gyakran kell másolatot készítenünk róla , amiben egy vagy több elemén változtatást hajtunk végre : let t2 = { t with Nev=" Teszt2 " } / / a fenti példa után készítünk egy másolatot egy más 'Nev' értékkel A diszkriminánsos unió típust olyan adattípusok reprezentálása használhatjuk , melyben a tárolt adatok opcionálisak . Hasonló , mint a C++ nyelvben használt unió típus , vagy a Visual Basic variant típusa . Itt viszont a deklarálásnál meg kell határoznunk úgynevezett eseteket , amelyeken belül minden típust is definiálnunk kell . Egy egyszerű példa amelyben egy alakzatot deklarálunk ezzel a szerkezettel : type Shape = | Circle of float / / a kör sugara | EquilateralTriangle of double / / a szabályos háromszög oldalhossza | Square of double / / a négyzet oldalhossza | Rectangle of double * double / / a téglalap a és b oldalának hosszai Amint az látható , ittesetről beszélhetünk : kör ( Circle ) , szabályos háromszög ( EquilateralTriangle ) , négyzet ( Square ) és téglalap ( Rectangle ) . ( A1-es verziótól már nevet is adhatunk az egyes eseteken belül a mezőknek , viszont ez nem kötelező . ) Ha ki akarjuk számítani a fent definiált alakzatok területét , akkor a mintaillesztés módszeréhez ( match ) kell fordulnunk : let pi =141592654 let area myShape = match myShape with | Circle radius -> pi * radius * radius | EquilateralTriangle s -> ( sqrt0 ) /0 * s * s | Square s -> s * s | Rectangle ( h , w ) -> h * w let radius =0 let myCircle = Circle( radius ) printfn " Kör területe , amelynek sugara %f: %f " radius ( area myCircle ) let squareSide =0 let mySquare = Square( squareSide ) printfn " Négyzet területe , amelynek oldalhossza %f: %f " squareSide ( area mySquare ) let height , width =0,0 let myRectangle = Rectangle( height , width ) printfn " Téglalap területe amelynek egyik oldala %f , másik oldala pedig %f: %f " height width ( area myRectangle ) A fenti kód futtatása a következő eredményt hozza : Kör területe , amelynek sugara000000:858347 Négyzet területe , amelynek oldalhossza 000000:000000 Téglalap területe amelynek egyik oldala000000 , másik oldala pedig000000:000000 Imperatív programozás Az F # nyelv támogatja az imperatív programozási paradigmát is . A használható szerkezetek a teljesség igénye nélkül : for ciklus while ciklus tömbök deklarálása [ … , … ] asszociatív tömbök , ún. szótárak deklarálása dict [ … ] vagy System.Collections.Generic.Dictionary <_, _> Az azonosítók és mezők / elemek megjelölhetők mutable tulajdonsággal , aminek hatására ezeknek az értéke később felülírható : let mutable x = / / definiáljuk az 'x' azonosítót kezdeti '1' értékkel x <- / / felülírjuk az 'x' értékét '3'-al Hasonló megoldás , amennyiben például egy rekord típus adott elemét szeretnénk felülírni : type Termek = { Megnevezes : string mutable Darabszam : int } let egyTermek = { Megnevezes = " Fapapucs " ; Darabszam = } egyTermek.Darabszam <- egyTermek.Darabszam - 1 Ezen felül az F # elérhetővé teszi az összes CLI típust és objektumot , amelyek például a System.Collections.Generic névtéren belül vannak definiálva . Objektumorientált programozás Az F # nyelvben a többi CLI nyelvhez hasonlóan van lehetőség a CLI típusok és objektumok használatára . Az osztályok az objektumorientált F # egyik legfontosabb építőelemei . Az osztályok a C # osztályokhoz hasonló tulajdonságokkal rendelkeznek : származhatnak ősosztályokból , elrejthetik a belső állapotukat , lehet konstruktoruk és megvalósíthatnak interfészeket is . Például itt egy osztály definíció , konstruktorral , amely nevet és egy kor értéket vár , valamint két tulajdonságot definiál : type Szemely( nev \ : string , kor \ : int ) = member x.Nev = nev member x.Kor = kor Az osztály alapértelmezetten publikus . A hozzáférési módosító megadására a type kulcsszó után van lehetőség . Források További információk F # dokumentáció a Microsoft oldalán ( angol ) F # fejlesztői csoport a Github oldalán ( angol ) F # kódrészletek ( angol ) Funkcionális programozási nyelvek Imperatív programozási nyelvek Objektumorientált programozási nyelvek Microsoft