F Sharp

A Wikipédiából, a szabad enciklopédiából
A szócikk címe technikai okok miatt pontatlan. A helyes cím: F#.
F#
Paradigma funkcionális, imperatív, objektumorientált, többelvű
Jellemző kiterjesztés .fs, .fsi, .fsx, .fsscript
Megjelent 2005 (1.0 verzió)
Tervező Microsoft, Don Syme
Fejlesztő Microsoft, The F# Software Foundation
Utolsó kiadás 4.0 (2015. július 20.)
Típusosság statikus, erősen típusos, típus biztos
Megvalósítások .NET Framework, Mono
Hatással volt rá ML, OCalm, C#, Python, Haskell, Scala, Erlang
Befolyásolt nyelvek C#
Licenc Apache Licenc
Weboldal

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 OCalm 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[szerkesztés]

Fejlesztése[szerkesztés]

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.[1] 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[szerkesztés]

Verziószám Megjelenés Főbb fejlesztések
1.0 2005. május[2]
  • funkcionális programozás
  • diszkriminánsos unió típus
  • rekord típus
  • rendezett n-es típus (tuple)
  • mintaillesztés
  • típuskikövetkeztetés
  • objektumorientált programozás
  • struktúrák (struct)
  • imperatív programozás
2.0 2010. április[3]
  • aktív minták
  • mértékegységek és mennyiségek
  • szekvenciális listák
  • opcionális paraméterek
  • asszinkron programozás
  • tömb szeletelés
  • idézett kifejezések
3.0 2012. augusztus[4]
  • LINQ lekérdezés
  • háromszorosan aposztrofált sztringek
  • CLIMutable tulajdonság
  • beépített mértékegységek
3.1 2013. október[5]
  • kiterjesztés a tömb daraboláshoz
  • unió típus név szerinti használata
  • típus következtetési fejlesztések
4.0 2015. július[6]
  • nem null értékű típusszolgáltatók

Áttekintés[szerkesztés]

Funkcionális programozás[szerkeszté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.

Matematikai megadás Definiálás F#-ban
let f x = x * x

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[szerkeszté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[szerkeszté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[szerkesztés]

  1. F# Historical Acknowledgements. (Hozzáférés: 2016. február 17.)
  2. Don Syme: F# 1.0.8 released. Microsoft. (Hozzáférés: 2014. szeptember 7.)
  3. Don Syme: F# 2.0 released as part of Visual Studio 2010. Microsoft. (Hozzáférés: 2014. szeptember 7.)
  4. Jason Zander: Visual Studio 2012 and .NET Framework 4.5 released to the web. Microsoft. (Hozzáférés: 2014. szeptember 7.)
  5. Visual Studio 2013 released to web. Microsoft. (Hozzáférés: 2014. szeptember 7.)
  6. Announcing the RTM of Visual F# 4.0. Microsoft. (Hozzáférés: 2015. szeptember 15.)

További információk[szerkesztés]