F Sharp

Technology
12 hours ago
8
4
2
Avatar
Author
Albert Flores

F# (vyslovované anglicky jako F Sharp, /ef ʃɑɹp/, doslova to označuje notu fis) je multiparadigmatický programovací jazyk pro .NET spojující funkcionální přístup s imperativním objektově orientovaným přístupem. Syntaxe jazyka vychází z ML a OCaml a dále je ovlivněna jazyky Haskell, C# a LINQ. F# je plně podporovaným jazykem pro platformu .NET a je součástí Visual Studia od verze 2010. V současné době se o vývoj jazyka stará Microsoft Research.

Cíle jazyka a souhrn vlastností

F# byl vyvinutý jako varianta ML s mnoha konstrukcemi převzatými z OCaml. Na rozdíl od mnoha skriptovacích jazyků se rychlostí blíží k C# (především díky silné typovosti). +more Podporuje také řadu dynamických programovacích technik, jako je například reflexe. F# umožňuje propojení s dalšími jazyky včetně snadné implementace DSL, bezproblémově spolupracuje se všemi jazyky . NET.

Microsoft Research zmiňuje mezi hlavní výhody jazyka tyto: * funkcionální jazyk se stručnou syntaxí a implicitním typováním * možnost interaktivního skriptování (jako v Pythonu) * kombinace typové bezpečnosti a implicitního typování (jako v ML) * výkon na úrovni C#, nativní běh na . NET frameworku * přístup ke všem knihovnám +moreNET'>. NET * integrovanost a plná podpora ve Visual Studiu.

F# je silně typový jazyk který ovšem používá implicitní typování (datový typ proměnné se nemusí specifikovat explicitně, překladač ho rozpozná podle přiřazované hodnoty). Jako jazyk pro . +moreNET podporuje F# všechny typy z . NET frameworku ale navíc přidává několik neměnných typů (změna jejich hodnoty je možná pouze vytvořením nové kopie) svázaných se specifickými vlastnostmi jazyka a používaných především pro úlohy funkcionálního programování. Těmito typy jsou: tuple, record, discriminated union, list a function. V této souvislosti stojí za zmínku, že i typy . NET jsou standardně v F# neměnné, opaku lze docílit použitím klíčového slova mutable.

Důležitou vlastností jazyka je interaktivní skriptování, které umožňuje komponenta F# Interactive. Syntaxe jazyka se pro skriptování v některých detailech liší, navíc je možné používat tzv. +more light syntaxi. Jde ale jen o drobné rozdíly v ukončování příkazů.

Syntaxe jazyka

Syntaxe jazyka jak už bylo řečeno vychází hlavně z ML a OCaml. Nejvýrazněji se na vzhledu kódu podepisují jazykové konstrukce implicitního typování a pattern matchingu.

V jazyce existují komentáře dvojího typu, řádkové uvozené // a víceřádkové začínající znaky (* a končící *).

