Funkcje (F#)

Funkcje są podstawowej jednostki wykonywania programu w dowolnym języku programowania.Tak jak w innych językach funkcja F# o nazwie, mogą mieć parametry i take argumenty i ma treść.Język F# obsługuje również funkcjonalności narzędzi programistycznych, takich jak leczeniu funkcji jako wartości, przy użyciu funkcji bez nazwy w wyrażeniach, skład funkcje tworząc nowe funkcje, funkcje curry i niejawna definicją funkcji w drodze częściowego stosowania argumenty funkcji.

Definiowanie funkcji przy użyciu let słowa kluczowego, lub, jeśli funkcja jest cykliczne, let rec kombinacji słowa kluczowego.

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

Uwagi

function-name Jest identyfikatorem, reprezentujący daną funkcję.parameter-list Składa się z kolejnych parametrów, które są rozdzielone spacjami.Można określić jawnie określony typ każdego parametru, zgodnie z opisem w sekcji Parametry.Jeśli nie określisz określonego argumentu typu, kompilator próbuje rozpoznać typ z treści funkcji.function-body Składa się z wyrażenia.Wyrażenie, które sprawia, że treści funkcji jest zwykle złożone wyrażenie złożone z kilku wyrażeń, których efektem ostatniego wyrażenia, która jest zwracana wartość.return-type Jest typu po dwukropku i jest opcjonalne.Jeśli nie zostanie jawnie określony typ zwracanej wartości, kompilator określa zwracany typ od ostatniego wyrażenia.

Definicja prosta funkcja podobny do następującego:

let f x = x + 1

W poprzednim przykładzie, nazwa funkcji jest f, argument jest x, która ma typ int, treść funkcji jest x + 1, wartość zwracana jest typu int.

Specyfikator wbudowany jest wskazówkę kompilator, że funkcja jest mały i kodu dla danej funkcji można zintegrować z treści obiektu wywołującego.

Zakres

Na każdym poziomie zakres inny niż zakres moduł nie jest to błąd, aby ponownie użyć nazwy wartości lub funkcji.Jeśli możesz ponownie użyć nazwy, nazwy zadeklarowanej później cienie nazwy zadeklarowanej wcześniej.Jednakże w zakresie najwyższego poziomu w module nazwy muszą być unikatowe.Na przykład poniższy kod generuje błąd, pojawiają się w module zakres, ale nie wtedy, gdy wydaje się wewnątrz funkcji:

let list1 = [ 1; 2; 3]
// Error: duplicate definition. 
let list1 = []  
let function1 =
   let list1 = [1; 2; 3]
   let list1 = []
   list1

Ale następujący kod jest do przyjęcia na dowolnym poziomie zakres:

let list1 = [ 1; 2; 3]
let sumPlus x =
// OK: inner list1 hides the outer list1. 
   let list1 = [1; 5; 10]  
   x + List.sum list1

Parametry

Nazwy parametrów są wymienione po nazwie funkcji.Typ parametru, można określić, jak pokazano w poniższym przykładzie:

let f (x : int) = x + 1

Jeśli określisz typu następuje nazwa parametru i jest oddzielone od nazwy jest dwukropek.Jeśli pominięto parametr typu dla parametru, typ parametru jest wnioskowana przez kompilator.Na przykład w poniższej definicji funkcji argument x się go doszukiwać się typ int ponieważ 1 jest typu int.

let f x = x + 1

Jednak kompilator zostanie próba utworzenia funkcji możliwie jak najbardziej uniwersalna.Na przykład należy zwrócić uwagę następujący kod:

let f x = (x, x)

Funkcja ta umożliwia tworzenie spójna z jeden argument dowolnego typu.Ponieważ typ nie jest określony, funkcja może służyć dowolny typ argumentu.Aby uzyskać więcej informacji, zobacz Automatyczna generalizacja (F#).

Funkcja organów

Treść funkcji może zawierać definicje zmiennych lokalnych i funkcje.Takie zmienne i funkcje są w zakresie, w treści funkcji bieżący, ale nie poza nim.Podczas masz włączoną opcję lekki składni, należy użyć wcięcia, aby wskazać, że definicja znajduje się w treści funkcji, jak pokazano w poniższym przykładzie:

let cylinderVolume radius length =
    // Define a local value pi. 
    let pi = 3.14159
    length * pi * radius * radius

Aby uzyskać więcej informacji, zobacz Wskazówki dotyczące formatowania kodu (F#) i Pełna składnia (F#).

Zwracają wartości

Kompilator używa ostatniego wyrażenia w treści funkcji do określenia wartości zwracanej i typu.Kompilator może rozpoznać typ ostatniego wyrażenia z poprzednimi wyrażeniami.W funkcji cylinderVolume, pokazane w poprzedniej sekcji, typ pi zależy od typu literał 3.14159 się float.Kompilator używa typu pi w celu określenia typu wyrażenia h * pi * r * r się float.W związku z tym, ogólnie rzecz biorąc zwracany typ funkcji jest float.

Aby jawnie określić wartość zwracana, wpisz następujący kod:

let cylinderVolume radius length : float =
   // Define a local value pi. 
   let pi = 3.14159
   length * pi * radius * radius

Jak kod jest napisane powyżej, kompilator stosuje się float całej funkcji; Jeśli masz na myśli ją zastosować również typy parametrów, należy użyć następującego kodu:

let cylinderVolume (radius : float) (length : float) : float

Wywołanie funkcji

Wywołanie funkcji przez określenie nazwy funkcji, ze spacją i następnie wszelkie argumenty, które są oddzielone spacjami.Na przykład, aby wywołać funkcję cylinderVolume i przypisać wynik z wartością vol, wpisz następujący kod:

let vol = cylinderVolume 2.0 3.0

Częściowe stosowanie argumentów

Jeśli podasz mniej niż określoną liczbę argumentów, utworzysz nową funkcję, która oczekuje, że pozostałe argumenty.Ta metoda obsługi argumentów jest określany jako zmiękczenia skóry surowej i jest to cecha funkcjonalna języków programowania, takich jak język F#.Na przykład użytkownik pracuje z dwóch rozmiarach potoku: jeden ma promień 2.0 i innych ma promień 3.0.Można utworzyć funkcje, które ustalania liczby potoku się następujące zmiany:

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

Następnie musi dostarczać dodatkowy argument, w razie potrzeby na pewien potoku dwóch różnych wielkości:

let length1 = 30.0
let length2 = 40.0
let smallPipeVol1 = smallPipeVolume length1
let smallPipeVol2 = smallPipeVolume length2
let bigPipeVol1 = bigPipeVolume length1
let bigPipeVol2 = bigPipeVolume length2

Rekurencyjnych

Rekurencyjnych są funkcje, które nazywają się.Wymagają one, aby określić rec następujące słowa kluczowego let słowa kluczowego.Wywoływać funkcji rekurencyjnej od w treści funkcji, tak jak wywołałoby każde wywołanie funkcji.Oblicza następujących funkcji rekurencyjnej nth Fibonacciego.Sekwencja Fibonacciego wiadomo, że już w starożytności a sekwencji, w którym każdy numer kolejnych jest sumą dwóch poprzednich liczbach w sekwencji.

let rec fib n = if n < 2 then 1 else fib (n - 1) + fib (n - 2)

Niektóre funkcje cykliczne może być związanej z przepełnieniem stosu program lub wykonać nieefektywnie, jeśli nie pisz je z rozwagą i uświadomienia specjalne techniki, takie jak użycie akumulatorów i kontynuacji.

Wartości funkcji

W F# wszystkie funkcje są traktowane jako wartości; w rzeczywistości są one znane jako wartości funkcji.Ponieważ funkcje są wartości, one może służyć jako argumenty innych funkcji lub w innych kontekstach gdzie wartości są używane.Oto przykład funkcji, która przyjmuje wartość funkcji jako argumentu:

let apply1 (transform : int -> int ) y = transform y

Określ typ wartości funkcji za pomocą -> token.Po lewej stronie token ten jest typ argumentu, a po prawej stronie jest zwracana wartość.W poprzednim przykładzie apply1 jest funkcją, która ma funkcję transform jako argument, gdzie transform jest funkcją, która przyjmuje całkowitą i zwraca innej liczby całkowitej.Poniższy kod ilustruje sposób używania apply1:

let increment x = x + 1

let result1 = apply1 increment 100

Wartość result będzie 101, po uruchomieniu poprzedniego kodu.

Wiele argumentów są oddzielone kolejnych -> tokeny, jak pokazano w poniższym przykładzie:

let apply2 ( f: int -> int -> int) x y = f x y

let mul x y = x * y

let result2 = apply2 mul 10 20

Wynik wynosi 200.

Wyrażenia lambda

A Wyrażenie lambda jest funkcją bez nazwy.W poprzednich przykładach, bez określenia o nazwie funkcji increment i mul, można użyć wyrażenia lambda się następujące zmiany:

let result3 = apply1 (fun x -> x + 1) 100

let result4 = apply2 (fun x y -> x * y ) 10 20

Definiowanie wyrażenia lambda przy użyciu fun słowa kluczowego.Wyrażenie lambda jest podobna do definicji funkcji, z wyjątkiem, że zamiast = token, -> token jest używany do oddzielania listy argumentów z treści funkcji.Tak jak w definicji funkcji regularnych typy argumentów można wywnioskować lub określone jawnie i zwracany typ wyrażenia lambda to pośrednio typ ostatniego wyrażenia w treści.Aby uzyskać więcej informacji, zobacz Wyrażenia lambda: fun — Słowo kluczowe (F#).

Funkcja składu i przetwarzanie potokowe

Funkcje w F# może składać się z innych funkcji.Skład dwie funkcje function1 i function2 jest innej funkcji, która reprezentuje aplikację z function1 a po nim stosowania function2:

let function1 x = x + 1
let function2 x = x * 2
let h = function1 >> function2
let result5 = h 100

Wynik jest 202.

Przetwarzanie potokowe umożliwia wywołania funkcji do połączonych ze sobą, jako kolejne czynności.Przetwarzanie potokowe działa następująco:

let result = 100 |> function1 |> function2

Wynik jest ponownie 202.

Operatory składu mają dwie funkcje i zwraca funkcję; z drugiej strony operatory rurociągu funkcję i argument i zwraca wartości.Poniższy przykład kodu pokazuje różnicę między podmiotami rurociągu i skład pokazując różnice w sygnatury funkcji i sposób użycia.

// 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
// ( <| ) : ('T -> 'U) -> 'T -> 'U
let Pipeline1 x = addOne <| timesTwo x

// Backward pipeline operator
// ( |> ) : 'T1 -> ('T1 -> 'U) -> 'U
let Pipeline2 x = addOne x |> timesTwo

// Result is 5
let result3 = Pipeline1 2

// Result is 6
let result4 = Pipeline2 2

Przeciążenie funkcji

Może doprowadzić do przeciążenia metody typu, ale nie funkcje.Aby uzyskać więcej informacji, zobacz Metody (F#).

Zobacz też

Inne zasoby

Wartości (F#)

Materiały referencyjne dotyczące języka F#