「@ で前のステップを参照する」とは何か
Power Query(M言語)で使われる @ は、「同じ名前のステップが“関数”として再定義されてしまったときに、元のステップ(値)を明示的に参照するための記号」です。 もう少し噛み砕くと、
「名前がかぶってしまったときに、“元のステップの値のほう”を指し示すための特別なラベル」
だと理解すると分かりやすくなります。
通常のクエリではあまり登場しませんが、
- ステップ名と関数名が同じになったとき
- 自動生成されたコードで「@ステップ名」が出てきたとき などに、「これ何?」となりがちなポイントです。
ここでは、初心者向けにステップバイステップで、 @ がどういう場面で使われ、何をしているのかを丁寧に解説していきます。
M言語の「ステップ」と「名前」の関係を整理する
let ~ in の中でステップは「名前付きの値」
Power Query の Mコードは、基本的に次のような形になっています。
let
Source = Excel.CurrentWorkbook(){[Name="売上"]}[Content],
Filtered = Table.SelectRows(Source, each [金額] > 1000),
Result = Table.Sort(Filtered, {{"金額", Order.Descending}})
in
Result
Power Queryここでの
SourceFilteredResult
は、それぞれ「名前付きの値」です。 M言語では、「名前=ステップ名」と「その中身の値」が1対1で対応していると考えてよいです。
通常は、この名前をそのまま後続のステップで参照します。
Table.SelectRows(Source, …)
Table.Sort(Filtered, …)
Power Queryこのときは、まだ @ は登場しません。
名前が「関数」として再定義されるとややこしくなる
問題が起きるのは、同じ名前を「関数」としても使ってしまったときです。
例として、次のようなコードを考えます。
let
Source = Excel.CurrentWorkbook(){[Name="売上"]}[Content],
// ここで Source という名前を「関数」として再定義してしまう
Source = (t as table) as table =>
Table.SelectRows(t, each [金額] > 1000),
Filtered = Source(Excel.CurrentWorkbook(){[Name="売上"]}[Content])
in
Filtered
Power Queryここでは、
- 最初の
Sourceは「売上テーブル」という値 - その後の
Sourceは「テーブルを受け取ってフィルタする関数」
という、同じ名前に別の意味を持たせてしまっている状態です。
このようなときに、「元の Source(売上テーブルのほう)を参照したい」となったらどうするか――そこで @ が登場します。
@ を使って「元のステップ」を参照する
@ステップ名 で「元の値」を指す
先ほどの例を、@ を使って書き直してみます。
let
Source = Excel.CurrentWorkbook(){[Name="売上"]}[Content],
// Source という名前を関数として再定義
Source = (t as table) as table =>
Table.SelectRows(t, each [金額] > 1000),
// @Source で「元のステップの Source(売上テーブル)」を参照
Filtered = Source(@Source)
in
Filtered
Power Queryここでのポイントは、
Source:今は「関数」@Source:元のステップのSource(売上テーブル)
という役割分担になっていることです。
@ステップ名 は、「関数として再定義される前の、そのステップ名が指していた元の値」を参照するための記号だと理解していただくと、挙動がスッと入ってきます。
ステップバイステップで「@ の必要になる場面」を理解する
ステップ1:名前の“上書き”が起きる状況をイメージする
M言語では、同じ let ブロックの中で同じ名前を再定義すると、 後から書いたほうが優先されます。
let
X = 1,
X = 2
in
X // 結果は 2
Power Queryこの「上書き」が、
- ステップ名(値)
- 関数名
の両方にまたがって起きると、 「元のステップを参照したいのに、今の名前は関数を指している」という状況になります。
そこで、「元のステップを指すための特別なラベル」として @ が用意されている、という流れです。
ステップ2:@ がないとどう困るか
先ほどの例で、@Source を使わずに書くとこうなります。
let
Source = Excel.CurrentWorkbook(){[Name="売上"]}[Content],
Source = (t as table) as table =>
Table.SelectRows(t, each [金額] > 1000),
Filtered = Source(Source)
in
Filtered
Power Queryここでの Source(Source) は、
- 関数
Sourceに - 引数として「関数
Source」を渡している
というおかしな状態になります。
本来やりたいのは、
- 関数
Sourceに - 引数として「元のステップの
Source(売上テーブル)」を渡す
ことなので、@Source が必要になるわけです。
ステップ3:自動生成コードで @ が出てきたときの読み方
Power Query が自動生成したコードの中に、 @ステップ名 が出てくることがあります。
そのときは、
「このステップ名は、どこかで関数としても使われていて、
@ステップ名は“元のステップの値のほう”を指しているんだな」
と読み解いていただくと、コードの意図が理解しやすくなります。
@ は「名前の衝突を解決するための安全装置」だと捉えると、 怖がらずに付き合えるようになります。
実務での @ の使いどころと注意点
1. 自分で積極的に使う場面は多くない
正直なところ、通常の実務クエリでは、 自分から積極的に @ を書く場面はあまり多くありません。
理由はシンプルで、
- ステップ名と関数名を同じにしない
- 名前の再定義を避ける
という方針で書いていけば、 そもそも @ が必要な状況を作らずに済むからです。
実務では、
Sourceは「元データ」FilterSalesは「フィルタ関数」TransformSalesは「変換関数」
というように、役割ごとに名前を分けておくほうが安全で読みやすいです。
2. それでも @ を理解しておくべき理由
それでも @ を理解しておくべきなのは、
- 自動生成されたコードに @ が出てくることがある
- 他の人が書いた高度な Mコードで @ が使われていることがある
- ライブラリ的な関数を作るときに、名前の衝突を避けるための知識として役立つ
といった理由からです。
「@ は、同じ名前の“元のステップ”を指すための記号」 という理解を持っているだけで、 コードを読むときの不安がかなり減ります。
3. セキュリティ・品質の観点からの注意
名前の再定義は、セキュリティや品質の観点からも注意が必要です。
- 元のステップ(生データ)と、加工後の関数が同じ名前だと、 どちらを参照しているのか分かりづらくなる
- 誤って関数のほうを参照してしまい、意図しない処理が走る可能性がある
- セキュリティチェック用の関数と、チェック対象のデータが同じ名前だと、レビューが難しくなる
そのため、
- ステップ名と関数名は意図的に分ける
- @ が必要になるような名前の衝突は、基本的に避ける
という方針が、実務では安全です。
@ は「最後の手段」であり、設計としては「使わなくて済むように名前を分ける」ほうが望ましいと考えていただくとよいです。
実務で使える @ の理解テンプレート
テンプレ1:元のステップと関数が同名になった例
let
Source = Excel.CurrentWorkbook(){[Name="売上"]}[Content],
Source = (t as table) as table =>
Table.SelectRows(t, each [金額] > 1000),
Filtered = Source(@Source)
in
Filtered
Power Queryテンプレ2:名前を分けて @ を不要にした例
let
Source = Excel.CurrentWorkbook(){[Name="売上"]}[Content],
FilterSales =
(t as table) as table =>
Table.SelectRows(t, each [金額] > 1000),
Filtered = FilterSales(Source)
in
Filtered
Power Queryまとめ:@ を理解することは「名前と値の関係」を理解すること
M言語で @ で前のステップを参照する というのは、 「同じ名前が“値”と“関数”の両方に使われてしまったときに、元のステップの値を明示的に指し示すための仕組み」だと整理できます。
ポイントは、
- ステップ名は「名前付きの値」
- 同じ名前を関数として再定義すると、元の値と関数が同名になる
@ステップ名は、そのうち「元のステップの値」のほうを参照するための記号- 実務では、名前を分けて設計することで、@ が必要な状況を避けるのが安全
ということです。
@ 自体を多用する必要はありませんが、 「@が出てきたら、名前の衝突が起きていて、元のステップを参照しているんだな」 と読み解けるようになっておくことは、 Power Query を深く理解し、他者のコードも安心して読めるようになるうえで、とても大きな意味があります。
