FunktionenFunctions

Funktionen sind die grundlegende Einheit für die Ausführung des Programms in einer beliebigen Programmiersprache.Functions are the fundamental unit of program execution in any programming language. So wie in anderen Sprachen auch, verfügt eine F#-Funktion über einen Namen, kann Parameter besitzen und Argumente verwenden und verfügt über Text.As in other languages, an F# function has a name, can have parameters and take arguments, and has a body. F# unterstützt auch funktionale Konstrukte der Programmierung, z.B. das Behandeln von Funktionen als Werte, Verwenden von unbenannten Funktionen als Ausdrücke, die Zusammensetzung von Funktionen zum Bilden neuer Funktionen, Funktionen mit Currying sowie die implizite Definition von Funktionen mit der teilweise Anwendung von Funktionsargumenten.F# also supports functional programming constructs such as treating functions as values, using unnamed functions in expressions, composition of functions to form new functions, curried functions, and the implicit definition of functions by way of the partial application of function arguments.

Sie definieren Funktionen durch Verwendung des Schlüsselworts let oder – sofern die Funktion rekursiv ist – die Schlüsselwortkombination let rec.You define functions by using the let keyword, or, if the function is recursive, the let rec keyword combination.

SyntaxSyntax

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

HinweiseRemarks

Der function-name ist ein Bezeichner, der die Funktion darstellt.The function-name is an identifier that represents the function. Der Bezeichner parameter-list besteht aus aufeinanderfolgenden Parametern, die durch Leerzeichen getrennt sind.The parameter-list consists of successive parameters that are separated by spaces. Sie können einen expliziten Typ für jeden Parameter angeben, wie im Abschnitt „Parameter“ beschrieben.You can specify an explicit type for each parameter, as described in the Parameters section. Wenn Sie keinen bestimmten Argumenttyp angeben, versucht der Compiler den Typ aus dem Funktionsrumpf abzuleiten.If you do not specify a specific argument type, the compiler attempts to infer the type from the function body. function-body besteht aus einem Ausdruck.The function-body consists of an expression. Der Ausdruck, der den Funktionsrumpf bildet, ist in der Regel ein zusammengesetzter Ausdruck, bestehend aus einer Reihe von Ausdrücken, die in einem abschließenden Ausdruck enden, was der Rückgabewert ist.The expression that makes up the function body is typically a compound expression consisting of a number of expressions that culminate in a final expression that is the return value. Der return-type ist ein Doppelpunkt, dem ein Typ folgt und der optional ist.The return-type is a colon followed by a type and is optional. Wenn Sie den Typ des Rückgabewerts nicht explizit angeben, bestimmt der Compiler den Rückgabetyp anhand des abschließenden Ausdrucks.If you do not specify the type of the return value explicitly, the compiler determines the return type from the final expression.

Eine einfache Funktionsdefinition lautet ungefähr folgendermaßen:A simple function definition resembles the following:

let f x = x + 1

Im vorherigen Beispiel ist der Funktionsname ist f, das Argument x, das den Typ int verweist, der Funktionsrumpf ist x + 1, und der Rückgabewert ist vom Typ int.In the previous example, the function name is f, the argument is x, which has type int, the function body is x + 1, and the return value is of type int.

Funktionen können als inline markiert werden.Functions can be marked inline. Informationen zu inline finden Sie unter Inlinefunktionen.For information about inline, see Inline Functions.

BereichScope

Auf jeder Ebene des Bereichs, der nicht der Modulbereich ist, ist es kein Fehler, einen Wert oder einen Namen einer Funktion Namen erneut zu verwenden.At any level of scope other than module scope, it is not an error to reuse a value or function name. Wenn Sie einen Namen wiederverwenden, führt der später deklarierte Name zum Shadowing des früher deklarierten Namens.If you reuse a name, the name declared later shadows the name declared earlier. Im Bereich der obersten Ebene in einem Modul, müssen Namen jedoch eindeutig sein.However, at the top level scope in a module, names must be unique. Der folgende Code generiert z.B. einen Fehler, wenn er im Modulbereich erscheint, jedoch nicht, wenn er innerhalb einer Funktion angezeigt wird:For example, the following code produces an error when it appears at module scope, but not when it appears inside a function:

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

