Funktioner
En funktion är ett värde som representerar en mappning från en uppsättning argumentvärden till ett enda värde. En funktion anropas av en uppsättning indatavärden (argumentvärdena) och skapar ett enda utdatavärde (returvärdet).
Funktioner skrivs med ett funktionsuttryck:
function-expression:
(
parameter-listopt)
function-return-typeopt=>
function-body
function-body:
uttryck
parameter-list:
fixed-parameter-list
fixed-parameter-list ,
optional-parameter-list
optional-parameter-list
fixed-parameter-list:
parameter
parametern ,
fixed-parameter-list
parameter:
parameter-name parameter-typeopt
parameter-name:
identifierare
parametertyp:
assertion
function-return-type:
assertion
påstående:
as
nullable-primiitve-type
optional-parameter-list:
optional-parameter
optional-parameter ,
optional-parameter-list
optional-parameter:
optional
parameter
nullable-primitve-type
nullable
opt primitive-type
Följande är ett exempel på en funktion som kräver exakt två värden x
och y
, och ger resultatet av att tillämpa operatorn på +
dessa värden. och x
är parametrar som ingår i parameterlistan för funktionen och är funktionstextenx + y
: y
(x, y) => x + y
Resultatet av utvärderingen av ett funktionsuttryck är att skapa ett funktionsvärde (inte för att utvärdera funktionstexten). Som en konvention i det här dokumentet visas funktionsvärden (till skillnad från funktionsuttryck) med parameterlistan men med en ellips (...
) i stället för funktionstexten. När funktionsuttrycket ovan till exempel har utvärderats visas det som följande funktionsvärde:
(x, y) => ...
Följande operatorer definieras för funktionsvärden:
Operator | Result |
---|---|
x = y |
Equal |
x <> y |
Not equal |
Den interna typen av funktionsvärden är en anpassad funktionstyp (härledd från den inbyggda typen function
) som visar parameternamnen och anger alla parametertyper och returtypen som ska vara any
. (Gå till Funktionstyper för information om funktionstyper.)
Funktionens funktionstext körs genom att funktionsvärdet anropas med hjälp av ett invoke-expression. Att anropa ett funktionsvärde innebär att funktionstexten för funktionsvärdet utvärderas och ett värde returneras eller att ett fel utlöses.
invoke-expression:
primary-expression (
argument-listopt )
argument-list:
expression-list
Varje gång ett funktionsvärde anropas anges en uppsättning värden som en argumentlista som kallas argumenten för funktionen.
En argumentlista används för att ange ett fast antal argument direkt som en lista med uttryck. I följande exempel definieras en post med ett funktionsvärde i ett fält och sedan anropas funktionen från ett annat fält i posten:
[
MyFunction = (x, y, z) => x + y + z,
Result1 = MyFunction(1, 2, 3) // 6
]
Följande gäller när du anropar en funktion:
Miljön som används för att utvärdera funktionens funktionstext innehåller en variabel som motsvarar varje parameter, med samma namn som parametern. Värdet för varje parameter motsvarar ett värde som konstruerats från argumentlistan för invoke-expression enligt definitionen i Parametrar.
Alla uttryck som motsvarar funktionsargumenten utvärderas innan funktionstexten utvärderas.
Fel som uppstår vid utvärdering av uttrycken i uttryckslistan eller funktionstexten sprids.
Antalet argument som skapas från argumentlistan måste vara kompatibelt med funktionens parametrar, eller så uppstår ett fel med orsakskoden
"Expression.Error"
. Processen för att fastställa kompatibilitet definieras i Parametrar.
Det finns två typer av parametrar som kan finnas i en parameterlista:
En obligatorisk parameter anger att ett argument som motsvarar parametern alltid måste anges när en funktion anropas. Obligatoriska parametrar måste anges först i parameterlistan. Funktionen i följande exempel definierar obligatoriska parametrar
x
ochy
:[ MyFunction = (x, y) => x + y, Result1 = MyFunction(1, 1), // 2 Result2 = MyFunction(2, 2) // 4 ]
En valfri parameter anger att ett argument som motsvarar parametern kan anges när en funktion anropas, men behöver inte anges. Om ett argument som motsvarar en valfri parameter inte anges när funktionen anropas används värdet
null
i stället. Valfria parametrar måste visas efter alla obligatoriska parametrar i en parameterlista. Funktionen i följande exempel definierar en fast parameterx
och en valfri parametery
:[ 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 ]
Antalet argument som anges när en funktion anropas måste vara kompatibelt med parameterlistan. Kompatibiliteten för en uppsättning argument A
för en funktion F
beräknas på följande sätt:
Låt värdet N representera antalet argument
A
som konstruerats från argumentlistan. Till exempel: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
Låt värdet Obligatoriskt representera antalet fasta parametrar
F
för och Valfritt antalet valfria parametrar förF
. Till exempel:() // Required = 0, Optional = 0 (x) // Required = 1, Optional = 0 (optional x) // Required = 0, Optional = 1 (x, optional y) // Required = 1, Optional = 1
Argument
A
är kompatibla med funktionenF
om följande är sant:- (N >= Fast) och (N <= (Fast + valfritt))
- Argumenttyperna är kompatibla med
F
motsvarande parametertyper
Om funktionen har en deklarerad returtyp är resultatvärdet för funktionens
F
brödtext kompatibelt medF
returtypen om följande är sant:- Värdet som returneras genom att utvärdera funktionstexten med de angivna argumenten för funktionsparametrarna har en typ som är kompatibel med returtypen.
Om funktionstexten ger ett värde som inte är kompatibelt med funktionens returtyp utlöses ett fel med orsakskoden
"Expression.Error"
.
För att kunna skriva ett funktionsvärde som är rekursivt är det nödvändigt att använda omfångsoperatorn (@
) för att referera till funktionen inom dess omfång. Följande post innehåller till exempel ett fält som definierar Factorial
funktionen och ett annat fält som anropar den:
[
Factorial = (x) =>
if x = 0 then 1 else x * @Factorial(x - 1),
Result = Factorial(3) // 6
]
På samma sätt kan ömsesidigt rekursiva funktioner skrivas så länge varje funktion som behöver nås har ett namn. I följande exempel har en del av Factorial
funktionen omstrukturerats till en andra Factorial2
funktion.
[
Factorial = (x) => if x = 0 then 1 else Factorial2(x),
Factorial2 = (x) => x * Factorial(x - 1),
Result = Factorial(3) // 6
]
En funktion kan returnera en annan funktion som ett värde. Den här funktionen kan i sin tur vara beroende av en eller flera parametrar för den ursprungliga funktionen. I följande exempel returnerar funktionen som är associerad med fältet MyFunction
en funktion som returnerar den angivna parametern:
[
MyFunction = (x) => () => x,
MyFunction1 = MyFunction(1),
MyFunction2 = MyFunction(2),
Result = MyFunction1() + MyFunction2() // 3
]
Varje gång funktionen anropas returneras ett nytt funktionsvärde som underhåller värdet för parametern så att parametervärdet returneras när den anropas.
Förutom parametrar kan funktionstexten för ett funktionsuttryck referera till variabler som finns i miljön när funktionen initieras. Funktionen som definieras av fältet MyFunction
kommer till exempel åt fältet C
för den omslutande posten A
:
[
A =
[
MyFunction = () => C,
C = 1
],
B = A[MyFunction]() // 1
]
När MyFunction
anropas får den åtkomst till värdet för variabeln C
, även om den anropas från en miljö (B
) som inte innehåller en variabel C
.
Varje uttryck är en syntaktisk förkortning för att deklarera otypade funktioner med en enda parameter med namnet _
(understreck).
each-expression:
each
each-expression-body
each-expression-body:
function-body
Förenklade deklarationer används ofta för att förbättra läsbarheten för funktionsanrop med högre ordning.
Följande par med deklarationer är till exempel semantiskt likvärdiga:
each _ + 1
(_) => _ + 1
each [A]
(_) => _[A]
Table.SelectRows( aTable, each [Weight] > 12 )
Table.SelectRows( aTable, (_) => _[Weight] > 12 )