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:

      optionalparâ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 functionintrí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 e y:

      [ 
          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âmetro x fixo e um parâmetro yopcional :

      [ 
          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 de F. 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ção F se o seguinte for verdadeiro:

    • (N >= Fixo) e (N <= (Fixo + Opcional))
    • Os tipos de argumento são compatíveis com Fos 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 com Fo 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 Aanexo:

[ 
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:
      eachcada-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 )