Paraméterek és argumentumok
Ez a témakör a paraméterek definiálásának és az argumentumok függvényeknek, metódusoknak és tulajdonságoknak való átadásának nyelvi támogatását ismerteti. Információkat tartalmaz arról, hogyan adhat át hivatkozás alapján, és hogyan definiálhat és használhat olyan metódusokat, amelyek változó számú argumentumot tartalmazhatnak.
Paraméterek és argumentumok
A kifejezésparaméter a várhatóan megadandó értékek nevét írja le. A kifejezés argumentum az egyes paraméterekhez megadott értékekhez használatos.
A paraméterek megadhatók tuple vagy curried formában, vagy a kettő valamilyen kombinációjában. Az argumentumokat explicit paraméternévvel adhatja át. A metódusok paraméterei megadhatóak választhatóként, és megadhatnak egy alapértelmezett értéket.
Paraméterminták
A függvényekhez és metódusokhoz megadott paraméterek általában szóközökkel elválasztott minták. Ez azt jelenti, hogy a Match Expressionsben leírt minták elvileg használhatók egy függvény vagy tag paraméterlistájában.
A metódusok általában az átadott argumentumok rekordformájú formáját használják. Ez egyértelműbb eredményt ad más .NET-nyelvek szempontjából, mivel a rekordforma megegyezik az argumentumok .NET-metódusokban való átadásának módjával.
A curried űrlapot leggyakrabban kötések használatával let
létrehozott függvényekkel használják.
Az alábbi pszeudokód példákat mutat be a rekord- és a curriált argumentumokra.
// Tuple form.
member this.SomeMethod(param1, param2) = ...
// Curried form.
let function1 param1 param2 = ...
A kombinált űrlapok akkor lehetségesek, ha egyes argumentumok össze vannak kötve, és vannak, amelyek nem.
let function2 param1 (param2a, param2b) param3 = ...
A paraméterlistákban más minták is használhatók, de ha a paraméterminta nem felel meg az összes lehetséges bemenetnek, előfordulhat, hogy a futtatáskor hiányos egyezés van. A kivétel MatchFailureException
akkor jön létre, ha egy argumentum értéke nem egyezik a paraméterlistában megadott mintákkal. A fordító figyelmeztetést ad ki, ha egy paraméterminta lehetővé teszi a hiányos egyezéseket. Legalább egy másik minta gyakran hasznos paraméterlistákhoz, és ez a helyettesítő karakterminta. A helyettesítő karakterek mintáját akkor használja egy paraméterlistában, ha egyszerűen figyelmen kívül szeretné hagyni a megadott argumentumokat. Az alábbi kód egy argumentumlistában szemlélteti a helyettesítő karakterek használatát.
let makeList _ = [ for i in 1 .. 100 -> i * i ]
// The arguments 100 and 200 are ignored.
let list1 = makeList 100
let list2 = makeList 200
A helyettesítő karakterminta akkor lehet hasznos, ha nincs szüksége a programnak átadott argumentumokra, például a fő belépési pontban, ha nem érdeklik a sztringtömbként általában megadott parancssori argumentumok, mint az alábbi kódban.
[<EntryPoint>]
let main _ =
printfn "Entry point!"
0
Az argumentumokban néha használt egyéb minták a minta, valamint a as
diszkriminált egyesítőkhöz és az aktív mintákhoz társított azonosító minták. Az egy-eseti diszkriminált egyesítő mintát az alábbiak szerint használhatja.
type Slice = Slice of int * int * string
let GetSubstring1 (Slice(p0, p1, text)) =
printfn "Data begins at %d and ends at %d in string %s" p0 p1 text
text[p0..p1]
let substring = GetSubstring1 (Slice(0, 4, "Et tu, Brute?"))
printfn "Substring: %s" substring
A kimenet a következő.
Data begins at 0 and ends at 4 in string Et tu, Brute?
Et tu
Az aktív minták paraméterekként hasznosak lehetnek, például amikor egy argumentumot kívánt formátummá alakítanak át, ahogyan az alábbi példában is látható:
type Point = { x : float; y : float }
let (| Polar |) { x = x; y = y} =
( sqrt (x*x + y*y), System.Math.Atan (y/ x) )
let radius (Polar(r, _)) = r
let angle (Polar(_, theta)) = theta
A mintával as
helyi értékként tárolhat egy egyeztetett értéket, ahogy az az alábbi kódsorban is látható.
let GetSubstring2 (Slice(p0, p1, text) as s) = s
Az időnként használt másik minta egy olyan függvény, amely az utolsó argumentumot névtelenül hagyja, mivel a függvény törzseként egy lambda kifejezést ad meg, amely azonnal végrehajt egy mintaegyezést az implicit argumentumon. Erre példa a következő kódsor.
let isNil = function [] -> true | _::_ -> false
Ez a kód egy olyan függvényt határoz meg, amely egy általános listát vesz fel, és akkor ad vissza true
, ha a lista üres, és false
egyébként. Az ilyen technikák használata megnehezítheti a kód olvasását.
Időnként hasznosnak bizonyulhatnak a hiányos egyezéseket tartalmazó minták, például ha tudja, hogy a program listáinak csak három eleme van, akkor egy paraméterlistában az alábbihoz hasonló mintát használhat.
let sum [a; b; c;] = a + b + c
A hiányos egyezésekkel rendelkező minták használata a legjobban a gyors prototípus-készítéshez és más ideiglenes használatra van fenntartva. A fordító figyelmeztetést ad ki az ilyen kódhoz. Az ilyen minták nem fedik le az összes lehetséges bemenet általános esetét, ezért nem alkalmasak az összetevő API-k használatára.
Névvel ellátott argumentumok
A metódusok argumentumai vesszővel tagolt argumentumlistában elfoglalt pozíció alapján határozhatók meg, vagy explicit módon továbbíthatók egy metódusnak a név megadásával, majd egy egyenlőségjellel és az átadandó értékkel. Ha a név megadásával van megadva, a deklarációban használttól eltérő sorrendben jelenhetnek meg.
Az elnevezett argumentumok a kód olvashatóbbá és könnyebben módosíthatóvá tehetik az API bizonyos módosításait, például a metódusparaméterek átrendezését.
A névvel ellátott argumentumok csak metódusok esetén engedélyezettek, nem let
pedig -bound függvényekhez, függvényértékekhez vagy lambdakifejezésekhez.
Az alábbi példakód az elnevezett argumentumok használatát mutatja be.
type SpeedingTicket() =
member this.GetMPHOver(speed: int, limit: int) = speed - limit
let CalculateFine (ticket : SpeedingTicket) =
let delta = ticket.GetMPHOver(limit = 55, speed = 70)
if delta < 20 then 50.0 else 100.0
let ticket1 : SpeedingTicket = SpeedingTicket()
printfn "%f" (CalculateFine ticket1)
Egy osztálykonstruktor hívásában az osztály tulajdonságainak értékeit az elnevezett argumentumokhoz hasonló szintaxissal állíthatja be. Az alábbi példa ezt a szintaxist mutatja be.
type Account() =
let mutable balance = 0.0
let mutable number = 0
let mutable firstName = ""
let mutable lastName = ""
member this.AccountNumber
with get() = number
and set(value) = number <- value
member this.FirstName
with get() = firstName
and set(value) = firstName <- value
member this.LastName
with get() = lastName
and set(value) = lastName <- value
member this.Balance
with get() = balance
and set(value) = balance <- value
member this.Deposit(amount: float) = this.Balance <- this.Balance + amount
member this.Withdraw(amount: float) = this.Balance <- this.Balance - amount
let account1 = new Account(AccountNumber=8782108,
FirstName="Darren", LastName="Parker",
Balance=1543.33)
További információt a Konstruktorok (F#) című témakörben talál.
Ugyanez a módszer, amely a tulajdonsághalmazok meghívására szolgál, minden objektumvisszaadó metódusra (például a gyári metódusokra) is vonatkozik:
type Widget() =
member val Width = 1 with get,set
member val Height = 1 with get,set
type WidgetFactory =
static member MakeNewWidget() =
new Widget()
static member AdjustWidget(w: Widget) =
w
let w = WidgetFactory.MakeNewWidget(Width=10)
w.Width // = 10
w.Height // = 1
WidgetFactory.AdjustWidget(w, Height=10)
w.Height // = 10
Vegye figyelembe, hogy ezek a tagok tetszőleges munkát végezhetnek, a szintaxis gyakorlatilag egy rövid kéz a tulajdonsághalmazok meghívásához a végső érték visszaadása előtt.
Opcionális paraméterek
Egy metódus opcionális paraméterét a paraméter neve előtti kérdőjel használatával adhatja meg. A választható paramétereket az F# beállítástípusként értelmezi a rendszer, így a lekérdezésük szokásos módon történik a beállítástípusok lekérdezésében egy kifejezés és Some
None
egy match
. Az opcionális paraméterek csak tagokon engedélyezettek, kötések használatával let
létrehozott függvényeken nem.
A meglévő opcionális értékeket paraméternév alapján adhat át a metódusnak, például ?arg=None
vagy ?arg=arg
?arg=Some(3)
. Ez akkor lehet hasznos, ha olyan metódust hoz létre, amely az opcionális argumentumokat egy másik metódusnak adja át.
Használhat olyan függvényt defaultArg
is, amely egy opcionális argumentum alapértelmezett értékét állítja be. A defaultArg
függvény az opcionális paramétert első argumentumként, az alapértelmezett értéket pedig másodikként veszi fel.
Az alábbi példa az opcionális paraméterek használatát mutatja be.
type DuplexType =
| Full
| Half
type Connection(?rate0 : int, ?duplex0 : DuplexType, ?parity0 : bool) =
let duplex = defaultArg duplex0 Full
let parity = defaultArg parity0 false
let mutable rate = match rate0 with
| Some rate1 -> rate1
| None -> match duplex with
| Full -> 9600
| Half -> 4800
do printfn "Baud Rate: %d Duplex: %A Parity: %b" rate duplex parity
let conn1 = Connection(duplex0 = Full)
let conn2 = Connection(duplex0 = Half)
let conn3 = Connection(300, Half, true)
let conn4 = Connection(?duplex0 = None)
let conn5 = Connection(?duplex0 = Some(Full))
let optionalDuplexValue : option<DuplexType> = Some(Half)
let conn6 = Connection(?duplex0 = optionalDuplexValue)
A kimenet a következő.
Baud Rate: 9600 Duplex: Full Parity: false
Baud Rate: 4800 Duplex: Half Parity: false
Baud Rate: 300 Duplex: Half Parity: true
Baud Rate: 9600 Duplex: Full Parity: false
Baud Rate: 9600 Duplex: Full Parity: false
Baud Rate: 4800 Duplex: Half Parity: false
A C# és a Visual Basic interop esetében az F# attribútumait [<Optional; DefaultParameterValue<(...)>]
használhatja, így a hívók egy argumentumot nem kötelezőként fognak látni. Ez egyenértékű azzal, hogy az argumentumot nem kötelezőként definiálja a C# fájlban, mint a következőben MyMethod(int i = 3)
.
open System
open System.Runtime.InteropServices
type C =
static member Foo([<Optional; DefaultParameterValue("Hello world")>] message) =
printfn $"{message}"
Megadhat egy új objektumot is alapértelmezett paraméterértékként. Előfordulhat például, hogy a Foo
tag nem kötelező CancellationToken
bemenetként:
open System.Threading
open System.Runtime.InteropServices
type C =
static member Foo([<Optional; DefaultParameterValue(CancellationToken())>] ct: CancellationToken) =
printfn $"{ct}"
Az argumentumként megadott értéknek DefaultParameterValue
meg kell egyeznie a paraméter típusával. A következők például nem engedélyezettek:
type C =
static member Wrong([<Optional; DefaultParameterValue("string")>] i:int) = ()
Ebben az esetben a fordító figyelmeztetést hoz létre, és teljesen figyelmen kívül hagyja mindkét attribútumot. Vegye figyelembe, hogy az alapértelmezett értéket null
gépelt jegyzetekkel kell megadni, ellenkező esetben a fordító nem a megfelelő típust, azaz [<Optional; DefaultParameterValue(null:obj)>] o:obj
.
Továbbítás hivatkozás alapján
Az F#-érték hivatkozás alapján történő átadása byrefs-eket is magában foglal, amelyek felügyelt mutatótípusok. Útmutatás a használni kívánt típushoz:
- Akkor használja
inref<'T>
, ha csak a mutatót kell elolvasnia. - Akkor használja
outref<'T>
, ha csak az egérmutatóra kell írnia. - Akkor használja
byref<'T>
, ha egyszerre kell olvasnia és írnia az egérmutatóra.
let example1 (x: inref<int>) = printfn $"It's %d{x}"
let example2 (x: outref<int>) = x <- x + 1
let example3 (x: byref<int>) =
printfn $"It's %d{x}"
x <- x + 1
let test () =
// No need to make it mutable, since it's read-only
let x = 1
example1 &x
// Needs to be mutable, since we write to it
let mutable y = 2
example2 &y
example3 &y // Now 'y' is 3
Mivel a paraméter egy mutató, és az érték nem módosítható, az érték módosításai a függvény végrehajtása után is megmaradnak.
A rekordokat visszatérési értékként használhatja a out
paraméterek .NET-kódtár-metódusokban való tárolásához. Másik lehetőségként paraméterként is kezelheti a out
paramétert byref
. Az alábbi példakód mindkét módszert szemlélteti.
// TryParse has a second parameter that is an out parameter
// of type System.DateTime.
let (b, dt) = System.DateTime.TryParse("12-20-04 12:21:00")
printfn "%b %A" b dt
// The same call, using an address of operator.
let mutable dt2 = System.DateTime.Now
let b2 = System.DateTime.TryParse("12-20-04 12:21:00", &dt2)
printfn "%b %A" b2 dt2
Paramétertömbök
Időnként meg kell határozni egy függvényt, amely tetszőleges számú heterogén típusú paramétert vesz igénybe. Nem lenne célszerű létrehozni az összes lehetséges túlterhelt metódust, hogy figyelembe lehessen venni az összes használható típust. A .NET-implementációk a paramétertömb funkcióval támogatják az ilyen metódusokat. Az aláírásban egy paramétertömböt használó metódus tetszőleges számú paramétert adhat meg. A paraméterek egy tömbbe kerülnek. A tömbelemek típusa határozza meg a függvénynek továbbítható paramétertípusokat. Ha elemtípusként definiálja a paramétertömböt System.Object
, az ügyfélkód bármilyen típusú értéket átadhat.
Az F#-ban a paramétertömbök csak metódusokban definiálhatók. Nem használhatók önálló függvényekben vagy modulokban definiált függvényekben.
Paramétertömböt az ParamArray
attribútum használatával definiálhat. Az ParamArray
attribútum csak az utolsó paraméterre alkalmazható.
Az alábbi kód egy paramétertömböt használó .NET-metódus meghívását és egy paramétertömböt használó metódust tartalmazó F# típus definícióját mutatja be.
open System
type X() =
member this.F([<ParamArray>] args: Object[]) =
for arg in args do
printfn "%A" arg
[<EntryPoint>]
let main _ =
// call a .NET method that takes a parameter array, passing values of various types
Console.WriteLine("a {0} {1} {2} {3} {4}", 1, 10.0, "Hello world", 1u, true)
let xobj = new X()
// call an F# method that takes a parameter array, passing values of various types
xobj.F("a", 1, 10.0, "Hello world", 1u, true)
0
Projektben való futtatáskor az előző kód kimenete a következő:
a 1 10 Hello world 1 True
"a"
1
10.0
"Hello world"
1u
true
Lásd még
Visszajelzés
https://aka.ms/ContentUserFeedback.
Hamarosan elérhető: 2024-ben fokozatosan kivezetjük a GitHub-problémákat a tartalom visszajelzési mechanizmusaként, és lecseréljük egy új visszajelzési rendszerre. További információ:Visszajelzés küldése és megtekintése a következőhöz: