Power Query Mのeach式を関数として理解する

LWP | Power Query Mのeach式を関数として理解する

LWP TECHNICAL ARTICLE | 168

Power Query Mのeach式を関数として理解する

アンダースコア、レコード、暗黙のフィールド参照を一つの規則で読む

Copyright © 2026 LWP 山中 一弘

本資料は、出典を明記いただければ、商用・非商用を問わず、ご自由に複製・改変・再配布していただけます。なお、著作権表示は改変せず、そのまま記載してご利用くださいますようお願いいたします。

記事要約

Mのeachは『各行を処理する命令』ではなく、引数名をアンダースコアにした単項の無名関数を作る簡略記法です。each 1は、入力を受け取っても使わず、常に1を返す関数です。each _ + 1は、(_) => _ + 1と同じ意味になります。

アンダースコアが行、値、レコードのどれになるかはeach自身ではなく、その関数を呼ぶ側が渡す値で決まります。Table.AddColumn、Table.SelectRows、List.Transformを明示的な関数へ展開し、each [単価]の暗黙のフィールド参照やネスト時の読み方まで整理します。

本記事の対象とゴール

想定読者

  • Table.AddColumnやTable.SelectRowsでeachを使う方

  • アンダースコアが何を表すか迷う方

  • ネストしたeachを安全に読み書きしたい方

本記事で得られること

  1. each 1、each _、each _ + 1をクエリとして実行し、関数そのものと呼び出し結果を区別できます。

  2. each式を通常の関数式へ展開できます。

  3. 呼び出し元からアンダースコアの値を判断できます。

  4. 曖昧なネストを明示的な引数名へ書き換えられます。

目次

  • 第1章 まず each を使わずに考えます

  • 第2章 each の正体

  • 第3章 アンダースコア _ の正体

  • 第4章 なぜ [単価] だけで書けるのか

  • 第5章 each はテーブル専用ではありません

  • 第6章 each の2つの利点

  • 第7章 each を使わない方が分かりやすい場合

  • 第8章 ネストした each に注意します

  • 第9章 each とクロージャー

  • 第10章 実務での読み方

  • 第11章 まとめ

  • 実務で覚えておくこと

第1章 まず each を使わずに考えます

1. Table.AddColumn は関数を受け取ります

最初に理解するべきなのは、each ではありません。

Table.AddColumn が何を要求しているかです。

たとえば、次のテーブルがあるとします。

商品 単価 数量
A 100 3
B 200 2

ここに「金額」列を追加し、

単価 × 数量

を計算したいとします。

Power Queryでは、通常次のように書きます。

Table.AddColumn(
    Source,
    "金額",
    each [単価] * [数量]
)

しかし、この状態では each の意味が隠れています。

そこで、まず each を使わずに書いてみます。

Table.AddColumn(
    Source,
    "金額",
    (row) => row[単価] * row[数量]
)

重要なのは第3引数です。

(row) => row[単価] * row[数量]

これは関数です。

Table.AddColumn は、第3引数として「計算結果の値」を受け取るのではありません。

各行に対して呼び出す関数を受け取ります。

2. 1行はMではレコードです

先ほどの1行、

商品 単価 数量
A 100 3

は、M言語では概念的に次のレコードとして扱えます。

[
    商品 = "A",
    単価 = 100,
    数量 = 3
]

つまり、Table.AddColumn が各行について第3引数の関数を呼び出すとき、その関数に渡される値はレコードです。

したがって、

(row) => row[単価] * row[数量]

の row には、たとえば、

[
    商品 = "A",
    単価 = 100,
    数量 = 3
]

が渡されます。

すると、row[単価] は100、row[数量] は3になり、結果として300を返します。

ここまででは、まだ each は必要ありません。

3. 関数を別に定義して渡すこともできます

let
    AddAmount =
        (row as record) as number =>
            row[単価] * row[数量],
 
    Result =
        Table.AddColumn(
            Source,
            "金額",
            AddAmount
        )
in
    Result

この形を見ると、Table.AddColumn の構造がはっきりします。

Table.AddColumn
    ↓
第3引数に関数を渡す
    ↓
Table.AddColumnが各行をその関数へ渡す
    ↓
関数が各行について値を返す
    ↓
その値が新しい列になる

この構造を理解してから each を見ることが重要です。

第2章 each の正体

1. each は1引数関数の簡略記法です

MicrosoftのM言語仕様では、

each 式

は、1個の引数 _ を持つ関数の簡略記法です。

したがって、

each _ + 1

と、

(_) => _ + 1

は意味的に同じです。

