F# programocskák VS 2008 interaktív módban gyorsan kipróbálhatók. Ehhez a szkript fájl(.fsx) első sorába a #light szót kell írni, ami azt jelenti, hogy használhatjuk a könnyített szintaxist. A blokkokat nem kell jelölni begin-nel és end -del, hanem elég behúzással jelölni azokat. Ekkor viszont a szkripter szól, ha rosszak a tabulációk. Az egyes függvényeket két darab pontosvesszővel le kell zárni.
A neten található példaprogramok kipróbálása során tapasztaltam, hogy a a fordító hiányolta a FSharp.Powerpack.dll-t. Hiába adtam a projekthez a referenciáját, nem volt hatása. Eheleyett érdemes a szkript elejére beírni:
#r @"FSharp.PowerPack"
Az F#-ban függvényekkel dolgozunk. Ez azt jelenti, hogy egy függvényt hasonlóan adhatunk meg, mint a matematikában szokásos jelölés: f(x) = x*x. Ugyanez F#-ban:let f x = x*x;;
A függvényt a let szóval kell indítani.A függvény hívása:
f 100
Az interaktív ablakban megjelenik az eredmény:
val f : int -> int
> val it : int = 10000
Látható, hogy a függvény visszatérési típusát nem kell definiálni, azt az F# állapítja meg.
Tegyük fel, hogy nem csak egész számokkal hívjuk meg a fenti függvényt! Pl. f 100.0
Ebben az esetben hibaüzenetet kapunk. error FS0001: This expression has type float but is here used with type int.
Úgy látszik, hogyaz F# alapból mindent int-nek tekint. Megoldás, megadjuk a bemenő paraméterek típusát:
let f (x : float) = x*x;;
f 100.0
Nézzünk egy komplexebb példát. Egy tízes számrendszerben megadott számot írunk át egy másikba:
#light
#r @"FSharp.PowerPack";;
//Felsoroljuk a számjegyeket
let szamjegyek = ['0';'1';'2';'3';'4';'5';'6';'7';'8';'9';'A';'B';'C';'D';'E';'F'];;
//Rekurzív hívással előállíjuk a számjegyek sorozat
let rec atir szam alap =
let h = int(truncate (float(szam / alap)))
//A maradék lesz a számjegy, h=0 a kilépési pont majd rekurzív hívás a hányadossal
int(szam % alap) :: if h=0 then [] else atir h alap;;
//A Framework System.Text namespace-t használjuk
open System.Text
let osszefuz x =
let y = new StringBuilder()
//Megfordítjuk a listát, a számokat konvertáljuk számjegyekre, majd hozzáadjuk a StringBuilder-hez
let o = x |> List.rev |> List.map(fun x -> List.nth szamjegyek x) |> List.map(fun x -> y.Append(x))
//Ez a visszatérési érték
y.ToString();;
atir 4096 16 |> osszefuz |> printf "%A " ;;
A fenti példában több új elem is van:
rec - kel jelöljük, hogy rekurzív a hívás.
|> pipeline operátor; a paraméter átadás kényelmes módja
fun x-> List.nth szamjegyek x egy un. lambda függvény, azaz a függvényt nem definiáljuk külön, hanem "inline" adjuk meg. Ez helyettesíthető lenne ezzel: let conv x = List.nth szamjegyek x;;
Nézzük ugyanezt C#-ban. Jól láthatóak a különbségek. Egyszerűbbnek tűnik. Lehet, hogy ez az én ügyetlenségem még.
class Program
{
static char[] szamjegyek = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F' };
static void Main(string[] args)
{
StringBuilder szamok = new StringBuilder();
atir(4096, 16, szamok);
System.Diagnostics.Debug.Write(szamok.ToString());
}
static void atir(int szam, int alap, StringBuilder szamok)
{
int h = (int)(szam / alap);
if (h!=0)
atir (h, alap, szamok);
szamok.Append(szamjegyek[szam % alap]);
}
}