F # - Funções
Em F #, as funções funcionam como tipos de dados. Você pode declarar e usar uma função da mesma maneira que qualquer outra variável.
Uma vez que as funções podem ser usadas como quaisquer outras variáveis, você pode -
- Crie uma função, com um nome e associe esse nome a um tipo.
- Atribua um valor a ele.
- Execute alguns cálculos nesse valor.
- Passe-o como parâmetro para outra função ou sub-rotina.
- Retorna uma função como resultado de outra função.
Definindo uma função
As funções são definidas usando o letpalavra-chave. Uma definição de função tem a seguinte sintaxe -
let [inline] function-name parameter-list [ : return-type ]
= function-body
Onde,
function-name é um identificador que representa a função.
parameter-listfornece a lista de parâmetros separados por espaços. Você também pode especificar um tipo explícito para cada parâmetro e, se não for especificado, o compilador tende a deduzi-lo do corpo da função (como variáveis).
function-bodyconsiste em uma expressão ou uma expressão composta que consiste em várias expressões. A expressão final no corpo da função é o valor de retorno.
return-typeé dois pontos seguido por um tipo e é opcional. Se o tipo de retorno não for especificado, o compilador o determinará a partir da expressão final no corpo da função.
Parâmetros de uma função
Você lista os nomes dos parâmetros logo após o nome da função. Você pode especificar o tipo de um parâmetro. O tipo do parâmetro deve seguir o nome do parâmetro separado por dois pontos.
Se nenhum tipo de parâmetro for especificado, ele será inferido pelo compilador.
Por exemplo -
let doubleIt (x : int) = 2 * x
Chamando uma função
Uma função é chamada especificando o nome da função seguido por um espaço e, a seguir, quaisquer argumentos separados por espaços.
Por exemplo -
let vol = cylinderVolume 3.0 5.0
Os programas a seguir ilustram os conceitos.
Exemplo 1
O programa a seguir calcula o volume de um cilindro quando o raio e o comprimento são dados como parâmetros
// the function calculates the volume of
// a cylinder with radius and length as parameters
let cylinderVolume radius length : float =
// function body
let pi = 3.14159
length * pi * radius * radius
let vol = cylinderVolume 3.0 5.0
printfn " Volume: %g " vol
Quando você compila e executa o programa, ele produz a seguinte saída -
Volume: 141.372
Exemplo 2
O programa a seguir retorna o maior valor de dois parâmetros fornecidos -
// the function returns the larger value between two
// arguments
let max num1 num2 : int32 =
// function body
if(num1>num2)then
num1
else
num2
let res = max 39 52
printfn " Max Value: %d " res
Quando você compila e executa o programa, ele produz a seguinte saída -
Max Value: 52
Exemplo 3
let doubleIt (x : int) = 2 * x
printfn "Double 19: %d" ( doubleIt(19))
Quando você compila e executa o programa, ele produz a seguinte saída -
Double 19: 38
Funções Recursivas
Funções recursivas são funções que chamam a si mesmas.
Você define um recursivo usando o let rec combinação de palavras-chave.
A sintaxe para definir uma função recursiva é -
//Recursive function definition
let rec function-name parameter-list = recursive-function-body
Por exemplo -
let rec fib n = if n < 2 then 1 else fib (n - 1) + fib (n - 2)
Exemplo 1
O programa a seguir retorna Fibonacci 1 a 10 -
let rec fib n = if n < 2 then 1 else fib (n - 1) + fib (n - 2)
for i = 1 to 10 do
printfn "Fibonacci %d: %d" i (fib i)
Quando você compila e executa o programa, ele produz a seguinte saída -
Fibonacci 1: 1
Fibonacci 2: 2
Fibonacci 3: 3
Fibonacci 4: 5
Fibonacci 5: 8
Fibonacci 6: 13
Fibonacci 7: 21
Fibonacci 8: 34
Fibonacci 9: 55
Fibonacci 10: 89
Exemplo 2
O programa a seguir retorna o fatorial 8 -
open System
let rec fact x =
if x < 1 then 1
else x * fact (x - 1)
Console.WriteLine(fact 8)
Quando você compila e executa o programa, ele produz a seguinte saída -
40320
Notações de seta em F #
F # relata sobre o tipo de dados em funções e valores, usando uma notação de seta encadeada. Vamos dar um exemplo de uma função que recebe uma entrada int e retorna uma string. Na notação de seta, é escrito como -
int -> string
Os tipos de dados são lidos da esquerda para a direita.
Vamos pegar outra função hipotética que pega duas entradas de dados int e retorna uma string.
let mydivfunction x y = (x / y).ToString();;
F # relata o tipo de dados usando a notação de seta em cadeia como -
val mydivfunction : x:int -> y:int -> string
O tipo de retorno é representado pelo tipo de dados mais à direita em notação de seta encadeada.
Mais alguns exemplos -
Notação | Significado |
---|---|
float → float → float | A função recebe duas entradas de float e retorna outro float . |
int → string → float | A função recebe um int e uma string de entrada e retorna um float . |
Expressões Lambda
UMA lambda expression é uma função sem nome.
Vamos dar um exemplo de duas funções -
let applyFunction ( f: int -> int -> int) x y = f x y
let mul x y = x * y
let res = applyFunction mul 5 7
printfn "%d" res
Quando você compila e executa o programa, ele produz a seguinte saída -
35
Agora, no exemplo acima, se em vez de definir a função mul, poderíamos ter usado expressões lambda como -
let applyFunction ( f: int -> int -> int) x y = f x y
let res = applyFunction (fun x y -> x * y ) 5 7
printfn "%d" res
Quando você compila e executa o programa, ele produz a seguinte saída -
35
Composição de função e pipelining
Em F #, uma função pode ser composta de outras funções.
O exemplo a seguir mostra a composição de uma função chamada f, a partir de duas funções function1 e function2 -
let function1 x = x + 1
let function2 x = x * 5
let f = function1 >> function2
let res = f 10
printfn "%d" res
Quando você compila e executa o programa, ele produz a seguinte saída -
55
F # também oferece um recurso chamado pipelining of functions. O pipelining permite que as chamadas de função sejam encadeadas como operações sucessivas.
O exemplo a seguir mostra que -
let function1 x = x + 1
let function2 x = x * 5
let res = 10 |> function1 |> function2
printfn "%d" res
Quando você compila e executa o programa, ele produz a seguinte saída -
55