さらに、引数名 _ を普通の名前へ置き換えて考えれば、

(x) => x + 1

と同じ構造です。

したがって、each を見たときには、「それぞれ処理する命令」と考えるより、「ここで1引数の関数を作っている」と考えた方が正確です。

2. each の後ろは関数本体です

each _ * 10

は、

(_) => _ * 10

です。

さらに普通の引数名を使えば、

(x) => x * 10

です。

したがって、each _ * 10 という式自体が関数です。

each はループを開始するキーワードではありません。each を書いた時点で、1引数関数を記述しています。

3. each 1 も完全な関数です

each の意味を確認するために非常に有効なのが、次の例です。

each 1

これは、

(_) => 1

と同じです。

つまり、引数は1個受け取りますが、その引数を使わず、常に1を返す関数です。

ここで重要なのは、each 1 に _ が書かれていないことです。それでも関数としては (_) => 1 です。引数を受け取っていますが、単に使っていないだけです。

この例を見ると、each が「各行を示す命令」ではなく、1引数関数を作る記法であることがよく分かります。

4. クエリの結果を each 1 にしてみます

まず、Power Queryの空のクエリに次のコードを入力します。

let
    FixedOne = each 1
in
    FixedOne

このクエリの結果は数値の1ではありません。結果として表示されるのは関数です。

FixedOne へ入っているのは、1という値ではなく、呼び出されたときに1を返す処理だからです。Mでは、関数を変数に入れ、クエリの結果として返せます。

この最小例は、each 1 の本質を最も直接的に示します。

each 1
    ↓
(_) => 1
    ↓
引数を1個受け取り、常に1を返す関数

5. each 1 で作った関数を呼び出します

次は、関数を作るだけでなく、その場で呼び出します。

let
    FixedOne = each 1,
    Result = FixedOne(999)
in
    Result

結果は1です。999は関数へ渡されていますが、関数本体で使われていないため、結果には影響しません。

文字列を渡しても同じです。

let
    FixedOne = each 1,
    Result = FixedOne("Excel")
in
    Result

この結果も1です。

レコードを渡しても同じです。

let
    FixedOne = each 1,
    Input = [商品 = "A", 単価 = 100],
    Result = FixedOne(Input)
in
    Result

この結果も1です。数値、文字列、レコードという入力の違いに関係なく1を返すのは、each 1 が入力を使わない関数だからです。

6. List.Transform が同じ関数を繰り返し呼び出します

each 自身が繰り返すのではないことも、each 1 で確認できます。

let
    Source = {10, 20, 30},
    Result =
        List.Transform(
            Source,
            each 1
        )
in
    Result

結果は次のリストです。

{1, 1, 1}

List.Transform が10、20、30を順番に関数へ渡します。each 1 で作られた関数は、どの値を受け取っても1を返します。

したがって、繰り返しを担当するのは List.Transform です。each が担当するのは、渡された値を1個受け取る関数を作ることです。

7. List.Select では真偽値を返す関数になります

List.Select は、各要素についてtrueまたはfalseを返す関数を受け取ります。常にtrueを返せば、すべての要素が残ります。

let
    Source = {10, 20, 30},
    Result =
        List.Select(
            Source,
            each true
        )
in
    Result

結果は {10, 20, 30} です。

逆に、常にfalseを返せば、すべての要素が除外されます。

let
    Source = {10, 20, 30},
    Result =
        List.Select(
            Source,
            each false
        )
in
    Result

結果は空のリスト {} です。

each true は (_) => true、each false は (_) => false です。ここでも入力は受け取りますが、判定には使っていません。

8. Table.AddColumn では行ごとに固定値を返せます

同じ each 1 をテーブルへ渡すと、各行に1が入った固定値列を作れます。

let
    Source =
        #table(
            {"商品"},
            {
                {"A"},
                {"B"},
                {"C"}
            }
        ),
    Result =
        Table.AddColumn(
            Source,
            "固定値",
            each 1,
            Int64.Type
        )
in
    Result

結果は、A、B、Cのどの行にも1が入ったテーブルです。

ここでも Table.AddColumn が行レコードを1行ずつ関数へ渡しています。each 1 は行レコードを受け取りますが、そのフィールドを一つも参照せず1を返します。

9. each _ は受け取った値をそのまま返します

each _

は、

(_) => _

です。

つまり、受け取った値をそのまま返す恒等関数です。空のクエリで次のように確認できます。

let
    Identity = each _,
    NumberResult = Identity(10),
    TextResult = Identity("Excel"),
    Result = [数値 = NumberResult, 文字列 = TextResult]
