F Sharp

programovací jazyk
Název tohoto článku nemůže z technických důvodů obsahovat znak #. Správný název by měl být F#.

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[2] od verze 2010. V současné době se o vývoj jazyka stará Microsoft Research.

F#
Paradigmamultiparadigmatický
Vznik2002
AutorMicrosoft Research, Don Syme
VývojářMicrosoft, The F# Software Foundation
Poslední verze3.1.1[1] (24. 1. 2014)
Typová kontrolastatické, silné, implicitní
Ovlivněn jazykyOCaml, C#, Python, Haskell, ML, LINQ, Scala, Erlang
Ovlivnil jazykyF*, LiveScript, C#
OSMultiplatformní (.NET, Mono)
LicenceApache license
WebMicrosoft Research - F#

Cíle jazyka a souhrn vlastností

editovat

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). 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[3] 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, ž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[4]. 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

editovat

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. 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[4].

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. 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 podmínka do tělo_cyklu.

Datové typy F#

editovat

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)[4].

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 (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 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

editovat

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.

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 (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ř. 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

editovat

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.

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é[4].

Vlastnosti jazyka

editovat

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[4].

F# od verze 1.9.1 obsahuje tzv. sequence expressions (sekvenční výrazy)[5] 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[4], 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ů[4]. 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

editovat

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

editovat

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 < 10 do
    n <- (n+1)
    printfn "%d" 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 .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)

Reference

editovat
  1. Archivovaná kopie. visualstudiogallery.msdn.microsoft.com [online]. [cit. 2014-10-05]. Dostupné v archivu pořízeném dne 2014-02-22. 
  2. SOMASEGAR, Sam. F# - A Functional Programming Language [online]. [cit. 2009-12-02]. Dostupné online. 
  3. Microsoft Research [online]. [cit. 2009-12-02]. Dostupné online. 
  4. a b c d e f g PETŘÍČEK, Tomáš. F# Language Overview [online]. [cit. 2009-12-01]. Dostupné online. 
  5. SYME, Don. Some Details on F# Computation Expressions [online]. [cit. 2009-12-03]. Dostupné online. 

Externí odkazy

editovat
  •   Obrázky, zvuky či videa k tématu F# na Wikimedia Commons
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy