関数を合成する
変換を連鎖させます。
「関数を合成する」はCoddyKit上の無料Lua Academyレッスンです。 これはレッスン4/4です。 下記で完全なレッスンを無料で読むことができます。その後、ブラウザ内の組み込みコードエディタと24時間対応のAIチューターでハンズオン演習できます。 これはLua Academy学習パスの一部であり、ウェブとCoddyKitアプリ全体で進捗が同期されます。 Lua Academyコースには全4レッスンが含まれています。
関数合成とは
関数合成は、2つの関数を1つに組み合わせます。合成された関数は、入力を最初の関数に渡し、その結果を2番目の関数に渡します。
数学ではこれを f(g(x)) と表します。関数合成を使うと、小さく焦点を絞った関数から大きな変換処理を組み立てられます。
2つの関数を合成する
compose ヘルパーは2つの関数を受け取り、新しい関数を返します。これを呼び出すと、まず g が実行され、その結果が f に渡されます。
順序は重要です。内側の関数が先に実行され、その出力に対して外側の関数が実行されます。
local function compose(f, g)
return function(x)
return f(g(x))
end
end
local function inc(n) return n + 1 end
local function dbl(n) return n * 2 end
local incThenDouble = compose(dbl, inc)
print(incThenDouble(3))順序が重要
引数の順序を入れ替えると結果が変わります。compose(f, g) は、まず g を適用し、その後 f を適用するという意味です。
以下の例では、2倍してから1を加える場合と、1を加えてから2倍する場合で結果が異なることを示しています。
local function compose(f, g) return function(x) return f(g(x)) end end
local function inc(n) return n + 1 end
local function dbl(n) return n * 2 end
print(compose(dbl, inc)(3))
print(compose(inc, dbl)(3))文字列関数を合成する
関数合成は、文字列変換を含む、任意の単一引数関数で利用できます。トリミング、大文字・小文字の変換、反転などを1つの再利用可能な処理として連結できます。
ここでは reverse が先に実行され、その後 upper が実行されるため、大文字化された反転文字列になります。
local function compose(f, g) return function(x) return f(g(x)) end end
local shout = compose(string.upper, string.reverse)
print(shout("lua"))複数の関数を合成する
2つを超える関数を連結するには、可変長の composeAll を作成します。入れ子にした呼び出しと同じように、関数を右から左へ適用します。
ループは関数リストを後ろからたどり、値を各関数へ順に渡します。
local function composeAll(...)
local fns = {...}
return function(x)
for i = #fns, 1, -1 do
x = fns[i](x)
end
return x
end
end
local f = composeAll(function(n) return n + 1 end,
function(n) return n * 2 end,
function(n) return n - 3 end)
print(f(10))右から左へ
composeAll(a, b, c) では、右端の関数 c が最初に実行され、次に b、最後に a が実行されます。これは入れ子にした a(b(c(x))) という形と一致します。
順序を読み取るのは難しい場合があるため、左から右へ実行するパイプのほうを好む人もいます。
左から右へのパイプ
pipe は読み取る順序を逆にします。関数は記述した順に、左から右へ実行されます。データパイプラインでは、このほうが追いやすいと感じる人が多くいます。
ループは前から順に進み、現在の値に各関数を適用します。
local function pipe(...)
local fns = {...}
return function(x)
for i = 1, #fns do
x = fns[i](x)
end
return x
end
end
local process = pipe(function(n) return n + 1 end,
function(n) return n * 2 end)
print(process(5))読みやすさのためのパイプ
pipe を使うと、手順が実行順に上から下へ並びます。これにより、複数段階の変換処理をコード自体で説明できるようになります。
ここでは、文字列から接頭辞を取り除き、小文字に変換してから反転する処理を、実行される順に並べています。
local function pipe(...) local fns={...} return function(x) for i=1,#fns do x=fns[i](x) end return x end end
local transform = pipe(string.lower, string.reverse,
function(s) return "[" .. s .. "]" end)
print(transform("LUA"))クロージャとの関数合成
部分適用やクロージャによって作成した関数も合成できます。小さく特殊化した関数を作り、それらをつなぎ合わせます。
各要素を個別にテストできる一方で、合成によって全体の処理の流れを表現できます。
local function pipe(...) local fns={...} return function(x) for i=1,#fns do x=fns[i](x) end return x end end
local function adder(n) return function(x) return x + n end end
local function muller(n) return function(x) return x * n end end
local calc = pipe(adder(3), muller(10))
print(calc(2))関数合成とパイプライン
関数合成は、データパイプラインを支える接着剤のようなものです。呼び出しを深く入れ子にする代わりに、合成した関数に一度名前を付け、多くの入力に適用できます。
これは map と組み合わせると特に効果的です。合成した関数を、各要素に適用する変換処理として渡せます。
local function map(t, f) local o={} for i,v in ipairs(t) do o[i]=f(v) end return o end
local function compose(f, g) return function(x) return f(g(x)) end end
local step = compose(function(n) return n + 1 end, function(n) return n * n end)
local r = map({1, 2, 3, 4}, step)
print(table.concat(r, ", "))関数は小さく保つ
関数合成は、小さく単一の目的を持つ関数を活用します。それぞれが1つの役割を担い、それらを組み合わせることで、ロジックを書き直さずに複雑な動作を構成できます。
これが関数型設計の核心です。小さな関数の語彙を作り、それらを合成して大きな考えを表現します。
理解度チェック
答える前に、実行される順序を注意深く追ってください。
まとめ
関数合成では、ある関数の出力を次の関数へ渡すように関数を組み合わせます。compose(f, g) は右から左へ g、次に f を実行し、pipe は読みやすさを重視して左から右へ実行します。
composeAll と pipe を使うと、多数の小さな関数を明確なパイプラインへ連結できます。特に map と組み合わせると強力です。
よくある質問
「関数を合成する」レッスンは無料ですか?
はい。「関数を合成する」の完全なテキストはこのウェブで無料で読めます。インタラクティブに演習し(組み込みコードエディタと24時間対応のAIチューター)、Lua Academyコースの残りをアンロックするには、CoddyKit PROにアップグレードしてください。 Lua Academyコースには全4レッスンが含まれています。
「関数を合成する」で何を学びますか?
変換を連鎖させます。 ブラウザで直接実行するハンズオンコードでLua Academyを演習し、24時間対応のAIチューターがレッスンを進める中での質問に答えます。
Lua Academyを始めるのに経験は必要ですか?
事前経験は必要ありません。CoddyKitのLua Academyは初級者から上級者向けに構成されているため、ここから始めるか最初から始めて、自分のペースで進むことができます。 これはレッスン4/4です。
「関数を合成する」レッスンにはどのくらい時間がかかりますか?
ほとんどのCoddyKitレッスンは約5~10分かかります。各レッスンはコンパクトでインタラクティブなので、着実に進歩し、ウェブとアプリ全体で正確に前回の場所から再開できます。
このLua Academyレッスンでコードを書いて実行できますか?
はい。すべてのLua Academyレッスンに組み込みコードエディタが含まれているため、ブラウザでリアルコードを書いて実行し、即座のAIフィードバックを取得できます。ローカル設定は不要です。
このコースのすべてのレッスン
- 値としての関数
- map、filter、reduce
- 部分適用
- 関数を合成する