in
    Result

結果は [数値 = 10, 文字列 = "Excel"] です。_ は、関数を呼び出すときに渡した値を表しています。

10. each _ + 1 は入力を使う最小の計算です

each 1 は入力を使いませんが、each _ + 1 は入力を計算に使います。

let
    AddOne = each _ + 1,
    Result = AddOne(10)
in
    Result

結果は11です。

同じ関数をリストへ渡すと、各要素に1を加えます。

let
    Source = {1, 2, 3},
    Result =
        List.Transform(
            Source,
            each _ + 1
        )
in
    Result

結果は {2, 3, 4} です。

11. _ は関数本体で何度でも参照できます

_ は特別な現在行命令ではなく引数名なので、通常の引数と同じように複数回参照できます。

let
    Square = each _ * _,
    Result = Square(4)
in
    Result

結果は16です。これは次の関数と同じ構造です。

let
    Square = (x) => x * x,
    Result = Square(4)
in
    Result

12. レコードを渡すとフィールドを参照できます

最後に、単純なレコードを使って [単価] の意味へつなげます。

let
    GetPrice = each [単価],
    Input = [商品 = "A", 単価 = 100],
    Result = GetPrice(Input)
in
    Result

結果は100です。

GetPrice が受け取ったレコードは _ です。[単価] は、その暗黙の引数 _ にある単価フィールドを参照しています。明示的に書けば、次の関数に相当します。

let
    GetPrice = (row) => row[単価],
    Input = [商品 = "A", 単価 = 100],
    Result = GetPrice(Input)
in
    Result

ここまでの最小例は、すべて同じ規則で読めます。

each 1
each true
each _
each _ + 1
each _ * _
each [単価]
each Text.Trim(_)

これらはすべて、引数を1個受け取る関数です。違うのは関数本体だけです。

第3章 アンダースコア _ の正体

1. _ は「現在行」という意味ではありません

Power Queryの解説では、「_ は現在の行です」と説明されることがあります。

Table.AddColumn や Table.SelectRows だけを使っている間は、結果としてその説明でも動きます。

しかし、M言語としては正確ではありません。

each は、

(_) => ...

の簡略記法です。

したがって _ の正体は、その1引数関数の引数名です。

2. _ が何になるかは呼び出し側が決めます

List.Transform(
    {1, 2, 3},
    each _ * 10
)

では、_ は1、2、3というリスト要素です。

一方、

Table.AddColumn(
    Source,
    "金額",
    each [単価] * [数量]
)

では、_ は行レコードです。

さらに、

Table.TransformColumns(
    Source,
    {
        {"商品", each Text.Trim(_)}
    }
)

では、_ は「商品」列の各セル値です。

つまり、

each
    ↓
1引数関数を作る
    ↓
その引数名が _

までは常に同じです。

しかし、_ に何が入るかは、その関数を呼び出す側によって決まります。

3. _ の型も each が決めるわけではありません

each は型指定なしの1引数関数を簡略記述します。

したがって、

each _ * 2

だけを見て、_ は数値である、と each が宣言しているわけではありません。

同様に、

each [単価]

では、_ にレコードが渡されることを前提にしています。

each を理解するときには、

_ は何ですか

ではなく、

この関数の呼び出し元は、何を引数として渡しますか

と考えることが重要です。

第4章 なぜ [単価] だけで書けるのか

1. ここには each とは別の簡略記法があります

each [単価] * [数量]

を、

each _[単価] * _[数量]

と考えることができます。

さらに each を展開すると、

(_) => _[単価] * _[数量]

です。

普通の引数名へ置き換えれば、

(row) => row[単価] * row[数量]

となります。

この変形は非常に重要です。

2. [単価] は暗黙のターゲットを使ったフィールド参照です

M言語には、レコードのフィールドを選択する記法があります。

明示的に書けば、

row[単価]

です。

一方、each 式の中では、

[単価]

と書くことができます。

MicrosoftのM言語仕様でも、

each [A]

と、

(_) => _[A]

が意味的に等価な例として示されています。

ここで注意したいのは、「レコードの規定値が _ だから省略できる」と理解するより、[A] という暗黙ターゲットのフィールド参照が、each の引数 _ に対して解釈されると理解する方が正確だということです。

つまり、each と [列名] には、関連していますが別々の簡略化が重なっています。

3. Table.AddColumn で each が特に美しく見える理由

普通の関数表現は、

(row) => row[単価] * row[数量]

です。

第1段階として、1引数関数を each で簡略化します。

each _[単価] * _[数量]

