Funções (F#)

Funções são a unidade fundamental da execução do programa em qualquer linguagem de programação. Como em outros idiomas, uma função F# tem um nome pode ter parâmetros e levar argumentos e tem um corpo. F# também suporta construções de programação funcionais como, por exemplo, tratando de funções como valores, usando funções sem nome em expressões, composição de funções para formar novas funções, funções curried e a definição implícita de funções por meio do aplicativo parcial dos argumentos da função.

Você definir funções usando a let palavra-chave, ou, se a função é recursiva, o let rec combinação de palavra-chave.

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

Comentários

O function-name é um identificador que representa a função. O parameter-list consiste em sucessivos parâmetros que são separados por espaços. Você pode especificar um tipo explícito para cada parâmetro, conforme descrito na seção parâmetros. Se você não especificar um tipo específico de argumento, o compilador tenta inferir o tipo do corpo da função. O function-body consiste em uma expressão. A expressão que constitui o corpo da função é normalmente uma expressão composta consiste em um número de expressões que culminar em uma expressão final que é o valor de retorno. O return-type é um dois-pontos seguido de um tipo e é opcional. Se você não especificar explicitamente o tipo de valor de retorno, o compilador determina o tipo de retorno da expressão final.

Uma definição de função simples é semelhante ao seguinte:

let f x = x + 1

No exemplo anterior, o nome de função é f, o argumento é x, que tem o tipo de int, o corpo da função é x + 1, e o valor de retorno é do tipo int.

O especificador in-line é uma dica ao compilador que a função é pequena e que o código da função pode ser integrado no corpo do chamador.

Escopo

Em qualquer nível de escopo diferente de escopo do módulo, não é um erro para reutilizar um nome de função ou valor. Se você reutilizar um nome, o nome declarado posteriormente sombra o nome declarado anteriormente. No entanto, no escopo do nível superior em um módulo, nomes devem ser exclusivos. Por exemplo, o código a seguir produz um erro, quando ela aparecer no escopo do módulo, mas não quando ele aparece dentro de uma função:

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

Mas o código a seguir é aceitável em qualquer nível de escopo:

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âmetros

Nomes de parâmetros são listados após o nome da função. Você pode especificar um tipo de um parâmetro, conforme mostrado no exemplo a seguir:

let f (x : int) = x + 1

Se você especificar um tipo, ele segue o nome do parâmetro e separado do nome por dois pontos. Se você omitir o tipo de parâmetro, o tipo de parâmetro é inferido pelo compilador. Por exemplo, na seguinte definição de função, o argumento x é inferido para ser do tipo int como 1 é do tipo int.

let f x = x + 1

No entanto, o compilador tentará fazer com que a função genérica possível. Por exemplo, observe o seguinte código:

let f x = (x, x)

A função cria uma tupla de um argumento de qualquer tipo. Porque o tipo não for especificado, a função pode ser usada com qualquer tipo de argumento. Para obter mais informações, consulte Generalização automática (F#).

Corpos de função

O corpo de uma função pode conter definições de funções e variáveis locais. Tais variáveis e funções estão no escopo no corpo da função atual, mas não fora dela. Quando você tem a opção de sintaxe leve habilitada, você deve usar o recuo para indicar que uma definição no corpo de um função, como mostrado no exemplo a seguir:

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

Para obter mais informações, consulte Diretrizes de formatação (F#) de código. e Sintaxe muito detalhada (F#).

Valores de retorno

O compilador usa a expressão final no corpo de um função para determinar o valor de retorno e o tipo. O compilador pode inferir o tipo da expressão final das expressões anteriores. Na função cylinderVolume, mostrado na seção anterior, o tipo de pi é determinado o tipo do literal 3.14159 ser float. O compilador usa o tipo de pi para determinar o tipo da expressão h * pi * r * r ser float. Portanto, o tipo de retorno geral da função é float.

Para especificar explicitamente o valor de retorno, escreva o código da seguinte maneira:


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

Como o código é escrito acima, o compilador aplica float para a função inteira; Se você quer dizer para aplicá-lo aos tipos de parâmetro, use o seguinte código:

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

Chamando uma função

Você pode chamar funções, especificando o nome da função seguido por um espaço e, em seguida, quaisquer argumentos separados por espaços. Por exemplo, para chamar a função cylinderVolume e atribui o resultado para o valor vol, você escreve o código a seguir:

let vol = cylinderVolume 2.0 3.0

Aplicação parcial da argumentos

Se você fornecer a menos que o número especificado de argumentos, você pode criar uma nova função que espera os argumentos restantes. Esse método de manipulação de argumentos é conhecido como currying e é uma característica de linguagens de programação funcionais como F#. Por exemplo, suponha que você está trabalhando com dois tamanhos do pipe: um tem um raio de 2.0 e outro tiver um raio de 3.0. Você pode criar funções que determinam o volume do pipe da seguinte maneira:

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

Você forneceria o argumento adicional conforme necessário para vários comprimentos de pipe dos dois tamanhos diferentes:

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

Recursivas: funções

Recursivas: funções são funções que se chamam. Eles exigem que você especifique o rec seguinte da palavra-chave a let palavra-chave. Chame a função recursiva de dentro do corpo da função exatamente como você poderia chamar qualquer chamada de função. A função recursiva a seguir calcula o nnúmero de Fibonacci th. A seqüência de número de Fibonacci conhecida desde a época e é uma seqüência em que cada número sucessivo é a soma dos dois números anteriores na seqüência.

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

Algumas funções de recursiva podem estourar a pilha do programa ou executar de forma ineficiente se não escreve com cuidado e com o reconhecimento de técnicas especiais, como, por exemplo, o uso de acumuladores e continuação.

Valores de função

No F#, todas as funções são consideradas valores; Na verdade, eles são conhecidos como os valores de função. Como as funções são valores, eles podem ser usados como argumentos para outras funções ou em outros contextos onde os valores são usados. Veja a seguir um exemplo de uma função que assume um valor de função como um argumento:

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

Você especifica o tipo de valor de um função usando o -> token. No lado esquerdo desse token é o tipo do argumento e no lado direito é o valor de retorno. No exemplo anterior, apply1 é uma função que usa uma função transform como um argumento, onde transform é uma função que tem um inteiro e retorna o inteiro de outro. O código a seguir mostra como usar apply1:

let increment x = x + 1

let result1 = apply1 increment 100

O valor de result será 101 após o anterior código é executado.

Vários argumentos são separados por sucessivas -> tokens, conforme mostrado no exemplo a seguir:

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

let mul x y = x * y

let result2 = apply2 mul 10 20

O resultado é 200.

Expressões Lambda

A expressão lambda é uma função sem nome. Nos exemplos anteriores, em vez de definir denominado funções increment e mul, você poderia usar expressões lambda da seguinte maneira:

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

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

Você definir expressões lambda, usando o fun palavra-chave. Uma expressão lambda é semelhante a uma definição de função, exceto que em vez da = token, o -> token é usado para separar a lista de argumentos do corpo da função. Como em uma definição de função regular, podem ser inferidos ou especificados explicitamente os tipos de argumento e o tipo de retorno da expressão lambda é inferido do tipo da última expressão no corpo. Para obter mais informações, consulte Expressões lambda: A diversão de palavra-chave (F#).

Composição de função e a canalização

Funções no F# podem ser compostas de outras funções. A composição de duas funções function1 e function2 é outra função, que representa o aplicativo de function1 seguidos da aplicação de function2:

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

O resultado é 202.

O pipelining permite chamadas de função fossem encadeadas como operações sucessivas. O pipelining funciona da seguinte maneira:

let result = 100 |> function1 |> function2

O resultado é novamente 202.

Consulte também

Outros recursos

Valores (F#)

Referência de linguagem do F#

Histórico de alterações

Date

History

Motivo

Maio de 2010

Exemplo de código fixo na seção parâmetros.