Megjegyzés
Az oldalhoz való hozzáféréshez engedély szükséges. Megpróbálhat bejelentkezni vagy módosítani a címtárat.
Az oldalhoz való hozzáféréshez engedély szükséges. Megpróbálhatja módosítani a címtárat.
A függvények a program végrehajtásának alapvető egységei bármilyen programozási nyelven. Más nyelvekhez hasonlóan az F#-függvényeknek is van neve, lehetnek paraméterei, argumentumai, és törzse is van. Az F# olyan funkcionális programozási szerkezeteket is támogat, mint például a függvények értékként való kezelése, a kifejezésekben meg nem nevezett függvények használata, a függvények összetétele új függvények létrehozásához, curried függvények létrehozása, valamint a függvények implicit definíciója a függvényargumentumok részleges alkalmazásával.
A függvényeket a let kulcsszóval, vagy ha a függvény rekurzív, a let rec kulcsszókombinációval definiálhatja.
Szemantika
// Non-recursive function definition.
let [inline] function-name parameter-list [: return-type ] = function-body
// Recursive function definition.
let rec function-name parameter-list = recursive-function-body
Megjegyzések
A függvény neve egy olyan azonosító, amely a függvényt jelöli. A paraméterlista egymást követő paraméterekből áll, amelyeket szóközök választanak el egymástól. Minden paraméterhez megadhat explicit típust a Paraméterek szakaszban leírtak szerint. Ha nem ad meg egy adott argumentumtípust, a fordító megpróbálja kikövetkeztetni a típust a függvény törzséből. A függvénytörzs egy kifejezésből áll. A függvény törzsét alkotó kifejezés általában összetett kifejezés, amely több olyan kifejezésből áll, amelyek egy végső kifejezésben csúcsosulnak ki, amely a visszatérési érték. A visszatérési típus egy kettőspont, amelyet egy típus követ, és nem kötelező. Ha nem adja meg explicit módon a visszatérési érték típusát, a fordító határozza meg a visszatérési típust a végső kifejezésből.
Egy egyszerű függvénydefiníció a következőhöz hasonlít:
let f x = x + 1
Az előző példában a függvény neve f, az argumentum a xtípus int, a függvény törzse x + 1, a visszatérési érték pedig típus int.
A függvények jelölhetők inline. További információ: inlineBeágyazott függvények.
Hatókör
A modul hatókörétől eltérő hatókörszinten nem hiba egy érték vagy függvénynév újbóli felhasználása. Ha újra felhasznál egy nevet, a később deklarált név árnyékot ad a korábban deklarált névnek. A modul legfelső szintű hatókörében azonban a neveknek egyedinek kell lenniük. A következő kód például hibát okoz, ha a modul hatókörében jelenik meg, de nem akkor, ha egy függvényben jelenik meg:
let list1 = [ 1; 2; 3 ]
// Error: duplicate definition.
let list1 = []
let function1 () =
let list1 = [ 1; 2; 3 ]
let list1 = []
list1
A következő kód azonban a hatókör bármely szintjén elfogadható:
let list1 = [ 1; 2; 3 ]
let sumPlus x =
// OK: inner list1 hides the outer list1.
let list1 = [ 1; 5; 10 ]
x + List.sum list1
Paraméterek
A paraméterek nevei a függvény neve után jelennek meg. Egy paraméter típusát az alábbi példában látható módon adhatja meg:
let f (x: int) = x + 1
Ha megad egy típust, az a paraméter nevét követi, és kettőspont választja el a névtől. Ha kihagyja a paraméter típusát, a paraméter típusát a fordító kikövetkezteti. Az alábbi függvénydefinícióban például az argumentum x típusra int lesz kikövetkeztetve, mert az 1 típus int.
let f x = x + 1
A fordító azonban megpróbálja a függvényt a lehető leggenerikusabbá tenni. Jegyezze fel például a következő kódot:
let f x = (x, x)
A függvény bármilyen típusú argumentumból létrehoz egy rekordot. Mivel a típus nincs megadva, a függvény bármilyen argumentumtípussal használható. További információ: Automatikus általánosítás.
Függvénytestek
A függvénytörzsek helyi változók és függvények definícióit tartalmazhatják. Az ilyen változók és függvények hatóköre az aktuális függvény törzsében található, de azon kívül nem. Behúzással kell jeleznie, hogy egy definíció egy függvénytörzsben található, ahogyan az alábbi példában látható:
let cylinderVolume radius length =
// Define a local value pi.
let pi = 3.14159
length * pi * radius * radius
További információ: Kódformázási irányelvek és részletes szintaxis.
Értékek visszaadva
A fordító a függvény törzsében lévő végső kifejezést használja a visszatérési érték és a típus meghatározásához. A fordító a korábbi kifejezések végső kifejezésének típusát is kikövetkezheti. Az előző szakaszban látható függvényben cylinderVolumea függvény típusa pi a konstans 3.14159 típusából lesz meghatározva float. A fordító a kifejezés típusának pi meghatározásához használja a típust length * pi * radius * radiusfloat. Ezért a függvény általános visszatérési típusa a .float
A visszatérési típus explicit megadásához írja be a kódot a következő módon:
let cylinderVolume radius length : float =
// Define a local value pi.
let pi = 3.14159
length * pi * radius * radius
Ahogy a kód fent meg van írva, a fordító a teljes függvényre alkalmazza a lebegőpontos kódot ; ha a paramétertípusokra is alkalmazni szeretné, használja a következő kódot:
let cylinderVolume (radius: float) (length: float) : float
Függvény meghívása
Függvényeket úgy hívhat meg, hogy megadja a függvény nevét, majd egy szóközt, majd a szóközök által elválasztott argumentumokat. Ha például meghívja a hengerVolume függvényt , és hozzárendeli az eredményt az vol értékhez, írja be a következő kódot:
let vol = cylinderVolume 2.0 3.0
Argumentumok részleges alkalmazása
Ha a megadott számú argumentumnál kevesebbet ad meg, hozzon létre egy új függvényt, amely a fennmaradó argumentumokat várja. Az argumentumok kezelésének ezt a módszerét currysnek nevezik, és olyan funkcionális programozási nyelvekre jellemző, mint az F#. Tegyük fel például, hogy két csőmérettel dolgozik: az egyik sugara 2,0 , a másik sugara 3,0. Az alábbiak szerint hozhat létre olyan függvényeket, amelyek meghatározzák a cső mennyiségét:
let smallPipeRadius = 2.0
let bigPipeRadius = 3.0
// These define functions that take the length as a remaining
// argument:
let smallPipeVolume = cylinderVolume smallPipeRadius
let bigPipeVolume = cylinderVolume bigPipeRadius
Ezután adja meg a végső argumentumot, szükség szerint a két különböző méretű cső különböző hosszához:
let length1 = 30.0
let length2 = 40.0
let smallPipeVol1 = smallPipeVolume length1
let smallPipeVol2 = smallPipeVolume length2
let bigPipeVol1 = bigPipeVolume length1
let bigPipeVol2 = bigPipeVolume length2
Rekurzív függvények
A rekurzív függvények maguknak nevezett függvények. Megkövetelik, hogy a let kulcsszót követve adja meg a rec kulcsszót. Hívja meg a rekurzív függvényt a függvény törzséből ugyanúgy, ahogyan bármely függvényhívást hívna meg. Az alábbi rekurzív függvény kiszámítja az n-edik Fibonacci-számot. A Fibonacci számsorozat már az ókor óta ismert, és olyan sorozat, amelyben minden egymást követő szám a sorozat előző két számának összege.
let rec fib n =
if n < 2 then 1 else fib (n - 1) + fib (n - 2)
Egyes rekurzív függvények túlcsordíthatják a program vermet, vagy nem hatékonyak, ha nem gondosan és speciális technikákkal, például a farokrekurzió, az akkumulátorok és a folytatások használatával írják meg őket.
Függvényértékek
Az F#-ban minden függvény értéknek számít; valójában függvényértékekként ismertek. Mivel a függvények értékek, argumentumként használhatók más függvények vagy más olyan környezetekben, ahol az értékeket használják. Az alábbi példa egy függvényre mutat be példát, amely argumentumként egy függvényértéket vesz fel:
let apply1 (transform: int -> int) y = transform y
A függvényérték típusát a -> jogkivonat használatával adhatja meg. A jogkivonat bal oldalán található az argumentum típusa, a jobb oldalon pedig a visszatérési érték. Az előző példában apply1 egy függvény argumentumként vesz fel egy függvényt transform , ahol transform egy függvény egész számot vesz fel, és egy másik egész számot ad vissza. A következő kód bemutatja a használat módját apply1:
let increment x = x + 1
let result1 = apply1 increment 100
Az érték result 101 lesz az előző kód futtatása után.
Több argumentumot egymást követő -> jogkivonatok választanak el egymástól, ahogy az a következő példában is látható:
let apply2 (f: int -> int -> int) x y = f x y
let mul x y = x * y
let result2 = apply2 mul 10 20
Az eredmény 200.
Lambda-kifejezések
A lambda kifejezés egy névtelen függvény. Az előző példákban a nevesített függvények növekményének és mul értékének meghatározása helyett a lambda kifejezéseket az alábbiak szerint használhatja:
let result3 = apply1 (fun x -> x + 1) 100
let result4 = apply2 (fun x y -> x * y) 10 20
A lambda kifejezéseket a fun kulcsszó használatával definiálhatja. A lambda kifejezés hasonlít egy függvénydefinícióra, azzal a kivételrel, hogy a = jogkivonat helyett a -> jogkivonat az argumentumlistát választja el a függvény törzsétől. A normál függvénydefiníciókhoz hasonlóan az argumentumtípusok kikövetkeztethetők vagy explicit módon is meghatározhatók, a lambda kifejezés visszatérési típusa pedig a törzs utolsó kifejezésének típusából lesz levonva. További információ: Lambda Expressions: The fun Keyword.
Csővezetékek
A cső operátor |>-t széles körben használják az F# adatok feldolgozásakor. Ez az operátor lehetővé teszi a függvények "csatornáinak" rugalmas kialakítását. A pipelining lehetővé teszi a függvényhívások egymást követő műveletekként való összekapcsolását:
let result = 100 |> function1 |> function2
Az alábbi minta bemutatja, hogyan használhatja ezeket az operátorokat egy egyszerű funkcionális folyamat létrehozásához:
/// Square the odd values of the input and add one, using F# pipe operators.
let squareAndAddOdd values =
values |> List.filter (fun x -> x % 2 <> 0) |> List.map (fun x -> x * x + 1)
let numbers = [ 1; 2; 3; 4; 5 ]
let result = squareAndAddOdd numbers
Az eredmény [2; 10; 26]. Az előző minta listafeldolgozó függvényeket használ, amelyek bemutatják, hogyan használhatók a függvények az adatok feldolgozására a folyamatok létrehozásakor. Maga a folyamatkezelő az F#-magtárban van definiálva az alábbiak szerint:
let (|>) x f = f x
Függvényösszetétel
Az F# függvényei más függvényekből is összeállíthatók. Két függvényfüggvény1 és függvény2 összetétele egy másik függvény, amely a függvény1 alkalmazását, majd a függvény2 alkalmazását jelöli:
let function1 x = x + 1
let function2 x = x * 2
let h = function1 >> function2
let result5 = h 100
Az eredmény 202.
Az összeállítási operátor >> két függvényt vesz fel, és egy függvényt ad vissza. Ezzel szemben a folyamat operátora |> egy értéket és egy függvényt vesz fel, és egy értéket ad vissza. Az alábbi példakód a folyamat és az összeállítási operátorok közötti különbséget mutatja be a függvény-aláírások és a használat különbségeinek bemutatásával.
// Function composition and pipeline operators compared.
let addOne x = x + 1
let timesTwo x = 2 * x
// Composition operator
// ( >> ) : ('T1 -> 'T2) -> ('T2 -> 'T3) -> 'T1 -> 'T3
let Compose2 = addOne >> timesTwo
// Backward composition operator
// ( << ) : ('T2 -> 'T3) -> ('T1 -> 'T2) -> 'T1 -> 'T3
let Compose1 = addOne << timesTwo
// Result is 5
let result1 = Compose1 2
// Result is 6
let result2 = Compose2 2
// Pipelining
// Pipeline operator
// ( |> ) : 'T1 -> ('T1 -> 'U) -> 'U
let Pipeline2 x = addOne x |> timesTwo
// Backward pipeline operator
// ( <| ) : ('T -> 'U) -> 'T -> 'U
let Pipeline1 x = addOne <| timesTwo x
// Result is 5
let result3 = Pipeline1 2
// Result is 6
let result4 = Pipeline2 2
Túlterhelési függvények
Egy típus metódusait túlterhelheti, de függvényeket nem. További információ: Metódusok.