LWP | Power Query MのFunction.Fromはクロージャーなのか
LWP TECHNICAL ARTICLE | 169
Power Query MのFunction.Fromはクロージャーなのか
高階関数、関数アダプター、評価環境の違いから正確に分類する
Copyright © 2026 LWP 山中 一弘
本資料は、出典を明記いただければ、商用・非商用を問わず、ご自由に複製・改変・再配布していただけます。なお、著作権表示は改変せず、そのまま記載してご利用くださいますようお願いいたします。
記事要約
Function.Fromは、リストを1個受け取る関数を、指定したシグネチャを持つ関数へ適合させる高階関数です。呼び出し側から受け取った複数引数はリストにまとめられ、元の単項関数へ渡されます。
Function.Fromそのものをクロージャーと呼ぶのは正確ではありません。分類としては関数アダプターです。一方、戻り値の関数が元の関数を後から利用できる点は、Mのクロージャーと環境モデルで理解できます。
本記事の対象とゴール
想定読者
Function.Fromの用途を知りたい方
高階関数とクロージャーを区別したい方
関数のシグネチャを適合させる設計を学びたい方
本記事で得られること
Function.Fromの引数変換を説明できます。
関数アダプターとクロージャーを分類できます。
Function.Fromが適する場面と独自ラッパーが適する場面を判断できます。
目次
1. Function.From は何をしているのか
2. これは「関数アダプター」と考えると分かりやすい
3. Function.From は高階関数である
4. ではクロージャーとは何か
5. M 言語は正式にクロージャーを持っている
6. Function.From の戻り値は、なぜクロージャーのように見えるのか
7. ただし「Function.From = クロージャー」ではない
8. Function.From の面白いところは「関数型」まで指定する点
9. Function.From は Calling Convention の変換とも考えられる
10. 自分で書くとどうなるか
11. Function.From とクロージャーを結びつけると何が理解しやすくなるか
12. Expression.Evaluate の「環境」ともつながっている
13. #shared との関係
14. M は思った以上に関数型言語である
15. 最も単純な理解
16. 結論
はじめに
Power Query M には、次の関数がある。
Function.From(functionType as type, function as function) as function
Microsoft の説明では、Function.From は、
単項関数を受け取り
新しい関数を作り
新しい関数に渡された複数の引数をリスト化し
そのリストを元の単項関数へ渡す
ための関数である。
たとえば、
Function.From(
type function (a as number, b as number) as number,
List.Sum
)(2, 1)
は 3 を返す。
この動きを見ると、
これはクロージャーではないのか?
という疑問が生じる。
結論から言うと、
Function.From そのものを「クロージャー」と呼ぶのは少し違います。しかし、Function.From が生成する新しい関数は、元の関数を保持した関数値として理解できるため、クロージャーの考え方で捉えると非常に分かりやすくなります。
より正確には、Function.From は、
高階関数 + 関数アダプター + M のクロージャー/環境モデル
として理解するとよい。
1. Function.From は何をしているのか
まず Microsoft の例をそのまま構造化してみる。
Function.From(
type function (a as number, b as number) as number,
List.Sum
)(2, 1)
元の List.Sum は、
List.Sum({2, 1})
のように、リストを1つ受け取る関数である。
つまり概念的には、
List.Sum
↓
引数:1個
↓
{2, 1}
という呼び出しである。
ところが Function.From を使うと、
f(2, 1)
という2引数の関数として呼び出せる。
内部の意味を概念的に書けば、
f = (a, b) => List.Sum({a, b})
に近い。
つまり、
元の関数
List.Sum(list)
↑
│
Function.From
│
↓
新しい関数
f(a, b)
↓
{a, b}
↓
List.Sum({a, b})
である。
重要なのは、
Function.From が「既存関数の呼び出し規約を変える新しい関数」を作っている
ことである。
2. これは「関数アダプター」と考えると分かりやすい
Function.From の本質は、単なる関数呼び出しではない。
元の関数:
f(list)
を、
g(a, b, c, ...)
という別のインターフェースを持つ関数へ変換する。
つまり、
List を1個受け取る関数
↓
Function.From
↓
複数引数を受け取る関数
という変換である。
プログラミング一般の用語でいえば、
Adapter(アダプター)
に近い。
元の関数そのものを書き換えるのではなく、
元の関数を包み、別の呼び出し方を提供する関数
を作っている。
3. Function.From は高階関数である
高階関数とは、一般に、
関数を引数として受け取る
関数を戻り値として返す
のどちらか、または両方を行う関数である。
Function.From は、
Function.From(
functionType,
function
)
という形で関数を引数に取り、
結果として、
function
を返す。
したがって、明確に高階関数である。
概念的には、
MakeAdapter = (f) =>
(a, b) => f({a, b})
と同じ系列の処理である。
4. ではクロージャーとは何か
クロージャーを理解するには、
「関数」と「その関数が作られたときの環境」
を分けて考える必要がある。
典型例を示す。
let
MakeAdder = (x) =>
(y) => x + y,
Add10 = MakeAdder(10)
in
Add10(5)
結果は、
15
である。
ここで、
MakeAdder(10)
の実行はすでに終わっている。
それにもかかわらず、
Add10(5)
を後から実行すると、x = 10 を覚えている。
概念的には、
Add10
│
├─ 関数本体
│ (y) => x + y
│
└─ 保存された環境
x = 10
となっている。
この、
関数本体 + その関数が生成されたときの環境
という組み合わせがクロージャーである。
5. M 言語は正式にクロージャーを持っている
Power Query M の言語仕様では、関数は定義時の環境を参照できる。
つまり、
(x) => () => x
のような関数を作ると、内側の関数は外側の x を保持できる。
例:
let
Make = (x) => () => x,
F1 = Make(1),
F2 = Make(2),
Result = F1() + F2()
in
Result
結果は、
3
となる。
F1 は x = 1 を保持し、
F2 は x = 2 を保持している。
この点について M 言語仕様では、クロージャーと関数の評価環境が明示的に説明されている。
6. Function.From の戻り値は、なぜクロージャーのように見えるのか
たとえば、
let
Original = (list) => List.Sum(list),
Converted =
Function.From(
type function (a as number, b as number) as number,
Original
)
in
Converted(10, 20)
とする。
Converted は後から、
Converted(10, 20)
と呼び出される。
その時点でも、
Original
という元の関数を利用できなければならない。
概念的には、
Converted = (a, b) => Original({a, b})
と考えられる。
すると Converted は、
Converted
│
├─ 関数本体
│ (a, b) => Original({a, b})
│
└─ 環境
Original = 元の関数
という構造に見える。
これはまさにクロージャー的である。
7. ただし「Function.From = クロージャー」ではない
ここは用語を正確に分ける必要がある。
Function.From はクロージャーという種類の値そのものではない。
Function.From は、
関数を受け取り、新しい関数を作る高階関数
である。
その戻り値である新しい関数は、意味論的には元の関数を参照し続ける必要があるため、
クロージャーとして理解すると自然
である。
整理すると次のようになる。
| 概念 | 意味 |
|---|---|
| クロージャー | 関数本体と、それが作られた環境の組み合わせ |
| 高階関数 | 関数を受け取る、または関数を返す関数 |
| 関数アダプター | 既存関数を別のインターフェースで呼べるよう包む関数 |
| Function.From | 関数を受け取り、指定した関数型の新しい関数を作る高階関数 |
| Function.From の戻り値 | 元関数を利用するラッパー関数として、クロージャー的に理解できる |
したがって、
Function.From はクロージャーですか?
への最も正確な答えは、
「Function.From 自体はクロージャーではなく高階関数・関数アダプターである。ただし、生成される関数を理解するにはクロージャーのモデルが非常によく合う」
となる。
8. Function.From の面白いところは「関数型」まで指定する点
Function.From の第1引数は、
functionType
である。
たとえば、
type function (a as number, b as number) as number
を指定する。
つまり単に、
(a, b) => ...
という関数を作るだけではなく、
どのような引数名・引数型・戻り値型を持つ関数として公開するか
まで指定している。
例:
type function (
a as number,
b as number
) as number
これによって、
入力
a : number
b : number
出力
number
という関数インターフェースを作れる。
9. Function.From は Calling Convention の変換とも考えられる
より低レベルな見方をすると、Function.From は、
関数の呼び出し規約を変換している
とも考えられる。
元:
f({a, b, c})
変換後:
g(a, b, c)
つまり、
複数の引数
a
b
c
│
└─────────┐
↓
{a,b,c}
↓
元の単項関数
↓
結果
である。
この意味では、
Curry / Uncurry
Adapter
Wrapper
Closure
Higher-order function
など、関数型プログラミングで登場するいくつかの考え方に近い。
ただし Function.From は一般的なカリー化そのものではない。
複数の引数をリストへまとめて、単項関数へ渡す
という特定の変換である。
10. 自分で書くとどうなるか
たとえば、
Original = (list) => list{0} + list{1}
という関数がある。
これを自分で2引数関数へ変換するなら、
Converted = (a, b) => Original({a, b})
でよい。
全体では、
let
Original = (list) =>
list{0} + list{1},
Converted = (a, b) =>
Original({a, b})
in
Converted(2, 1)
結果:
3
Function.From を使うと、
let
Original = (list) =>
list{0} + list{1},
Converted =
Function.From(
type function (
a as number,
b as number
) as number,
Original
)
in
Converted(2, 1)
となる。
つまり Function.From は、
この種のラッパー関数生成を、型情報込みで一般化したもの
と理解できる。
11. Function.From とクロージャーを結びつけると何が理解しやすくなるか
ここまで理解すると、M の関数を単なる「処理の名前」として見る必要がなくなる。
関数そのものが値であり、
f = List.Sum
のように変数へ格納できる。
さらに、
MakeSomething(f)
のように関数を別の関数へ渡せる。
そして、
g = Function.From(..., f)
のように、新しい関数を生成できる。
その g は、後から実行されても元の f を利用できる。
つまり、
関数
↓
値として保持
↓
別の関数へ渡す
↓
新しい関数を生成
↓
生成時の環境を保持
↓
後から実行
という、典型的な関数型言語の世界になる。
12. Expression.Evaluate の「環境」ともつながっている
Power Query M を理解するとき、
Function.From
だけを見るより、
Expression.Evaluate
と並べるとさらに面白い。
Expression.Evaluate では、
Expression.Evaluate(
expression,
environment
)
として、評価時の環境を明示的に渡せる。
つまり M では、
式は「どの環境で評価するか」によって参照できる名前が変わる
という考え方が非常に明確に存在する。
一方、クロージャーでは、
関数が作られたときの環境を関数側が保持する
と考える。
概念的に並べると、
Expression.Evaluate
文字列の式
+
評価環境
↓
評価
Closure
関数本体
+
生成時の環境
↓
後から実行
となる。
両者は別の機能だが、
M における「式・関数・環境」の関係
を理解するという意味では強くつながっている。
13. #shared との関係
Power Query には、
#shared
という共有環境をレコードとして取得する仕組みもある。
たとえば、
Expression.Evaluate(
code,
#shared
)
とすれば、共有環境に存在する名前を使ってコードを評価できる。
さらに独自ライブラリ TLib を組み合わせれば、
Expression.Evaluate(
code,
Record.Combine({
#shared,
[TLib = TLib]
})
)
のようにできる。
ここでも、
環境を値として扱う
という M の特徴が見えてくる。
14. M は思った以上に関数型言語である
Power Query は GUI から利用することが多いため、
「Excel や Power BI のデータ加工スクリプト」
程度に見えることがある。
しかし M 言語そのものを見ると、
関数がファーストクラス値
高階関数
クロージャー
レキシカルスコープ
関数生成
型としての function
評価環境
再帰関数
レコード
遅延評価的な要素
など、かなり本格的な言語機能を持っている。
Function.From は、その特徴がよく見える関数の一つである。
15. 最も単純な理解
Function.From を最初に理解するときは、次の3段階で考えるとよい。
第1段階:関数変換
Listを受け取る関数
↓
Function.From
↓
複数引数を受け取る関数
第2段階:高階関数
関数を入力
↓
Function.From
↓
関数を出力
第3段階:クロージャー
生成された関数は、
新しい関数本体
+
元の関数を参照できる環境
を持つものとして理解できる。
16. 結論
Function.From は、
クロージャーそのものではない。
分類としては、
高階関数であり、既存関数のインターフェースを変換する関数アダプター
と考えるのが最も正確である。
しかし、その戻り値である新しい関数は、元の関数を後から利用できる必要があるため、
M のクロージャーと評価環境の仕組みを使った関数生成として理解すると非常に自然である。
したがって、
Function.From
=
高階関数
+
関数アダプター
+
クロージャー/環境モデル
という理解が実用的である。
そして、この理解をさらに進めると、
Expression.Evaluate
environment レコード
#shared
TLib のような共通ライブラリ
関数を値として扱う設計
まで、一つの「M における関数と環境」というテーマとしてつながってくる。
出典メモ
Microsoft Learn『Function.From』 https://learn.microsoft.com/en-us/powerquery-m/function-from
Microsoft Learn『Power Query M formula language specification - Functions』 https://learn.microsoft.com/en-us/powerquery-m/m-spec-functions