Proměnná (name v terminologii F#, protože se nejedná o proměnné v klasickém slova smyslu, mohou totiž uchovávat i funkce) se deklaruje tak že jejímu názvu předchází klíčové slovo let, které zároveň znamená automatické určení typu proměnné (podobně jako var v C# 3.0).

Hodnota se proměnné přiřadí při deklaraci pomocí operátoru =, pokud je potřeba ji později změnit (pouze v kontextu měnitelných proměnných označených klíčovým slovem mutable), slouží k tomu operátor .

Pro spolupráci s . NET je důležitá konstrukce pro tvorbu objektů převzatá z C# - objekty se tvoří pomocí klíčového slova new. +more Pro „oznámení“ používání nějakého namespace se používá klíčové slovo open (ekvivalent using v C#). K vlastnostem a metodám se přistupuje klasicky přes tečkovou notaci a metody se volají s parametry v závorkách.

Mezi literály, mimo klasické čísla a řetězce, patří také některé konstrukce F#, jako tuple (viz dále).

Datový typ (třída) se deklaruje pomocí klíčového slova type a to jak typy .NET tak i speciální typy F#, konkrétněji viz níže nebo v.

Funkce se definují několika způsoby, buď pomocí klíčového slova fun, nebo jako výraz kde na levé straně jsou vedle let a názvu také parametry a za rovnítkem následuje definice. Rekurzivní funkce musejí být jako rekurzivní explicitně definovány pomocí klíčového slova rec.

Důležitou konstrukcí F# je pattern matching, umožňuje porovnávat výraz s jinými a podle toho rozhodnout o dalším postupu výpočtu, přitom pojmenuje a tím získá přístup na složky dat. Nejčastější aplikací je rozložení typu tuple (viz níže) nebo řízení toku programu konstrukcí match proměnná with | když-výraz -> tak-výraz kde část po | se může libovolněkrát opakovat. +more Tato konstrukce může nahradit řadu ifů a switchů a zlepšit čitelnost kódu.

F# podporuje i základní cykly. Ty jsou vlastně funkce bez návratové hodnoty (v terminologii jazyka F# „výrazy typu unit“).

Klasický cyklus for je uvozen klíčovým slovem for, následuje řídící proměnná, rovnítko, počáteční hodnota, klíčové slovo to nebo downto (určující přičítání/odčítání jedničky), koncová hodnota, do a tělo cyklu. Jinak řečeno: for řídící_prom = počáteční_hodnota [down]to konečná_hodnota do tělo_cyklu.

Cyklus známý jako foreach (projde celé pole a do každé iterace nabídne jednu položku) se zapíše [for jedna_položka in procházené_pole do tělo_cyklu ].

Cyklus while má jednoduchou syntaxi while podminka do tělo_cyklu.

Datové typy F#

Všechny typy F# jsou aliasy pro speciální generické datové typy . NET. +more Mimoto jsou v F# další aliasy na často používané třídy . NET, například obj pro System. Object nebo ResizeArray pro System. Collections. Generic. List (kvůli odlišení od F# typu List).

Tuple

Tuple je nejjednodušší speciální datový typ v F#. Umožňuje „zabalit“ dvě nebo více nepojmenovaných hodnot každou libovolného typu. +more Množství i typ hodnot musejí být známy už při překladu. Je to v podstatě primitivní přepravka vhodná pro interní použití jež ani nemusí být explicitně definována jako typ (vytvoří se automaticky při použití). Každý tuple je odvozen od generické třídy Tuple.

Příklad uložení jména se soundexovým kódem a jeho rozložení na hodnoty pomocí jednoduché konstrukce pattern matching: let mrCarroll = ("Carroll", "C64") let (name, soundex) = mrCarroll Tentýž příklad v interaktivním režimu (s odpověďmi konzole): > let mrCarroll = ("Carroll", "C64");; val mrCarroll : string * string = ("Carroll", "C64") > let (name, soundex) = mrCarroll;; val soundex : string = "C64" val name : string = "Carroll"

Record

Record (záznam) je rozšířeným typem tuple. Umožňuje pojmenovat jednotlivé datové složky a přistupovat k nim známou „tečkovou notací“, velmi se tak podobá typu struct v C#. +more Record už musí být definován jako typ. S . NET je record provázán tak že při jeho definici se vytvoří třída a jednotlivé datové složky má jako atributy.

Příklad vytvoření Recordu a odvození z něj druhého: type ShopItem = { Name:string; Price:int } let commonCar = { Name="car"; Price=1000 } let luxuryCar = { commonCar with Price=5000 }

Discriminated union

Discriminated union je typ který umožňuje uložení hodnoty jednoho z různých nabídnutých typů. O konkrétním typu se rozhoduje podle volaného konstruktoru.

Příklad elegantní reprezentace binárního stromu pomocí Discriminated union. Zápis int * BinaryTree * BinaryTree vyjadřuje typ tuple s třemi položkami, první typu int a zbylé dvě typu BinaryTree. +more type BinaryTree = | Fork of int * BinaryTree * BinaryTree | Leaf of int let heap = Fork (2,Fork (17,Fork (22,Leaf (49),Leaf (31)),Leaf (51)),Fork (29,Leaf(11),Leaf (25))).

List

List (seznam) je typický spojový seznam tvořený vždy položkou a odkazem na zbytek seznamu v zápise první_položka::zbytek_seznamu (tzv. tail operátor známý např. +more z Lispu) nebo ve zkráceném zápise [ hodnota1;hodnota2;. ]. Prázdný seznam se zapíše [].

F# obsahuje také speciální jazykovou konstrukci pro tvorbu typu array který ale je standardním typem .NET a není tedy neměnný. Lze ho vytvořit konstrukcí [| hodnota1;hodnota2;... |].

Příklad dvou možných zápisů tvorby seznamu List: let list1 = 1::2::3::[] let list2 = [1; 2; 3]

Function

V F# je každá funkce typem. Funkce jsou také neměnným typem, ale F# nabízí řadu možností jak upravovat jejich volání, například použitím curryingu nebo skládáním funkcí, funkce mohou být předávány jako parametry dalších funkcí, F# také podporuje lambda funkce.

Příklad definice jednoduché funkce pro sčítání a následně z ní odvozené funkce pro přičtení 10tky (jednoduchá ukázka techniky zvané currying) a nakonec volání které vyústí v hodnotu 20 uloženou v proměnné twenty: let add = ( fun lhs rhs -> lhs + rhs ) let add10 = add 10 let twenty = add10 10

Funkci add lze také nadefinovat takto: let add lhs rhs = lhs + rhs

Příklad funkce sumy všech hodnot v Listu. Řešeno pro funkcionální jazyky typickým způsobem (odpojení první položky, její zpracování, a rekurzivní volání na zbytek pole), využívá pattern matching a ilustruje deklaraci rekurzivní funkce klíčovým slovem rec. +more let list = [ 1 . 10 ] (* seznam se všemi položkami od 1 do 10 *) //pomocná funkce s akumulační proměnnou acc let rec sumAcc acc list = match list with | top::tail -> sumAcc (acc + top) tail | _ -> acc //výsledná funkce sumy let sum list = sumAcc 0 list let res = sum list (* val res : int = 55 *).

K předchozímu příkladu stojí za zmínku i vlastnost jazyka F# podobná se zásobníkovými jazyky, totiž že obě funkce by se mohly jmenovat stejně a program by fungoval správně, druhá by skryla první a sama by ji uvnitř bez problémů volala. Je to dáno způsobem, jakým v F# funguje obor hodnot proměnné.

Vlastnosti jazyka

F# používá pattern matching jednak aby převedl jména na hodnoty, ale také pro kontrolu, zda mají data požadovanou strukturu nebo hodnotu. Pattern matching může být použit se všemi standardními F# typy, nejčastěji s typy tuple a discriminated union. +more Jazyk F# také podporuje obecnější pattern matching pomocí tzv. active patterns, které umožňují kontrolu dat z různých pohledů na typ.

Protože je jazyk F# určen pro platformu . NET (musí vyhovovat požadavkům CLI) a protože jako jedno z paradigmat podporuje imperativní objektově orientované programování, obsahuje konstrukce pro tvorbu smyček for a while a . +moreNET tříd i rozhraní (v terminologii F# společně nazývané object types - objektové typy) v podobném rozsahu jako ostatní jazyky . NET.

F# od verze 1. 9. +more1 obsahuje tzv. sequence expressions (sekvenční výrazy) zapisované jako seq{ . }, které obsahují sekvenční bloky různých konstrukcí. Na rozdíl od ostatních jazykových konstrukcí F# jsou „líně vykonávané“ (lazily evaluated, tj. vyhodnocují se až v momentě využití). Mohou být použity pro filtrování i pro zkrácení zápisu (mnoharozměrné) kolekce. Jsou základem pro podporu LINQ a důležité pro asynchronní volání (async{ . }).

F# je díky kombinaci vlastností funkcionálních a objektových jazyků vhodný na programování asynchronních operací a vícevláknových aplikací pro víceprocesorové systémy.

Jako jedno z paradigmat které F# do jisté míry přejímá je Language-oriented programming, usnadňuje tak tvorbu DSL, ovšem omezenou syntaxí jazyka (lze „pouze“ změnit význam příkazů F#). Nejjednodušší příklad je využití discriminated unions jako deklarativní jazyk na vyhodnocování aritmetických výrazů. +more F# rozšiřuje schopnosti . NET System. Reflection a umožňuje tak meta-programming (meta programování - manipulování s kódem jako s daty).

Název jazyka

Název jazyka F# je, podobně jako v ostatních jazycích .NET (počínaje jazykem C#), odvozen z hudební notace, kde křížek označuje zvýšení noty o půl tónu a v tomto případě by označoval notu fis, tedy F zvýšené o půl tónu.

Křížek na počítačové klávesnici (#) a křížek v hudební nauce (♯) jsou dva odlišné znaky. Pro zápis názvu jazyka F Sharp se nepoužívá znak hudebního křížku z technických důvodů, protože tento se na standardní klávesnici nevyskytuje. +more Pro zjednodušení se tak používá klasický křížek.

Příklady

Výpis na standardní výstup: printfn "Ahoj světe."

Jednoduchá rekurzivně definovaná funkce, která slouží k výpočtu faktoriálu: let rec factorial n = match n with | 0 -> 1 | _ -> n * factorial (n - 1)

Cyklus s předem známým počtem opakování (typu for), který vypíše celá čísla od 1 do 10: for n = 1 to 10 do printfn "%d" n

Cyklus s předem neznámým počtem opakování (typu while), jenž vypíše celá čísla od 4 do 10: let mutable n = 3 while n

Cyklus s předem známým počtem opakování (typu foreach), který pole deseti celých čísel od 1 do 10 přetaví na pole deseti sudých čísel od 2 do 20: let nums = [1..10] [ for num in nums do yield num*2 ]

Jednoduchá aplikace . NET s grafickým uživatelským rozhraním: (* otevření formulářové knihovny . +moreNET *) open System. Windows. Forms (* vytvoření okna(Form) a nastavení vlastností *) let form = new Form(Visible=true, TopMost=true, Text="Welcome to F#") (* vytvoření nápisu(Label) s textem *) let label = let temp = new Label let x = 3 + (4 * 5) (* nastavení hodnoty vlastnosti Text *) temp. Text ] do Application. Run(form).

Reference

5 min read
Share this post:
Like it 8

Leave a Comment

Please, enter your name.
Please, provide a valid email address.
Please, enter your comment.
Enjoy this post? Join Cesko.wiki
Don’t forget to share it
Top