FuncionesFunctions

Las funciones son la unidad fundamental de la ejecución del programa en cualquier lenguaje de programación.Functions are the fundamental unit of program execution in any programming language. Al igual que en otros lenguajes, una función de F# tiene un nombre, puede tener parámetros y tomar argumentos, y tiene un cuerpo.As in other languages, an F# function has a name, can have parameters and take arguments, and has a body. F# también admite construcciones de programación funcional como el tratamiento de las funciones como valores, el uso de funciones sin nombre en expresiones, la composición de funciones para crear nuevas funciones, funciones currificadas y la definición implícita de funciones mediante la aplicación parcial de argumentos de función.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.

Las funciones se definen mediante la palabra clave let, o bien, si la función es recursiva, la combinación de palabras clave let rec.You define functions by using the let keyword, or, if the function is recursive, the let rec keyword combination.

SintaxisSyntax

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

ComentariosRemarks

El nombre de la función es un identificador que representa la función.The function-name is an identifier that represents the function. La lista de parámetros consta de parámetros sucesivos separados por espacios.The parameter-list consists of successive parameters that are separated by spaces. Se puede especificar un tipo explícito para cada parámetro, tal como se describe en la sección Parámetros.You can specify an explicit type for each parameter, as described in the Parameters section. Si no se especifica un tipo de argumento concreto, el compilador intenta deducir el tipo del cuerpo de la función.If you do not specify a specific argument type, the compiler attempts to infer the type from the function body. El cuerpo de la función consta de una expresión.The function-body consists of an expression. La expresión que forma el cuerpo de la función suele ser una expresión compuesta formada por varias expresiones que culminan en una expresión final que es el valor devuelto.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. El tipo de valor devuelto es un signo de dos puntos seguido de un tipo y es opcional.The return-type is a colon followed by a type and is optional. Si no se especifica explícitamente el tipo del valor devuelto, el compilador determina el tipo de valor devuelto a partir de la expresión final.If you do not specify the type of the return value explicitly, the compiler determines the return type from the final expression.

Una definición de función simple es similar a la siguiente:A simple function definition resembles the following:

let f x = x + 1

En el ejemplo anterior, el nombre de función es f, el argumento es x, que tiene el tipo int, el cuerpo de la función es x + 1 y el valor devuelto es de tipo 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.

Las funciones se pueden marcar como inline.Functions can be marked inline. Para más información sobre inline, vea Inline Functions (Funciones insertadas).For information about inline, see Inline Functions.

ÁmbitoScope

En cualquier nivel de ámbito distinto al ámbito de módulo, no es un error volver a usar un nombre de función o valor.At any level of scope other than module scope, it is not an error to reuse a value or function name. Si se vuelve a usar un nombre, el último nombre declarado prevalece sobre el declarado anteriormente.If you reuse a name, the name declared later shadows the name declared earlier. Pero en el ámbito de nivel superior en un módulo, los nombres deben ser únicos.However, at the top level scope in a module, names must be unique. Por ejemplo, el código siguiente produce un error cuando aparece en el ámbito de módulo, pero no cuando aparece dentro de una función: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

Pero el código siguiente es aceptable en cualquier nivel de ámbito: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

ParámetrosParameters

Los nombres de los parámetros aparecen después del nombre de función.Names of parameters are listed after the function name. Se puede especificar un tipo para un parámetro, como se muestra en el ejemplo siguiente:You can specify a type for a parameter, as shown in the following example:

let f (x : int) = x + 1

Si se especifica un tipo, sigue al nombre del parámetro y se separa del nombre mediante dos puntos.If you specify a type, it follows the name of the parameter and is separated from the name by a colon. Si se omite el tipo del parámetro, el compilador infiere el tipo de parámetro.If you omit the type for the parameter, the parameter type is inferred by the compiler. Por ejemplo, en la siguiente definición de función, se deduce que el argumento x es del tipo int porque 1 es de tipo int.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

Pero el compilador intentará que la función sea lo más genérica posible.However, the compiler will attempt to make the function as generic as possible. Por ejemplo, observe el código siguiente:For example, note the following code:

let f x = (x, x)

La función crea una tupla a partir de un argumento de cualquier tipo.The function creates a tuple from one argument of any type. Dado que no se especifica el tipo, la función se puede usar con cualquier tipo de argumento.Because the type is not specified, the function can be used with any argument type. Para más información, vea Automatic Generalization (Generalización automática).For more information, see Automatic Generalization.

Cuerpos de funciónFunction Bodies

El cuerpo de una función puede contener definiciones de variables locales y funciones.A function body can contain definitions of local variables and functions. Estas variables y funciones están en ámbito en el cuerpo de la función actual, pero no fuera de ella.Such variables and functions are in scope in the body of the current function but not outside it. Una vez habilitada la opción de sintaxis ligera, se debe usar sangría para indicar que es una definición de un cuerpo de función, como se muestra en el ejemplo siguiente: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

Para más información, vea Code Formatting Guidelines (Instrucciones de formato de código) y Verbose Syntax (Sintaxis detallada).For more information, see Code Formatting Guidelines and Verbose Syntax.

Valores devueltosReturn Values

El compilador usa la expresión final en el cuerpo de una función para determinar el tipo y el valor devuelto.The compiler uses the final expression in a function body to determine the return value and type. Es posible que el compilador deduzca el tipo de la expresión final a partir las expresiones anteriores.The compiler might infer the type of the final expression from previous expressions. En la función cylinderVolume, como se muestra en la sección anterior, el tipo de pi se determina a partir del tipo del literal 3.14159 como float.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. El compilador usa el tipo de pi para determinar el tipo de la expresión h * pi * r * r como float.The compiler uses the type of pi to determine the type of the expression h * pi * r * r to be float. Por tanto, el tipo de valor devuelto global de la función es float.Therefore, the overall return type of the function is float.

