0Pricing
Lua Academy · レッスン

関数を合成する

変換を連鎖させます。

「関数を合成する」は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フィードバックを取得できます。ローカル設定は不要です。

このコースのすべてのレッスン

  1. 値としての関数
  2. map、filter、reduce
  3. 部分適用
  4. 関数を合成する
← Lua Academyに戻る