Der folgende Code ist jedoch auf jeder Ebene des Bereichs akzeptabel:But the following code is acceptable at any level of scope:

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

ParameterParameters

Namen von Parametern werden nach dem Funktionsnamen aufgeführt.Names of parameters are listed after the function name. Sie können einen Typ für einen Parameter angeben, wie im folgenden Beispiel gezeigt:You can specify a type for a parameter, as shown in the following example:

let f (x : int) = x + 1

Wenn Sie einen Typ angeben, folgt er auf den Namen des Parameters und wird durch einen Doppelpunkt von diesem getrennt.If you specify a type, it follows the name of the parameter and is separated from the name by a colon. Wenn Sie den Typ für den Parameter weglassen, wird der Parametertyp vom Compiler abgeleitet.If you omit the type for the parameter, the parameter type is inferred by the compiler. In der folgenden Funktion wird z.B. das Argument x vom Typ int abgeleitet, da 1 vom Typ int ist.For example, in the following function definition, the argument x is inferred to be of type int because 1 is of type int.

let f x = x + 1

Allerdings versucht der Compiler die Funktion so allgemein wie möglich zu machen.However, the compiler will attempt to make the function as generic as possible. Beachten Sie beispielsweise folgenden Code:For example, note the following code:

let f x = (x, x)

Die Funktion erstellt ein Tupel aus einem Argument eines beliebigen Typs.The function creates a tuple from one argument of any type. Da der Typ nicht angegeben ist, kann die Funktion mit jedem Argumenttyp verwendet werden.Because the type is not specified, the function can be used with any argument type. Weitere Informationen finden Sie unter Automatische Verallgemeinerung.For more information, see Automatic Generalization.

FunktionsrümpfeFunction Bodies

Ein Funktionsrumpf kann Definitionen von lokalen Variablen und Funktionen enthalten.A function body can contain definitions of local variables and functions. Diese Variablen und Funktionen sind im Bereich des Texts der aktuellen Funktion enthalten, jedoch nicht außerhalb.Such variables and functions are in scope in the body of the current function but not outside it. Wenn Sie die einfache Syntaxoption aktiviert haben, müssen Sie einen Einzug verwenden, um anzugeben, dass sich eine Definition in einem Funktionsrumpf befindet, so wie im folgenden Beispiel gezeigt.When you have the lightweight syntax option enabled, you must use indentation to indicate that a definition is in a function body, as shown in the following example:

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

Weitere Informationen finden Sie unter Richtlinien für das Formatieren von Code und Ausführliche Syntax.For more information, see Code Formatting Guidelines and Verbose Syntax.

RückgabewerteReturn Values

Der Compiler verwendet den letzten Ausdruck in einem Funktionsrumpf, um den Rückgabewert und den Typ zu bestimmen.The compiler uses the final expression in a function body to determine the return value and type. Der Compiler kann den Typ des abschließenden Ausdrucks möglicherweise von vorherigen Ausdrücken ableiten.The compiler might infer the type of the final expression from previous expressions. In der Funktion cylinderVolume, die im vorherigen Abschnitt gezeigt wird, wird bestimmt, dass der Typ pi vom Typ des Literals 3.14159 float ist.In the function cylinderVolume, shown in the previous section, the type of pi is determined from the type of the literal 3.14159 to be float. Der Compiler verwendet den Typ pi, um zu bestimmen, dass der Typ des Ausdrucks h * pi * r * r float ist.The compiler uses the type of pi to determine the type of the expression h * pi * r * r to be float. Daher ist der allgemeine Rückgabetyp der Funktion float.Therefore, the overall return type of the function is float.

Um den Rückgabewert explizit anzugeben, schreiben Sie den Code wie folgt:To specify the return value explicitly, write the code as follows:

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

Wie der oben geschriebene Code, wendet der Compiler float auf gesamten Funktion an; wenn Sie sie auch auf Parametertypen anwenden möchten, verwenden Sie folgenden Code:As the code is written above, the compiler applies float to the entire function; if you mean to apply it to the parameter types as well, use the following code:

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

Aufrufen einer FunktionCalling a Function

