F Sharp
Z Multimediaexpo.cz
- Název tohoto článku není z technických důvodů zcela správný. Správný název by měl být F#.
F# (vyslovované anglicky jako F Sharp, 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 bude součástí připravovaného Visual Studia 2010[1]. V současné době se o vývoj jazyka stará Microsoft Research.
Obsah |
Cíle jazyka a souhrn vlastností
F# byl vyvinutý jako varianta ML s mnoha konstrukcemi převzatými z OCaml. Narozdíl od mnoha skriptovacích jazyků se rychlostí blíží k C# (především díky silné typovosti). 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[2] 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 .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 .NET
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 i že 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[3]. Syntaxe jazyka se pro skriptování v některých detailech liší, navíc je možné používat tzv. 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 </code>let</code>, které
znamená automatické přiřazení 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é slova new
. 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 [3].
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<code>.
Důležitou konstrukcí F# je pattern matching, umožňuje porovnávat výraz s jinými resp. hledět na jeden výraz z několika pohledů. Nejčastější aplikací je rozložení typu tuple (viz níže) nebo řízení toku programu konstrukcí <code>match proměnná with | když-výraz -> tak-výraz kde část po |
se může libovolněkrát opakovat. 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. Mimoto jsou v F# další aliasy na často používané třídy .NET, například obj
pro System.Object nebo ResizeArray<T>
pro System.Collections.Generic.List<T> (kvůli odlišení od F# typu List)[3].
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. 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#. 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 vlastnosti.
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
vyjádřuje typ tuple s třemi položkami, první typu int a zbylé dvě typu
BinaryTree.
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ý spojovaný 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ř. 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í jazkyky 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
.
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é[3].
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. 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 .NET tříd i rozhraní (v terminologii F# společně nazývané object types – objektové typy) v podobném rozsahu jako ostatní jazyky .NET[3].
F# od verze 1.9.1 obsahuje tzv. sequence expressions (sekvenční výrazy)[4] 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[3], 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ů[3]. 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. Pro zjednodušení se tak používá klasický křížek.
Příklady
Příklad nejjednodušší aplikace:
printfn "Ahoj světe."
Příklad demonstrující syntaxi jazyka na funkci rekurzivně počítající faktoriál:
let rec factorial n = match n with | 0 -> 1 | _ -> n * factorial (n – 1)
Příklad cyklu for, vypíše čísla od 1 do 10:
for n = 1 to 10 do printfn "%d" n
Příklad cyklu while:
let mutable n = 3 while n < 10 do n <- (n+1) printfn "%d" n
Příklad cyklu for (foreach) v F#, vrátí pole sudých čísel od 2 do 20:
let nums = [1..10] [ for num in nums do yield num*2 ]
Příklad jednoduché okenní aplikace .NET:
(* otevření formulářové knihovny .NET *) 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 <- sprintf "x = %d" x (* vrácení hodnoty (do proměnné label) *) temp (* přidání nápisu do okna *) do form.Controls.Add(label) (* spuštění aplikace *) [<STAThread>] do Application.Run(form)
Externí odkazy
- ↑ . Dostupné online.
- ↑ . Dostupné online.
- ↑ 3,0 3,1 3,2 3,3 3,4 3,5 3,6 . Dostupné online.
- ↑ . Dostupné online.
Náklady na energie a provoz naší encyklopedie prudce vzrostly. Potřebujeme vaši podporu... Kolik ?? To je na Vás. Náš FIO účet — 2500575897 / 2010 |
---|
Informace o článku.
Článek je převzat z Wikipedie, otevřené encyklopedie, do které přispívají dobrovolníci z celého světa. |