さらに、暗黙のフィールド参照により、

each [単価] * [数量]

まで短くできます。

つまり、次の2段階の省略があります。

第1の省略
(row) => ...
    ↓
each ...
 
第2の省略
_[単価]
    ↓
[単価]

この二重の簡略化によって、通常の関数式が非常に自然な列計算の形になります。

4. 日本語では「それぞれ」と読めますが、それは結果です

each [単価] * [数量]

を日本語で「それぞれの行について、単価×数量を計算します」と読むのは自然です。

ただし、言語として起きていることは、

1引数関数を作る
↓
Table.AddColumnが各行レコードを引数として渡す
↓
関数が計算結果を返す

です。

したがって、each = 各行について ではありません。

Table.AddColumn が行を1個ずつ関数へ渡すため、結果として「各行について」と読めるのです。

第5章 each はテーブル専用ではありません

1. List.Transform

List.Transform(
    {1, 2, 3},
    each _ * 10
)

は、

List.Transform(
    {1, 2, 3},
    (x) => x * 10
)

と同じ構造です。

ここで _ はレコードではなく、リスト要素です。

2. List.Select

List.Select(
    {1, 2, 3, 4, 5},
    each _ >= 3
)

は、

List.Select(
    {1, 2, 3, 4, 5},
    (x) => x >= 3
)

です。

3. Table.SelectRows

Table.SelectRows(
    Source,
    each [売上] >= 1000
)

は、

Table.SelectRows(
    Source,
    (row) => row[売上] >= 1000
)

と考えられます。

ここでは呼び出し側が各行レコードを渡すので、_ は行レコードです。

4. Table.TransformColumns

Table.TransformColumns(
    Source,
    {
        {"商品", each Text.Trim(_)}
    }
)

は、

Table.TransformColumns(
    Source,
    {
        {"商品", (value) => Text.Trim(value)}
    }
)

と考えられます。

ここで _ は行レコードではなく、その列のセル値です。

この違いを理解していないと、each [列名] が使える場所と使えない場所の区別がつかなくなります。

第6章 each の2つの利点

1. 1引数関数を短く書けます

通常の関数、

(x) => x * 2

を、

each _ * 2

と書けます。

短い関数を高階関数へ渡す場合、非常に読みやすくなります。

2. 行レコードではフィールド参照まで短くできます

通常、

(row) => row[単価] * row[数量]

と書くところを、

each [単価] * [数量]

と書けます。

この二重の簡略化が、Table.AddColumn や Table.SelectRows で特に強力です。

3. 「処理内容」だけに集中できます

次の2つを比較します。

(row) => row[単価] * row[数量]

each [単価] * [数量]

後者では、引数名、ラムダ演算子 =>、レコード変数名が表面から消えています。

残るのは「単価 × 数量」という処理内容だけです。

簡単な行処理で each が読みやすい理由はここにあります。

第7章 each を使わない方が分かりやすい場合

1. each は万能ではありません

短い処理では非常に便利ですが、関数が複雑になると、逆に引数名を明示した方が読みやすくなります。

(row) =>
    let
        price = row[単価],
        quantity = row[数量],
        discount = row[値引率]
    in
        if quantity = null then
            null
        else if quantity <= 0 then
            0
        else
            price * quantity * (1 - discount)

このような場合、row と明示した方が参照関係を追いやすくなります。

2. 2引数以上の関数は通常の関数構文で書きます

each は1個の引数 _ を取る関数の簡略記法です。

したがって、

(a, b) => a + b

のような2引数関数を、そのまま each へ置き換えるものではありません。

each は1引数関数に特化した簡略構文です。

第8章 ネストした each に注意します

1. each が2つあると _ の意味が切り替わります

Table.AddColumn(
    Source,
    "変換後",
    each
        List.Transform(
            [Values],
            each _ * 2
        )
)

ここには each が2つあります。

外側の each は、概念的には、

(row) => ...

です。

一方、内側の each は、

(x) => x * 2

です。

つまり、

外側の each
    _ = 行レコード
 
内側の each
    _ = リスト要素

となります。

2. 複雑になったら引数名を戻します

Table.AddColumn(
    Source,
    "変換後",
    (row) =>
        List.Transform(
            row[Values],
            (value) => value * 2
        )
)

こちらなら、row は行、value はリスト要素と明確です。

each は短く書くための道具であって、必ず使わなければならないものではありません。

第9章 each とクロージャー

1. each 自体はクロージャーではありません

each は、

(_) => ...

という関数式のシンタックスシュガーです。