Sie können Funktionen aufrufen, indem den Funktionsnamen, gefolgt von einem Leerzeichen angeben, und dann beliebige Argumente, die durch Leerzeichen getrennt sind.You call functions by specifying the function name followed by a space and then any arguments separated by spaces. Um z.B. die Funktion cylinderVolume abzurufen und das Ergebnis dem Wert vol zuzuweisen, schreiben Sie folgenden Code:For example, to call the function cylinderVolume and assign the result to the value vol, you write the following code:

let vol = cylinderVolume 2.0 3.0

Teilweise Anwendung von ArgumentenPartial Application of Arguments

Wenn Sie weniger als die angegebene Anzahl von Argumenten angeben, erstellen Sie eine neue Funktion, die die übrigen Argumente erwartet.If you supply fewer than the specified number of arguments, you create a new function that expects the remaining arguments. Diese Methode zum Behandeln von Argumenten wird als Currying bezeichnet und ist ein Merkmal funktionaler Programmiersprachen wie F#.This method of handling arguments is referred to as currying and is a characteristic of functional programming languages like F#. Nehmen wir beispielsweise an, dass Sie mit zwei Pipegrößen arbeiten: eine besitzt den Radius von 2,0 und die andere einen Radius von 3,0.For example, suppose you are working with two sizes of pipe: one has a radius of 2.0 and the other has a radius of 3.0. Sie können Funktionen erstellen, die die Menge der Pipe wie folgt bestimmen:You could create functions that determine the volume of pipe as follows:

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

Sie geben dann das zusätzliche Argument an, das für unterschiedliche Längen der Pipe mit den zwei verschiedenen Größen benötigt wird:You would then supply the additional argument as needed for various lengths of pipe of the two different sizes:

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

Rekursive FunktionenRecursive Functions

Rekursive Funktionen sind Funktionen, die sich selbst aufrufen.Recursive functions are functions that call themselves. Sie erfordern die Angabe des Schlüsselworts rec, das dem Schlüsselwort let folgt.They require that you specify the rec keyword following the let keyword. Rufen Sie die rekursive Funktion im Rumpf der Funktion so auf, wie Sie auch jede andere Funktion aufrufen würden.Invoke the recursive function from within the body of the function just as you would invoke any function call. Die folgende rekursive Funktion berechnet den n te Fibonacci-Zahl.The following recursive function computes the nth Fibonacci number. Die die Fibonacci-Zahlenfolge ist seit dem Altertum bekannt und ist eine Sequenz, in der die einzelnen aufeinander folgenden Zahlen die Summe der vorherigen zwei Zahlen in der Sequenz sind.The Fibonacci number sequence has been known since antiquity and is a sequence in which each successive number is the sum of the previous two numbers in the sequence.

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

Einige rekursive Funktionen können auf einem Programmstapel möglicherweise zum Überlauf führen oder ineffizient ausgeführt werden, wenn Sie sie nicht sorgfältig und unter Beachtung besonderer Methoden schreiben, z.B. mit der Verwendung von Akkumulatoren und Fortsetzungen.Some recursive functions might overflow the program stack or perform inefficiently if you do not write them with care and with awareness of special techniques, such as the use of accumulators and continuations.

FunktionswerteFunction Values

In F# werden alle Funktionen als Werte betrachtet. Sie sind in der Tat als Funktionswerte bekannt.In F#, all functions are considered values; in fact, they are known as function values. Da Funktionen Werte sind, können sie als Argumente für andere Funktionen oder in anderen Kontexten verwendet werden, in denen Werte verwendet werden.Because functions are values, they can be used as arguments to other functions or in other contexts where values are used. Es folgt ein Beispiel für eine Funktion, die den Wert einer Funktion als Argument akzeptiert:Following is an example of a function that takes a function value as an argument:

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

Sie geben den Typ eines Funktionswerts mithilfe des ->-Token an.You specify the type of a function value by using the -> token. Auf der linken Seite dieses Tokens befindet sich der Typ des Arguments, und auf der rechten Seite befindet sich der Rückgabewert.On the left side of this token is the type of the argument, and on the right side is the return value. Im vorherigen Beispiel ist apply1 eine Funktion, die eine transform-Funktion als Argument verwendet, wobei transform eine Funktion ist, die einen Integer nimmt und einen anderen dafür zurückgibt.In the previous example, apply1 is a function that takes a function transform as an argument, where transform is a function that takes an integer and returns another integer. Im folgenden Code wird die Verwendung von apply1 veranschaulicht:The following code shows how to use apply1:

let increment x = x + 1

let result1 = apply1 increment 100

Der Wert von result wird nach der Ausführung des vorangehenden Codes 101 sein.The value of result will be 101 after the previous code runs.

Mehrere Argumente werden durch aufeinander folgende ->-Token getrennt, wie im folgenden Beispiel gezeigt:Multiple arguments are separated by successive -> tokens, as shown in the following example:

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

let mul x y = x * y

let result2 = apply2 mul 10 20

Das Ergebnis ist 200.The result is 200.

Lambda-AusdrückeLambda Expressions

Ein Lambdaausdruck ist eine unbenannte Funktion.A lambda expression is an unnamed function. Im vorherigen Beispiel könnten Sie Lambdaausdrücke verwenden, anstatt benannte Funktionen als increment und mul zu definieren.In the previous examples, instead of defining named functions increment and mul, you could use lambda expressions as follows:

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

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

Sie definieren Lambdaausdrücke mithilfe des fun-Schlüsselworts.You define lambda expressions by using the fun keyword. Ein Lambdaausdruck ähnelt einer Funktionsdefinition, außer dass statt eines =-Tokens das ->-Token zum Trennen der Argumentliste vom Funktionsrumpf verwendet wird.A lambda expression resembles a function definition, except that instead of the = token, the -> token is used to separate the argument list from the function body. So wie in einer regulären Funktionsdefinition, können Argumenttypen explizit abgeleitet oder angegeben werden. Der Rückgabetyp des Lambdaausdrucks wird vom Typ des letzten Ausdrucks im Text abgeleitet.As in a regular function definition, the argument types can be inferred or specified explicitly, and the return type of the lambda expression is inferred from the type of the last expression in the body. Weitere Informationen finden Sie unter Lambda-Ausdrücke: Das fun-Schlüsselwort (F#).For more information, see Lambda Expressions: The fun Keyword.

Funktionskomposition und PipeliningFunction Composition and Pipelining

Funktionen in F# können aus anderen Funktionen zusammengestellt werden.Functions in F# can be composed from other functions. Die Zusammensetzung der beiden Funktionen function1 und function2 ist eine weitere Funktion, die die Anwendung von function1 gefolgt von der Anwendung von function2 darstellt:The composition of two functions function1 and function2 is another function that represents the application of function1 followed the application of function2:

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

Das Ergebnis ist 202.The result is 202.

Pipelining ermöglicht, dass Funktionsaufrufe miteinander als aufeinanderfolgende Operationen verkettet werden.Pipelining enables function calls to be chained together as successive operations. Pipelining funktioniert wie Folgt:Pipelining works as follows:

let result = 100 |> function1 |> function2

Das Ergebnis ist wieder 202.The result is again 202.

Die Kompositionsoperatoren nehmen zwei Funktionen und geben eine Funktion zurück. Dagegen nehmen Pipeline-Operatoren eine Funktion und ein Argument und geben einen Wert zurück.The composition operators take two functions and return a function; by contrast, the pipeline operators take a function and an argument and return a value. Das folgende Codebeispiel zeigt den Unterschied zwischen den Pipeline- und Kompositionsoperatoren durch Darstellung der Unterschiede in den Funktionssignaturen und in der Nutzung.The following code example shows the difference between the pipeline and composition operators by showing the differences in the function signatures and usage.

// 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 Pipeline1 x = addOne <| timesTwo x

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

// Result is 5
let result3 = Pipeline1 2

// Result is 6
let result4 = Pipeline2 2

Überladen von FunktionenOverloading Functions

Sie können die Methoden eines Typs überladen, jedoch keine Funktionen.You can overload methods of a type but not functions. Weitere Informationen finden Sie unter Methoden.For more information, see Methods.

Siehe auchSee Also

WerteValues

F#-SprachreferenzF# Language Reference