Exportar (0) Imprimir
Expandir todo
Este artículo proviene de un motor de traducción automática. Mueva el puntero sobre las frases del artículo para ver el texto original. Más información.
Traducción
Original
Este tema aún no ha recibido ninguna valoración - Valorar este tema

Funciones (F#)

Las funciones representan la unidad fundamental de la ejecución de un programa en cualquier lenguaje de programación. Al igual que en otros lenguajes, las funciones en F# tienen un nombre, pueden tener parámetros y recibir argumentos, y tienen un cuerpo. 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 formar nuevas funciones, funciones currificadas y la definición implícita de funciones mediante la aplicación parcial de argumentos de función.

Las funciones se definen mediante la palabra clave let o, si la función es recursiva, mediante la combinación de palabras clave let rec.

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

function-name es un identificador que representa la función. parameter-list se compone de parámetros sucesivos separados con un espacio. Se puede especificar un tipo explícito para cada parámetro, tal y como se describe en la sección Parámetros. Si no se especifica un tipo concreto para un argumento, el compilador intenta deducir el tipo a partir del cuerpo de la función. function-body se compone de una expresión. La expresión que compone 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. return-type es un signo de dos puntos seguido de un tipo y es opcional. Si no se especifica explícitamente el tipo del valor devuelto, el compilador lo determinará a partir de la expresión final.

Una definición de función simple se parecerá a la siguiente:

let f x = x + 1

En el ejemplo anterior, el nombre de función es f, el argumento es x, cuyo tipo es int, el cuerpo de la función es x + 1 y el tipo del valor devuelto es int.

El especificador inline indica al compilador que la función es pequeña y que su código se puede integrar en el cuerpo de la función que la llame.

En cualquier nivel de ámbito que no sea el ámbito de módulo, no es un error reutilizar un valor o nombre de función. Si se reutiliza un nombre, el último nombre declarado prevalece sobre el declarado anteriormente. Sin embargo, en el ámbito de nivel superior de un módulo, los nombres deben ser únicos. Por ejemplo, el código siguiente genera un error cuando aparece en el ámbito de módulo, pero no genera ningún error cuando aparece en una función:


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


Sin embargo, el código siguiente es aceptable en cualquier nivel de ámbito:


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


Los nombres de los parámetros aparecen después del nombre de la función. Se puede especificar un tipo para un parámetro, tal y como se muestra en el ejemplo siguiente:

let f (x : int) = x + 1

Si se especifica un tipo, debe figurar después del nombre del parámetro e ir separado del nombre mediante un signo de dos puntos. Si se omite el tipo del parámetro, el compilador lo inferirá. Por ejemplo, en la definición de función siguiente, se infiere que el tipo del argumento x es int porque 1 es de tipo int.

let f x = x + 1

Sin embargo, el compilador intentará que la función sea lo más genérica posible. Por ejemplo, tenga en cuenta el código siguiente:

let f x = (x, x)

La función crea una tupla a partir de un argumento de cualquier tipo. Dado que no se especifica el tipo, la función puede usarse con cualquier tipo de argumento. Para obtener más información, vea Generalización automática (F#).

El cuerpo de una función puede contener definiciones de variables y funciones locales. Estas variables y funciones existen en el ámbito del cuerpo de la función actual, pero no fuera del mismo. Cuando está habilitada la opción de sintaxis simplificada, se debe utilizar la sangría para indicar que una definición pertenece al cuerpo de una función, tal y como se muestra en el ejemplo siguiente:


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


Para obtener más información, vea Instrucciones de formato de código (F#) y Sintaxis detallada (F#).

El compilador utiliza la expresión final del cuerpo de una función para determinar el valor devuelto y el tipo de dicho valor. El compilador puede inferir el tipo de la expresión final a partir de expresiones anteriores. En la función cylinderVolume, que se muestra en la sección anterior, se determina que el tipo de pi es float a partir del tipo del literal 3.14159. El compilador usa el tipo de pi para determinar que el tipo de la expresión h * pi * r * r es float. Por consiguiente, el tipo global del valor devuelto por la función es float.

Para especificar explícitamente el valor devuelto, escriba el código de la siguiente manera:



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


De esta manera, el compilador aplica float a toda la función; si desea aplicarlo también a los tipos de parámetro, use el código siguiente:

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

Para llamar a una función, se especifica el nombre de la función seguido de un espacio y, a continuación, se especifican los argumentos separados por un espacio. Por ejemplo, para llamar a la función cylinderVolume y asignar el resultado al valor vol, escriba el código siguiente:

let vol = cylinderVolume 2.0 3.0

Si se proporciona un número de argumentos menor que el especificado, se crea una nueva función que espera los argumentos restantes. Este método de control de argumentos se denomina currificación y es una característica de los lenguajes de programación funcional como F#. Por ejemplo, supongamos que usa dos tamaños de canalización: uno tiene un radio de 2.0 y el otro tiene un radio de 3.0. Podrá crear funciones que determinen el volumen de canalización de la siguiente manera:


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


A continuación, proporcionará el argumento adicional según sea necesario para diversas longitudes de canalización de los dos tamaños:


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


Las funciones recursivas son funciones que se llaman a sí mismas. Requieren que se especifique la palabra clave rec después de la palabra clave let. La función recursiva debe invocarse desde el cuerpo de la función de la misma manera que se invoca cualquier llamada de función. La siguiente función recursiva calcula el enésimo número de Fibonacci. La secuencia de números de Fibonacci se conoce desde la antigüedad. Es una secuencia en la que cada número sucesivo es la suma de los dos números anteriores de la secuencia.


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


Algunas funciones recursivas podrían desbordar la pila de programas o ser ineficaces si no se escriben con cuidado y con conocimiento de determinadas técnicas especiales, como el uso de acumuladores y continuaciones.

En F#, todas las funciones se consideran valores; de hecho, se conocen como valores de función. Dado que las funciones son valores, se pueden utilizar como argumentos de otras funciones o en otros contextos donde se usen valores. A continuación figura un ejemplo de una función que recibe un valor de función como argumento:


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


El tipo de un valor de función se especifica mediante el token ->. A la izquierda de este token figura el tipo del argumento y a la derecha aparece el tipo del valor devuelto. En el ejemplo anterior, apply1 es una función que recibe una función transform como argumento, donde transform es una función que recibe un entero y devuelve otro entero. En el siguiente código se muestra cómo usar apply1:


let increment x = x + 1

let result1 = apply1 increment 100


El valor de result será 101 después de que se ejecute el código anterior.

Si la función recibe varios argumentos, estos van separados por sucesivos tokens ->, tal y como se muestra en el siguiente ejemplo:


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.

Una expresión lambda es una función sin nombre. En los ejemplos anteriores, en lugar de definir las funciones con nombre increment y mul, podría usar expresiones lambda de la siguiente manera:


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. Una expresión lambda es similar a una definición de función, con la diferencia de que se usa el token -> en lugar de = para separar la lista de argumentos del cuerpo de la función. Al igual que en una definición de función normal, los tipos de los argumentos se pueden inferir o especificar explícitamente, y el tipo del valor devuelto por la expresión lambda se deduce a partir del tipo de la última expresión del cuerpo. Para obtener más información, vea Expresiones lambda: la palabra clave fun (F#).

En F# se pueden crear funciones mediante la composición de otras funciones. La composición de las funciones function1 y function2 produce otra función que representa la aplicación de function1 seguida de la aplicación de function2:


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


El resultado es 202.

La canalización permite encadenar las llamadas de función como operaciones sucesivas. La canalización funciona de la siguiente manera:

let result = 100 |> function1 |> function2

Una vez más, el resultado es 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 devuelve un valor. El ejemplo de código siguiente se muestra la diferencia entre la canalización y operadores de composición mostrando las diferencias en las firmas y el uso de la función.

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


Puede sobrecargar métodos de un tipo pero no de funciones. Para obtener más información, vea Métodos (F#).

¿Te ha resultado útil?
(Caracteres restantes: 1500)
Gracias por sus comentarios

Adiciones de comunidad

AGREGAR
Mostrar:
© 2014 Microsoft. Reservados todos los derechos.