Tempo de leitura:
Neste tutorial vamos perceber a diferença entre utilizar each _ e declarar explicitamente uma função na linguagem M do Power Query.
O objetivo não é deixar de utilizar each. Pelo contrário: each é extremamente útil para escrever funções simples de forma rápida e compacta.
No entanto, à medida que as nossas expressões se tornam mais avançadas, declarar explicitamente os parâmetros de uma função pode tornar o código mais claro e, em algumas situações, torna-se mesmo necessário.
Vamos começar pelo exemplo mais simples e aumentar gradualmente a complexidade.
1. each _ vs. função explícita
Vamos começar por criar uma lista com os números de 1 a 10:
{1 .. 10}
Pretendemos agora multiplicar cada elemento da lista por 2.
Podemos utilizar List.Transform:
List.Transform( Source, each _ * 2)
A função List.Transform percorre cada elemento da lista e executa a função que fornecemos no segundo argumento.
Neste caso:
each _ * 2
O underscore _ representa o elemento atual da lista.
Assim, durante a execução, podemos imaginar:
_ = 1 → 1 * 2_ = 2 → 2 * 2_ = 3 → 3 * 2...
Mas podemos escrever exatamente a mesma transformação utilizando uma função explícita:
List.Transform( Source, (x) => x * 2)
Neste caso, demos ao parâmetro da função o nome x.
Portanto:
each _ * 2
é equivalente a:
(x) => x * 2
O resultado é exatamente o mesmo.
Neste exemplo concreto, a função explícita não apresenta uma vantagem significativa. Na realidade, each _ é mais curto e perfeitamente legível.
O objetivo deste primeiro exemplo é apenas perceber uma ideia fundamental:
each é uma forma abreviada de declarar uma função com um parâmetro implícito representado por _.
2. Cenário 1 – Quando existem vários parâmetros
Vamos agora analisar uma situação em que a função explícita deixa de ser apenas uma alternativa.
Considere a seguinte lista:
{10, 20, 30, 40}
Pretendemos somar todos os valores.
Podemos utilizar List.Accumulate:
List.Accumulate( {10, 20, 30, 40}, 0, (acumulado, valor) => acumulado + valor)
Neste caso, a função fornecida ao List.Accumulate recebe dois parâmetros:
(acumulado, valor) =>
O primeiro, acumulado, contém o resultado acumulado até ao momento.
O segundo, valor, contém o elemento atual da lista.
A execução ocorre conceptualmente desta forma:
acumulado valor resultado0 10 1010 20 3030 30 6060 40 100
O resultado final é:
100
Aqui já encontramos uma diferença importante.
each representa essencialmente uma função com apenas um parâmetro implícito:
(_) => ...
Mas neste caso necessitamos de dois:
(acumulado, valor) =>
Por isso, precisamos de declarar explicitamente a função.
Criar uma lista de valores acumulados
Podemos utilizar o mesmo princípio para criar uma lista com a evolução do acumulado:
List.Accumulate( Source, {0}, (acumulado, valor) => acumulado & {List.Last(acumulado) + valor})
Aqui o estado inicial já não é simplesmente:
0
mas sim:
{0}
Ou seja, uma lista.
Em cada iteração:
List.Last(acumulado)
obtém o último valor calculado, soma-lhe o valor atual e acrescenta o resultado à lista.
Para:
{10, 20, 30, 40}
obtemos:
{0, 10, 30, 60, 100}
Este é um excelente exemplo de uma situação em que uma função explícita é necessária porque a função recebe vários parâmetros.
3. Cenário 2 – Declarar tipos de dados
Outra vantagem das funções explícitas é podermos definir claramente os tipos de dados esperados pela função.
Vamos criar uma função para calcular:
Quantidade × Preço
Podemos escrever:
let fxMultiplicar = (quantidade as number, preco as number) as number => quantidade * preco, Resultado = fxMultiplicar(50, 15)in Resultado
Vamos analisar a declaração:
(quantidade as number, preco as number) as number =>
Estamos a indicar que a função recebe dois parâmetros:
quantidadepreco
e que ambos têm de ser do tipo:
number
Depois dos parâmetros temos ainda:
as number
que define o tipo de dados devolvido pela função.
Podemos interpretar a assinatura desta função como:
number + number → number
Neste caso:
fxMultiplicar(50, 15)
devolve:
750
A grande vantagem é que estamos a tornar explícito o contrato da função.
Sabemos exatamente:
o que entra;que tipos são aceites;e que tipo será devolvido.
Se tentarmos fornecer um valor incompatível com os tipos declarados, o Power Query pode identificar esse problema.
Por exemplo:
fxMultiplicar("50", 15)
Aqui "50" é texto, enquanto a função espera um number.
Assim, quando os tipos dos parâmetros são relevantes, a função explícita permite escrever código mais rigoroso e previsível.
4. Cenário 3 – Quando existem vários âmbitos
Vamos agora entrar numa das situações mais importantes: funções aninhadas.
Vamos criar uma tabela:
let Source = #table( {"Produto", "Valores", "Factor"}, { {"A", {10, 20, 40}, 2}, {"B", {2, 4, 6}, 3} } )in Source
Temos:
Produto Valores FactorA {10,20,40} 2B {2,4,6} 3
Pretendemos multiplicar cada número existente na coluna Valores pelo Factor da respetiva linha.
Aqui temos duas operações diferentes.
Primeiro, precisamos de percorrer as linhas da tabela.
Depois, para cada linha, temos de percorrer os elementos da lista existente em [Valores].
Podemos escrever:
let Source = #table( {"Produto", "Valores", "Factor"}, { {"A", {10, 20, 40}, 2}, {"B", {2, 4, 6}, 3} } ), Calculo = Table.AddColumn( Source, "Multiplicar pelo Fator", (LinhaTabela) => List.Transform( LinhaTabela[Valores], (ValorLista) => ValorLista * LinhaTabela[Factor] ) )in Calculo
Aqui existem dois âmbitos diferentes.
A função:
(LinhaTabela) =>
recebe a linha atual da tabela.
Por exemplo:
Produto = AValores = {10,20,40}Factor = 2
Dentro dessa função chamamos List.Transform.
Esta função recebe outro parâmetro:
(ValorLista) =>
que representa cada elemento da lista.
Assim, temos:
LinhaTabela → linha atual da tabelaValorLista → elemento atual da lista
Para a primeira linha:
LinhaTabela[Factor] = 2
enquanto ValorLista passa sucessivamente por:
102040
Portanto:
ValorLista * LinhaTabela[Factor]
executa:
10 × 2 = 2020 × 2 = 4040 × 2 = 80
A grande vantagem das funções explícitas começa agora a tornar-se evidente.
Ao utilizarmos nomes como:
LinhaTabelaValorLista
sabemos imediatamente qual é o âmbito de cada valor.
Em expressões aninhadas, isto pode tornar o código bastante mais fácil de compreender do que utilizar vários each e vários _.
5. Cenário 4 – Referenciar o contexto exterior
Vamos agora avançar um passo.
No exemplo anterior existiam dois âmbitos.
Neste exemplo, a função interior vai precisar de consultar diretamente informação que pertence ao âmbito exterior.
Imaginemos duas tabelas.
A primeira contém clientes:
ID_Cliente Cliente1 Contoso2 Fabrikam3 Adventure Works
E temos uma segunda tabela chamada Vendas:
ID_Cliente Valor1 1001 2502 3003 1503 400
Pretendemos adicionar à tabela de clientes uma nova coluna chamada:
ValoresVenda
Essa coluna deverá conter as linhas da tabela Vendas correspondentes a cada cliente.
Podemos utilizar:
NovaColuna = Table.AddColumn( Tabela, "ValoresVenda", (LinhaCliente) => Table.SelectRows( Vendas, (LinhaVendas) => LinhaVendas[ID_Cliente] = LinhaCliente[ID_Cliente] ) )
Vamos analisar cuidadosamente o âmbito.
A função exterior é:
(LinhaCliente) =>
LinhaCliente representa a linha atual da tabela onde estamos a adicionar a nova coluna.
Depois executamos:
Table.SelectRows( Vendas, ...)
Esta função percorre as linhas da tabela Vendas.
A função interior é:
(LinhaVendas) =>
Por isso temos agora:
LinhaCliente → linha da tabela exteriorLinhaVendas → linha da tabela Vendas
E chegamos à parte mais importante:
LinhaVendas[ID_Cliente] =LinhaCliente[ID_Cliente]
Do lado esquerdo estamos a consultar o ID_Cliente da linha atual da tabela Vendas.
Do lado direito estamos a consultar o ID_Cliente da linha pertencente ao âmbito exterior.
Por exemplo, se estivermos no cliente 1:
LinhaCliente[ID_Cliente] = 1
o Table.SelectRows vai testar as linhas de Vendas:
1 = 1 → verdadeiro1 = 1 → verdadeiro2 = 1 → falso3 = 1 → falso3 = 1 → falso
Como resultado, a nova coluna contém apenas as vendas pertencentes ao cliente atual.
Este exemplo demonstra uma característica muito importante das funções em M:
uma função interior pode continuar a aceder a identificadores definidos no âmbito da função exterior.
E aqui a vantagem da função explícita torna-se particularmente evidente.
Em vez de termos vários _ cujo significado depende do each onde nos encontramos, podemos escrever:
LinhaClienteLinhaVendas
e perceber imediatamente de que contexto vem cada valor.
Conclusão
each continua a ser extremamente útil em Power Query.
Para uma transformação simples como:
each _ * 2
não existe normalmente qualquer necessidade de escrever:
(x) => x * 2
A primeira solução é mais curta e perfeitamente clara.
Mas à medida que o código evolui, as funções explícitas começam a oferecer vantagens importantes.
Com elas podemos:
- trabalhar com vários parâmetros;
- declarar os tipos de dados dos parâmetros e do resultado;
- distinguir diferentes âmbitos em funções aninhadas;
- referenciar claramente valores pertencentes ao contexto exterior.
A regra prática pode ser muito simples:
Se a expressão é curta e existe apenas um contexto óbvio, each _ é normalmente a melhor escolha.
Quando precisamos de identificar parâmetros, distinguir âmbitos ou trabalhar com lógica mais avançada, uma função explícita torna o código muito mais claro e controlável.
Próximo artigo:
Artigo Anterior:
Artigos por Categoria
- Microsoft Excel (48)
- Power Apps (16)
- Power Automate (3)
- Power BI (15)
- Power Query (16)
- Python (3)
- VBA (7)
Últimos Artigos
- Power Query M: Quando devemos usar uma função explícita em vez de each _?
- Quando usar Folder.Files e Folder.Contents no Power Query
- Funções DAX para Análise Avançada: INDEX, OFFSET e WINDOW
- Funções REDUCE e SCAN no Excel: Entenda a Diferença
- Como Usar Parâmetros no Power BI para Relatórios Interativos

Leave a Reply