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