Funções
Uma função é um valor que representa um mapeamento de um conjunto de valores de argumento para um único valor. Uma função é invocada por um conjunto fornecido de valores de entrada (os valores de argumento) e produz um único valor de saída (o valor de retorno).
Funções de escrita
As funções são escritas usando uma expressão-função:
função-expressão:
(
parameter-listopt)
function-return-typeopt=>
function-body
função-corpo:
expressão
lista de parâmetros:
lista de parâmetros fixos
fixed-parameter-list ,
optional-parameter-list
lista de parâmetros opcional
lista de parâmetros fixos:
parâmetro
parameter-fixed-parameter-list,
Parâmetro:
parameter-name parameter-typeopt
nome-parâmetro:
identificador
tipo de parâmetro:
assertion
função-retorno-tipo:
assertion
asserção:
as
nullable-primiitve-type
opcional-parameter-list:
parâmetro-opcional
optional-parameter ,
optional-parameter-list
opcional-parâmetro:
optional
parâmetro
nullable-primitve-type
nullable
opt primitivo-tipo
A seguir está 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. Os parâmetros e são que fazem parte da lista de parâmetros da função, e o x + y
é o corpo da função:y
x
(x, y) => x + y
O resultado da avaliação de uma função-expressão é produzir um valor de função (não avaliar a função-corpo). Como uma convenção neste documento, os valores de função (em oposição às expressões de função) são mostrados com a lista de parâmetros, mas com uma reticência (...
) em vez do corpo da função. Por exemplo, uma vez que a expressão de função acima tenha sido avaliada, ela seria mostrada como o seguinte valor de função:
(x, y) => ...
Os seguintes operadores são definidos para valores de função:
Operador | Result |
---|---|
x = y |
Igual |
x <> y |
Não é igual a |
O tipo nativo de valores de função é um tipo de função personalizada (derivado do tipo function
intrínseco) que lista os nomes de parâmetros e especifica todos os tipos de parâmetros e o tipo de retorno a ser any
. (Ir para Tipos de função para obter detalhes sobre tipos de função.)
Invocando funções
O corpo da função de uma função é executado invocando o valor da função usando uma expressão de invocação. 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.
invocar-expressão:
opt pela 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, chamada 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 exemplo a seguir 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
]
O seguinte vale ao invocar uma função:
O ambiente usado para avaliar o corpo 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 construído a partir da lista de argumentos da invoke-expression, conforme definido em Parameters.
Todas as expressões correspondentes aos argumentos de função são avaliadas antes que o corpo-função seja avaliado.
Os erros gerados ao avaliar as expressões na lista de expressões ou no corpo da função são propagados.
O número de argumentos construídos a partir da lista de argumentos deve ser compatível com os parâmetros da função, ou um erro é gerado com o código
"Expression.Error"
de razão . O processo para determinar a compatibilidade é definido em Parâmetros.
Parâmetros
Existem dois tipos de parâmetros que podem estar presentes em uma lista de parâmetros:
Um parâmetro obrigatório indica que um argumento correspondente ao parâmetro deve sempre ser especificado quando uma função é invocada. Os parâmetros necessários devem ser especificados primeiro na lista de parâmetros. A função no exemplo a seguir define os parâmetros
x
necessários 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 é necessário ser especificado. Se um argumento que corresponde 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 quaisquer parâmetros necessários em uma lista de parâmetros. A função no exemplo a seguir define um parâmetrox
fixo e um parâmetroy
opcional :[ 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 forma:
Deixe que o valor N represente o número de argumentos
A
construídos a partir da lista de argumentos. 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 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
são compatíveis com a funçãoF
se o seguinte for verdadeiro:- (N >= Fixo) e (N <= (Fixo + Opcional))
- Os tipos de argumento são compatíveis com
F
os tipos de parâmetros correspondentes do
Se a função tiver um tipo de retorno declarado, o valor do resultado do corpo da função
F
será compatível comF
o tipo de retorno do se o seguinte for verdadeiro:- O valor gerado pela avaliação do corpo da função com os argumentos fornecidos para os parâmetros da função tem um tipo que é compatível com o tipo de retorno.
Se o corpo da função produz um valor incompatível com o tipo de retorno da função, um erro com o código
"Expression.Error"
de razão é gerado.
Funções recursivas
Para escrever um valor de função que é recursivo, é necessário usar o operador de escopo (@
) para fazer referência à função dentro de seu escopo. Por exemplo, o registro a seguir contém um campo que define a Factorial
função 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 escritas, desde que cada função que precisa ser acessada tenha um nome. No exemplo a seguir, parte da Factorial
função foi refatorada em uma segunda Factorial2
função.
[
Factorial = (x) => if x = 0 then 1 else Factorial2(x),
Factorial2 = (x) => x * Factorial(x - 1),
Result = Factorial(3) // 6
]
Encerramentos
Uma função pode retornar outra função como um valor. Esta função pode, por sua vez, depender de um ou mais parâmetros para a função original. No exemplo a seguir, a função associada ao campo MyFunction
retorna uma função que retorna o parâmetro especificado para ele:
[
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 que mantém o valor do parâmetro para que, quando ele for invocado, o valor do parâmetro seja retornado.
Funções e ambientes
Além dos parâmetros, o corpo-função de uma expressão-função pode fazer referência a variáveis que estão presentes no ambiente quando a função é inicializada. Por exemplo, a função definida pelo campo MyFunction
acede ao campo C
do registo A
anexo:
[
A =
[
MyFunction = () => C,
C = 1
],
B = A[MyFunction]() // 1
]
Quando MyFunction
é invocado, ele acessa o valor da variável C
, mesmo que esteja sendo invocado de um ambiente (B
) que não contém uma variável C
.
Declarações simplificadas
Cada expressão é uma abreviação sintática para declarar funções não tipadas usando um único parâmetro chamado _
(sublinhado).
cada expressão:
each
cada-expressão-corpo
cada expressão-corpo:
função-corpo
As declarações simplificadas são comumente usadas para melhorar a legibilidade da invocação de funções 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 )