したがって、each を使っただけでクロージャーになるわけではありません。

2. 外側の環境を参照するとクロージャーになります

let
    rate = 1.1,
 
    AddTax =
        each _ * rate
in
    AddTax

each を展開すると、

(_) => _ * rate

です。

この関数本体は、引数 _ だけでなく、外側で定義された rate = 1.1 も参照しています。

M言語では、関数本体は関数が初期化された環境に存在する変数を参照できます。

したがって AddTax は、rate = 1.1 を含む環境を参照するクロージャーとして理解できます。

3. each を理解するとMの関数型的な構造が見えてきます

Table.AddColumn
    ↓
関数を引数として受け取る
    ↓
高階関数
 
each
    ↓
1引数関数を簡潔に書く
 
_
    ↓
その関数の引数
 
外側の値も参照する
    ↓
クロージャー

each は単なるPower Query独特の便利記法ではありません。

M言語が、関数を値として扱え、関数を他の関数へ渡せ、関数が環境を参照できるという性質を持つことの上に成り立っている記法です。

第10章 実務での読み方

1. each を見たら一度展開します

each [単価] * [数量]

を見たら、頭の中で一度、

(_) => _[単価] * _[数量]

へ展開します。

さらに必要なら、

(row) => row[単価] * row[数量]

と読み換えます。

これだけで、each に関する多くの混乱を避けられます。

2. _ を見たら呼び出し元を確認します

_ だけを見て意味を決めてはいけません。

この each はどの関数へ渡されていますか
        ↓
その関数はコールバックへ何を渡しますか
        ↓
それが _ の実体です

代表例は次のとおりです。

呼び出し側 _ に渡されるもの
Table.AddColumn 行レコード
Table.SelectRows 行レコード
List.Transform リスト要素
List.Select リスト要素
Table.TransformColumns 対象列の値

3. each [列名] は二つの簡略化が重なっています

通常の関数は、

(row) => row[単価] * row[数量]

です。

第1段階として、1引数関数を each で書きます。

each _[単価] * _[数量]

第2段階として、暗黙のフィールド参照を使います。

each [単価] * [数量]

したがって、この短い式の裏には、

  • 関数があります。

  • 引数があります。

  • 引数は行レコードです。

  • レコードのフィールドを参照しています。

  • Table.AddColumn がその関数を各行について呼び出しています。

という構造があります。

第11章 まとめ

1. each の定義

each は、1個の引数 _ を持つ型指定なし関数を簡潔に記述するためのシンタックスシュガーです。

each _ + 1

は、

(_) => _ + 1

と同じ意味です。

2. _ の定義

_ は、each が作る1引数関数の引数名です。

_ が行レコード、数値、テキスト、リスト要素、セル値のどれになるかは、each ではなく、その関数の呼び出し側によって決まります。

3. [列名] の意味

行レコードを受け取る関数では、

_[単価]

を、

[単価]

という暗黙のフィールド参照で記述できます。

したがって、

each [単価]

は、

(_) => _[単価]

と意味的に等価です。

4. each が特にTable系関数で便利な理由

Table.AddColumn や Table.SelectRows では、

  • 1個の行レコードを引数として渡します。

  • 1引数関数なので each が使えます。

  • 引数がレコードなので [列名] と短く書けます。

という条件がそろいます。

そのため、

(row) => row[単価] * row[数量]

を、

each [単価] * [数量]

まで簡略化できます。

これが、each がPower Queryのテーブル処理と非常に相性よく設計されているように見える理由です。

実務で覚えておくこと

1. each はループ命令ではありません。

1引数の無名関数を作る構文です。

2. _ は「現在行」という意味ではありません。

その関数の1個の引数です。

3. _ が何になるかは呼び出し側が決めます。

Table.AddColumn なら行レコード、List.Transform ならリスト要素です。

4. each [単価] は二重に簡略化されています。

each [単価]

↓

each _[単価]

↓

(_) => _[単価]

↓

(row) => row[単価]

この変形を理解できれば、each を暗記する必要はありません。

出典メモ

  • Microsoft Learn『Power Query M formula language specification - Functions』 https://learn.microsoft.com/en-us/powerquery-m/m-spec-functions

  • Microsoft Learn『Basic concepts』 https://learn.microsoft.com/en-us/powerquery-m/m-spec-basic-concepts

  • Microsoft Learn『Power Query M formula language specification - Operators』 https://learn.microsoft.com/en-us/powerquery-m/m-spec-operators

  • Microsoft Learn『Power Query M formula language reference』 https://learn.microsoft.com/en-us/powerquery-m/