Parametry i argumenty (F#)
W tym temacie opisano obsługę języka Definiowanie parametrów i przekazywanie argumentów funkcji, metod i właściwości.Zawiera ona informacje dotyczące sposobu przekazywany za pomocą odwołania i sposób definiowania i metod, które można wykonać, zmienna liczba argumentów.
Parametry i argumenty
Określenie parametr jest używany do opisu nazw wartości, które mają być dostarczone.Określenie argument jest używany dla wartości podane dla każdego parametr.
Parametry można określić w krotce lub curried formularzlub w kombinacji dwóch.Argument jest przekazywany za pomocą nazwy jawny parametr .Parametry metod można określony jako opcjonalne i biorąc pod uwagę wartość domyślna.
Parametr desenie
Parametry podane funkcje i metody są ogólnie rzecz biorąc, desenie, oddzielonych spacjami.Oznacza to, że w regułydowolny desenie opisane w Wyrażenia dopasowania (F#) , można na liście parametr dla funkcja lub składnika.
Metody zwykle użyć krotki formularz przekazywanie argumentów.To osiąga lepszy wynik z perspektywy innych.NET języków, ponieważ krotka formularz pasuje argumenty są przekazywane w sposób.Metody netto.
Curried formularz jest najczęściej używana z funkcjami utworzone za pomocą let wiązania.
Następujący pseudokod pokazuje przykłady krotka i curried argumentów.
// Tuple form.
member this.SomeMethod(param1, param2) = ...
// Curried form.
let function1 param1 param2 = ...
Połączone formularze są możliwe, gdy niektóre argumenty są w krotek, a niektóre nie.
let function2 param1 (param2a, param2b) param3 = ...
Inne wzorce można również w listy parametr , ale jeśli wszystkie możliwe dane wejściowe nie dopasowanie do wzorca parametr , może występować dopasowanie niekompletne w czasie wykonywania.wyjątek MatchFailureException jest generowany, gdy wartość argument nie pasuje określonych na liście parametr wzorców. kompilator kwestie ostrzeżenie deseń parametr umożliwia meczów niekompletne.Co najmniej jeden wzorzec innych powszechnie przydaje się do listy parametr , i to deseń symboli wieloznacznych.Po prostu chcesz ignorować argumenty, które są dostarczane użyć deseniu z symboli wieloznacznych na liście parametr .Poniższy kod ilustruje wykorzystanie deseń symbolu wieloznacznego, na liście argument .
let makeList _ = [ for i in 1 .. 100 -> i * i ]
// The arguments 100 and 200 are ignored.
let list1 = makeList 100
let list2 = makeList 200
Wzorzec symbol wieloznaczny może być przydatne w każdym przypadku, gdy nie ma potrzeby przekazanych argumentów, takich jak w pkt głównego wpis do programu, jeśli nie jesteś zainteresowany argumentów wiersza polecenia, które są normalnie dostarczane jako tablicy ciągów, jak w poniższym kodzie.
[<EntryPoint>]
let main _ =
printfn "Entry point!"
0
Innych wzorców, które są czasami używane w argumentach są as wzoru i desenie identyfikator skojarzony dyskryminowanych związków i desenie active.Można użyć jednego przypadku dyskryminowanych deseń Unii w następujący sposób.
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
Wprowadza dane wyjściowe.
Data begins at 0 and ends at 4 in string Et tu, Brute?
Et tu
Active desenie mogą być przydatne jako parametry, na przykład, podczas przekształcania argument w wybranym formacie, jak w poniższym przykładzie:
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
Można użyć as wzorzec do przechowywania dopasowanej wartości jako wartość lokalnego, jak przedstawiono w następującym wiersz kodu.
let GetSubstring2 (Slice(p0, p1, text) as s) = s
Inny deseń, który jest czasami używany jest pozostawia ostatni argument nienazwanych, podając jako treść funkcja funkcja , wyrażenie lambda, które niezwłocznie przeprowadza dopasowanie do wzorca na niejawny argument.Przykładem tego jest następujący wiersz kodu.
let isNil = function [] -> true | _::_ -> false
Ten kod zawiera definicję funkcja , która przyjmuje listę rodzajowy i zwraca true , jeśli lista jest pusta, a false inaczej.Wykorzystanie takich technik może utrudnić kodu do odczytu.
Od czasu do czasu desenie, które obejmują niekompletne meczów są użyteczne, na przykład, jeśli wiadomo, że tylko trzy elementy listy w programie, może użyć deseniu podobnym następujące na liście parametr .
let sum [a; b; c;] = a + b + c
Używanie wzorców, które mają odpowiedniki niekompletne, najlepiej jest zarezerwowany do szybkiego tworzenia prototypów i innych zastosowań tymczasowych.kompilator wygeneruje ostrzeżenie dla takiego kodu.Takie desenie nie mogą obejmować wszystkie możliwe dane wejściowe w ogólnym przypadku i dlatego nie są odpowiednie dla składnik interfejsów API.
Nazwanych argumentów
Można określić argumenty dla metody według pozycji na liście oddzielone przecinkami argument lub one mogą być przekazywane do metoda jawnie przez podanie nazwy, a po nim znak równości i wartości, które mają być przekazywane w.Jeśli określono, podając jego nazwę, może się pojawić w innej kolejności niż w zgłoszeniu.
Nazwanych argumentów można wprowadzić kod bardziej czytelny i większej elastyczności niektórych rodzajów zmian w interfejsie API, takie jak zmiana kolejności parametrów metoda .
Nazwanych argumentów są dozwolone tylko dla metod, nie dla let-powiązane wartości funkcja , funkcji lub wyrażenia lambda.
Poniższy przykład kodu demonstruje użycie nazwanych argumentów.
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)
W wywołaniu konstruktorklasy można ustawić wartości właściwości klasy przy użyciu składni podobne do nazwanych argumentów.Składnię tę można znaleźć w poniższym przykładzie.
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)
Aby uzyskać więcej informacji, zobacz konstruktory (F#).
Parametry opcjonalne
Opcjonalny parametr do metoda można określić przy użyciu znaku zapytania na początku nazwy parametr .Parametry opcjonalne są interpretowane jako typ opcji F#, dzięki czemu możesz kwerenda je w zwykły sposób, że typy opcji będą pytani, za pomocą match wyrażenie z Some i None.Parametry opcjonalne są dozwolone tylko dla członków, nie na utworzone przy użyciu funkcji let wiązania.
Można również użyć funkcja defaultArg, który ustawia wartość domyślna opcjonalny argument.defaultArg funkcja przyjmuje opcjonalny parametr jako pierwszy argument i wartość domyślna jako drugi.
Poniższy przykład ilustruje użycie parametrów opcjonalnych.
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)
Wprowadza dane wyjściowe.
Baud Rate: 9600 Duplex: Full Parity: false
Baud Rate: 4800 Duplex: Half Parity: false
Baud Rate: 300 Duplex: Half Parity: true
Przekazywanie przez odwołanie
F# obsługuje byref słowa kluczowego, które określa, że parametr jest przekazywany przez odwołanie.Oznacza to, że wszelkie zmiany wartości są zachowywane po wykonaniu funkcja.Wartości przekazywane do byref parametr musi być mutable. Alternatywnie można przekazać odwołania komórek odpowiedniego typu.
Przekazywanie przez odwołanie w.Języki netto evolved jako sposób zwrócić więcej niż jedną wartość funkcja.F# zwraca krotki, w tym celu lub użyć komórki mutable odniesienia jako parametr.byref parametr znajduje się głównie ze względu na współdziałanie z.NET bibliotek.
Poniższe przykłady ilustrują użycie byref słowa kluczowego.Uwaga, że gdy komórka odwołania jest używany jako parametr, należy utworzyć komórki odwołanie jako nazwaną wartość i wykorzystania, która nie tylko dodać jako parametr ref operator , jak pokazano w pierwsze wywołanie Increment w poniższym kodzie. Ponieważ tworzenie komórki odwołanie tworzy kopię wartości podstawowej, pierwsze wywołanie po prostu zwiększa wartość tymczasowej.
type Incrementor(z) =
member this.Increment(i : int byref) =
i <- i + z
let incrementor = new Incrementor(1)
let mutable x = 10
// Not recommended: Does not actually increment the variable.
incrementor.Increment(ref x)
// Prints 10.
printfn "%d" x
let mutable y = 10
incrementor.Increment(&y)
// Prints 11.
printfn "%d" y
let refInt = ref 10
incrementor.Increment(refInt)
// Prints 11.
printfn "%d" !refInt
Można użyć krotki jako wartość zwracana z przechowywać dowolne out parametrów.Metody netto biblioteka .Alternatywnie, można traktować out parametr jako byref parametr. Poniższy przykład kodu ilustruje oba te sposoby.
// 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
Tablic parametrów
Czasami jest zdefiniowanie dowolnej liczby parametrów typu heterogenicznych zajmuje funkcja .Nie byłoby praktyczne, utworzyć wszystkich możliwych przeciążenia metody do konta dla wszystkich typów, które mogłyby zostać wykorzystane..NET platforma zapewnia obsługę takich metod, za pomocą tablicy parametr cecha.metoda , która przyjmuje tablica parametr w jego podpisu można dostarczone z dowolnej liczby parametrów.Parametry są wprowadzane do tablicy.Typ elementów tablicy Określa typy parametr , które mogą być przekazywane do funkcja.W przypadku zdefiniowania tablica parametr z Object jako typ elementu, następnie kod klienta można przekazać wartości dowolnego typu.
F# tablic parametr mogą być definiowane tylko w metodach.Nie można ich używać w funkcji autonomicznych lub funkcje, które są zdefiniowane w modułach.
Tablica parametr jest definiowany przy użyciu atrybutParamArray.ParamArray, który atrybut może być tylko stosowane do ostatniego parametr.
Poniższy kod ilustruje oba telefoniczną.NET metoda , która przyjmuje tablica parametr i definicji typu F#, że metoda , która zajmuje tablica parametr .
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
Po uruchomieniu programu projekt, dane wyjściowe poprzedniego kodu jest następująca:
a 1 10 Hello world 1 True
"a"
1
10.0
"Hello world"
1u
true