Funções
Uma função é um valor que representa um mapeamento de um conjunto de valores de argumento para um valor. Uma função é invocada por um conjunto de valores de entrada (os valores de argumento) fornecido e produz um valor de saída (o valor retornado).
Escrita de funções
As funções são gravadas usando uma expressão-de-função:
expressão-de-função:
(
listade parâmetros opt)
function-return-typeopt=>
function-body
corpo-da-função:
expressão
lista-de-parâmetros:
lista-de-parâmetros-fixos
lista ,
de parâmetros fixos lista de parâmetros opcionais
lista-de-parâmetros-opcionais
lista-de-parâmetros-fixos:
parâmetro
parâmetro ,
lista de parâmetros fixos
parameter:
nome-do-parâmetro tipo-de-parâmetroopcional
nome-do-parâmetro:
identificador
tipo-de-parâmetro:
assertion
tipo-de-retorno-da-função:
assertion
declaração:
as
tipo de primiitve anulável
lista-de-parâmetros-opcionais:
parâmetro-opcional
parâmetro-opcional ,
lista-de-parâmetros-opcionais
parâmetro-opcional:
optional
parâmetro
tipo-primitivo-anulável
nullable
opt do tipo primitivo
Veja a seguir um exemplo de uma função que requer exatamente dois valores x
e y
e produz o resultado da aplicação do operador +
a esses valores. x
e y
são parâmetros que fazem parte da parameter-list da função, e x + y
é o function-body:
(x, y) => x + y
O resultado da avaliação de uma expressão-de-função é produzir um valor de função (não avaliar o corpo-da-função). Como uma convenção neste documento, os valores de função (e não as expressões de função) são mostrados com a parameter-list, mas com reticências (...
) em vez de com o function-body. Por exemplo, depois que a expressão de função acima tiver sido avaliada, ela será mostrada como o seguinte valor de função:
(x, y) => ...
Os seguintes operadores são definidos para valores de função:
Operador | Resultado |
---|---|
x = y |
Igual |
x <> y |
Diferente |
O tipo nativo de valores de função é um tipo de função personalizada (derivado do tipo intrínseco function
) que lista os nomes de parâmetro e especifica todos os tipos de parâmetro e o tipo de retorno para any
. (Acesse Tipos de função para obter detalhes sobre os tipos de função.)
Invocação de funções
O function-body de uma função é executado por meio da invocação do valor da função usando uma invoke-expression. Invocar um valor de função significa que o corpo-da-função do valor da função é avaliado e um valor é retornado ou um erro é gerado.
expressão-de-invocação:
opção de lista de argumentos de expressão(
primária )
lista-de-argumentos:
lista-de-expressões
Cada vez que um valor de função é invocado, um conjunto de valores é especificado como uma lista-de-argumentos, também chamados de argumentos para a função.
Uma lista-de-argumentos é usada para especificar um número fixo de argumentos diretamente como uma lista de expressões. O seguinte exemplo define um registro com um valor de função em um campo e, em seguida, invoca a função de outro campo do registro:
[
MyFunction = (x, y, z) => x + y + z,
Result1 = MyFunction(1, 2, 3) // 6
]
Os seguintes preceitos são válidos ao invocar uma função:
O ambiente usado para avaliar o corpo-da-função da função inclui uma variável que corresponde a cada parâmetro, com o mesmo nome que o parâmetro. O valor de cada parâmetro corresponde a um valor criado com base na argument-list da invoke-expression, conforme definido em Parâmetros.
Todas as expressões correspondentes aos argumentos da função são avaliadas antes que o corpo-da-função seja avaliado.
Os erros gerados ao avaliar as expressões na expression-list ou no function-body são propagados.
O número de argumentos criados com base na argument-list deve ser compatível com os parâmetros da função. Caso contrário, um erro será gerado com o código de motivo
"Expression.Error"
. O processo para determinar a compatibilidade é definido em Parâmetros.
Parâmetros
Há dois tipos de parâmetros que podem estar presentes em uma parameter-list:
Um parâmetro obrigatório indica que um argumento correspondente ao parâmetro precisa sempre ser especificado quando uma função é invocada. Os parâmetros obrigatórios precisam ser especificados primeiro na parameter-list. A função neste exemplo define os parâmetros necessários
x
ey
:[ MyFunction = (x, y) => x + y, Result1 = MyFunction(1, 1), // 2 Result2 = MyFunction(2, 2) // 4 ]
Um parâmetro opcional indica que um argumento correspondente ao parâmetro pode ser especificado quando uma função é invocada, mas não obrigatoriamente. Se um argumento que corresponder a um parâmetro opcional não for especificado quando a função for invocada, o valor
null
será usado. Os parâmetros opcionais devem aparecer após qualquer parâmetro obrigatório em uma parameter-list. A função neste exemplo define um parâmetro fixox
e um parâmetro opcionaly
:[ MyFunction = (x, optional y) => if (y = null) x else x + y, Result1 = MyFunction(1), // 1 Result2 = MyFunction(1, null), // 1 Result3 = MyFunction(2, 2), // 4 ]
O número de argumentos especificados quando uma função é invocada deve ser compatível com a lista de parâmetros. A compatibilidade de um conjunto de argumentos A
para uma função F
é calculada da seguinte maneira:
Permita que o valor N represente o número de argumentos
A
criados com base na argument-list. Por exemplo:MyFunction() // N = 0 MyFunction(1) // N = 1 MyFunction(null) // N = 1 MyFunction(null, 2) // N = 2 MyFunction(1, 2, 3) // N = 3 MyFunction(1, 2, null) // N = 3 MyFunction(1, 2, {3, 4}) // N = 3
Deixe o valor Required representar o número de parâmetros fixos de
F
e Optional representar o número de parâmetros opcionais deF
. Por exemplo:() // Required = 0, Optional = 0 (x) // Required = 1, Optional = 0 (optional x) // Required = 0, Optional = 1 (x, optional y) // Required = 1, Optional = 1
Os argumentos
A
serão compatíveis com a funçãoF
se as seguintes condições forem verdadeiras:- (N >= Fixo) e (N <= (Fixo + Opcional))
- Os tipos de argumento são compatíveis com os tipos de parâmetro correspondentes do
F
Se a função tiver um tipo de retorno declarado, o valor de resultado do corpo da função
F
será compatível com o tipo de retorno deF
se o seguinte for verdadeiro:- O valor produzido pela avaliação do corpo da função com os argumentos fornecidos para os parâmetros de função tem um tipo compatível com o tipo de retorno.
Se o corpo da função gerar um valor incompatível com o tipo de retorno da função, um erro com o código de motivo
"Expression.Error"
será gerado.
Funções recursivas
Para gravar um valor de função que é recursivo, é necessário usar o operador de escopo (@
) para fazer referência à função dentro do escopo dela. Por exemplo, o seguinte registro contém um campo que define a função Factorial
e outro campo que a invoca:
[
Factorial = (x) =>
if x = 0 then 1 else x * @Factorial(x - 1),
Result = Factorial(3) // 6
]
Da mesma forma, funções mutuamente recursivas podem ser gravadas, desde que cada função que precise ser acessada tenha um nome. No exemplo a seguir, parte da função Factorial
foi refatorada em uma segunda função Factorial2
.
[
Factorial = (x) => if x = 0 then 1 else Factorial2(x),
Factorial2 = (x) => x * Factorial(x - 1),
Result = Factorial(3) // 6
]
Fechamentos
Uma função pode retornar outra função como um valor. Essa função pode, por sua vez, depender de um ou mais parâmetros da função original. No seguinte exemplo, a função associada ao campo MyFunction
retorna uma função que retorna o parâmetro especificado para ela:
[
MyFunction = (x) => () => x,
MyFunction1 = MyFunction(1),
MyFunction2 = MyFunction(2),
Result = MyFunction1() + MyFunction2() // 3
]
Cada vez que a função é invocada, um novo valor de função será retornado mantendo o valor do parâmetro, de modo que, quando a função for invocada, o valor do parâmetro será retornado.
Funções e ambientes
Além dos parâmetros, o corpo-da-função de uma expressão-de-função pode referenciar variáveis que estão presentes no ambiente quando a função é inicializada. Por exemplo, a função definida pelo campo MyFunction
acessa o campo C
do registro delimitador A
:
[
A =
[
MyFunction = () => C,
C = 1
],
B = A[MyFunction]() // 1
]
Quando MyFunction
é invocado, ele acessa o valor da variável C
, embora ele esteja sendo invocado de um ambiente (B
) que não contém uma variável C
.
Declarações simplificadas
A each-expression é uma abreviação sintática para declarar funções não tipadas usando um único parâmetro chamado _
(sublinhado).
expressão-each:
each
cada corpo de expressão
corpo-da-expressão-each:
corpo-da-função
Declarações simplificadas são normalmente usadas para melhorar a legibilidade da invocação de uma função de ordem superior.
Por exemplo, os seguintes pares de declarações são semanticamente equivalentes:
each _ + 1
(_) => _ + 1
each [A]
(_) => _[A]
Table.SelectRows( aTable, each [Weight] > 12 )
Table.SelectRows( aTable, (_) => _[Weight] > 12 )