Para especificar explícitamente el valor devuelto, escriba el código de esta forma: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

Tal como se escribe el código anterior, el compilador aplica float a toda la función. Si también quiere aplicarlo a los tipos de parámetro, use el código siguiente: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

Llamar a una funciónCalling a Function

Las funciones se llaman especificando el nombre de la función seguido de un espacio y, después, los argumentos separados por espacios.You call functions by specifying the function name followed by a space and then any arguments separated by spaces. Por ejemplo, para llamar a la función cylinderVolume y asignar el resultado al valor vol, se escribe el código siguiente: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

Aplicación parcial de argumentosPartial Application of Arguments

Si se proporcionan menos argumentos que los especificados, se crea una nueva función que espera los argumentos restantes.If you supply fewer than the specified number of arguments, you create a new function that expects the remaining arguments. Este método de control de argumentos se conoce como currificación y es una característica de los lenguajes de programación funcionales como F#.This method of handling arguments is referred to as currying and is a characteristic of functional programming languages like F#. Por ejemplo, supongamos que está trabajando con dos tamaños de canalización: una tiene un radio de 2,0 y la otra tiene un radio de 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. Se podrían crear funciones que determinen el volumen de canalización de esta forma: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

Después, se proporcionaría el argumento adicional según sea necesario para las distintas longitudes de canalización de los dos tamaños diferentes: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

Funciones recursivasRecursive Functions

Las funciones recursivas son funciones que se llaman a sí mismas.Recursive functions are functions that call themselves. Requieren que se especifique la palabra clave rec después de la palabra clave let.They require that you specify the rec keyword following the let keyword. La función recursiva se invoca desde el interior del cuerpo de la función de la misma forma que se invocaría cualquier llamada de función.Invoke the recursive function from within the body of the function just as you would invoke any function call. La siguiente función recursiva calcula el número deFibonacci n.The following recursive function computes the nth Fibonacci number. La secuencia de números de Fibonacci se conoce desde la antigüedad y es una secuencia en la que cada número sucesivo es la suma de los dos números anteriores en la secuencia.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)

Es posible que algunas funciones recursivas desborden la pila del programa o tengan un rendimiento ineficaz si no se escriben con cuidado y con el conocimiento de determinadas técnicas especiales, como el uso de acumuladores y continuaciones.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.

Valores de funciónFunction Values

En F#, todas las funciones se consideran valores, de hecho, se conocen como valores de función.In F#, all functions are considered values; in fact, they are known as function values. Dado que las funciones son valores, se pueden usar como argumentos de otras funciones o en otros contextos donde se usan los valores.Because functions are values, they can be used as arguments to other functions or in other contexts where values are used. El siguiente ejemplo muestra una función que toma un valor de función como argumento:Following is an example of a function that takes a function value as an argument:

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

El tipo de un valor de función se especifica mediante el token ->.You specify the type of a function value by using the -> token. En el lado izquierdo de este token está el tipo del argumento y, en el lado derecho, el valor devuelto.On the left side of this token is the type of the argument, and on the right side is the return value. En el ejemplo anterior, apply1 es una función que toma una función transform como argumento, donde transform es una función que toma un entero y devuelve otro entero.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. En el código siguiente se muestra cómo usar apply1:The following code shows how to use apply1:

let increment x = x + 1

let result1 = apply1 increment 100

El valor de result será 101 después de ejecutar el código anterior.The value of result will be 101 after the previous code runs.

Si hay varios argumentos, se separan por sucesivos tokens ->, como se muestra en el ejemplo siguiente: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

El resultado es 200.The result is 200.

Expresiones lambdaLambda Expressions

Una expresión lambda es una función sin nombre.A lambda expression is an unnamed function. En los ejemplos anteriores, en lugar de definir las funciones con nombre increment y mul, se podrían usar expresiones lambda de esta forma: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

Las expresiones lambda se definen mediante la palabra clave fun.You define lambda expressions by using the fun keyword. Una expresión lambda es similar a una definición de función, salvo que en lugar del token = se usa el token -> para separar la lista de argumentos del cuerpo de la función.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. Al igual que en una definición de función normal, se pueden deducir o especificar explícitamente los tipos de argumento, y el tipo de valor devuelto de la expresión lambda se deduce del tipo de la última expresión en el cuerpo.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. Para más información, vea Lambda Expressions: The fun Keyword (Expresiones lambda: la palabra clave fun).For more information, see Lambda Expressions: The fun Keyword.

Composición de funciones y canalizaciónFunction Composition and Pipelining

En F#, las funciones se pueden componer a partir de otras funciones.Functions in F# can be composed from other functions. La composición de dos funciones función1 y función2 es otra función que representa la aplicación de función1 seguida de la aplicación de función2: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

El resultado es 202.The result is 202.

La canalización permite encadenar llamadas a funciones como operaciones sucesivas.Pipelining enables function calls to be chained together as successive operations. La canalización funciona de la siguiente manera:Pipelining works as follows:

let result = 100 |> function1 |> function2

El resultado es 202 de nuevo.The result is again 202.

Los operadores de composición toman dos funciones y devuelven una función. Por el contrario, los operadores de canalización toman una función y un argumento, y devuelven un valor.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. En el ejemplo de código siguiente se muestra la diferencia entre los operadores de canalización y composición mostrando las diferencias en las firmas de función y el uso.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 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

Sobrecargar funcionesOverloading Functions

Los métodos de un tipo se pueden sobrecargar, pero no las funciones.You can overload methods of a type but not functions. Para más información, vea Métodos.For more information, see Methods.

Vea tambiénSee also