0Pricing
Lua Academy · レッスン

値としての関数

関数を保存して渡します。

「値としての関数」はCoddyKit上の無料Lua Academyレッスンです。 これはレッスン1/4です。 下記で完全なレッスンを無料で読むことができます。その後、ブラウザ内の組み込みコードエディタと24時間対応のAIチューターでハンズオン演習できます。 これはLua Academy学習パスの一部であり、ウェブとCoddyKitアプリ全体で進捗が同期されます。 Lua Academyコースには全4レッスンが含まれています。

関数は第一級の値

Luaでは、関数は第一級の値です。つまり、関数は単なるデータとして扱えます。変数に保存したり、別の関数に渡したり、関数から返したり、テーブルに格納したりできます。

この1つの考え方が、関数型プログラミングの基盤になります。関数を数値や文字列と同じように扱うことで、柔軟で再利用可能なツールを構築できます。

関数を変数に保存する

関数に付けた名前は、実際には関数の値を保持する変数にすぎません。その値を別の変数に自由に代入できます。

以下の2つの名前は同じ関数を指しているため、どちらを呼び出しても同じコードが実行されます。

local function greet(name)
  return "Hello, " .. name
end

local hi = greet
print(greet("Ada"))
print(hi("Lin"))

匿名関数

関数を作るために名前を付ける必要はありません。匿名関数はfunction ... end構文で記述し、値として直接使います。

匿名関数をローカル変数に代入する方法は、通常の関数定義と同じですが、インラインで記述します。

local square = function(x)
  return x * x
end

print(square(5))
print(square(9))

引数として関数を渡す

関数も値なので、別の関数に渡すことができます。別の関数を受け取る関数を高階関数と呼びます。

ここでのapplyは、実行する関数を渡されるまで、どのような処理を行うか知りません。

local function apply(f, x)
  return f(x)
end

local function double(n) return n * 2 end

print(apply(double, 10))
print(apply(function(n) return n + 1 end, 10))

関数を返す

関数から別の関数を返すことができます。これにより、渡された引数で設定された関数を必要に応じて作成できます。

以下のmultiplierは、呼び出すたびに新しい関数を作成し、指定された係数を保持します。

local function multiplier(factor)
  return function(x)
    return x * factor
  end
end

local triple = multiplier(3)
print(triple(4))
print(multiplier(10)(5))

クロージャは変数を捕捉する

返された関数が外側の関数にあるローカル変数を使うと、その変数を捕捉します。関数と捕捉した変数を組み合わせたものをクロージャと呼びます。

捕捉されたfactorは、外側の関数の呼び出しが終了した後も、クロージャが存在する間は保持されます。

local function counter()
  local n = 0
  return function()
    n = n + 1
    return n
  end
end

local next = counter()
print(next())
print(next())
print(next())

テーブルに関数を格納する

テーブルには、ほかの値と同じように関数を格納できます。Luaでモジュールやオブジェクトを構築できるのはこの仕組みのおかげです。テーブルで名前と関数の値を対応付けます。

キーを使って関数を検索して呼び出したり、操作を格納したテーブルを反復処理したりできます。

local ops = {
  add = function(a, b) return a + b end,
  sub = function(a, b) return a - b end
}

print(ops.add(2, 3))
print(ops["sub"](9, 4))

戦略をテーブルに格納する

関数をテーブルに格納すると、キーを使って実行時に動作を選択できます。これにより、長いif-elseの連鎖を分かりやすい検索処理に置き換えられます。

名前で操作を選択すれば、呼び出し側のコードを短く保ち、新しいキーにも簡単に対応できます。

local dispatch = {
  upper = string.upper,
  lower = string.lower,
  rev = string.reverse
}

local function run(name, s)
  return dispatch[name](s)
end

print(run("upper", "lua"))
print(run("rev", "lua"))

コールバック

コールバックとは、後で呼び出すために渡す関数です。Luaの標準ライブラリでもこのパターンが使われています。たとえば、table.sortは比較関数を受け取ります。

コールバックがルールを決め、ライブラリが反復処理や並べ替えを担当します。

local nums = {5, 2, 9, 1}
table.sort(nums, function(a, b)
  return a > b
end)

print(table.concat(nums, ", "))

関数には同一性がある

すべての関数の値は、それぞれ異なるオブジェクトです。同じコードを含んでいても、別々の関数リテラルが等しくなることはありません。

ただし、1つの関数を2つの変数に保存した場合は、両方の名前が同じ値を参照するため、等しいと判定されます。

local f = function() return 1 end
local g = function() return 1 end
local h = f

print(f == g)
print(f == h)

なぜ重要なのか

関数を値として扱うと、汎用的なツールを一度だけ作成し、渡す関数によって動作をカスタマイズできます。map、filter、部分適用、合成はすべてこの仕組みを利用しています。

このコースの以降の内容では、第一級関数とクロージャを基盤に、実用的なパターンを構築していきます。

確認問題

Luaにおける第一級関数の理解度を確認しましょう。

まとめ

Luaの関数は第一級の値です。変数やテーブルに保存したり、引数として渡したり、別の関数から返したりできます。

外側の関数のローカル変数を捕捉する関数を返すと、クロージャが作成されます。これらの考え方が、これから学ぶすべての関数型プログラミングのパターンの基盤になります。

よくある質問

「値としての関数」レッスンは無料ですか?

はい。「値としての関数」の完全なテキストはこのウェブで無料で読めます。インタラクティブに演習し(組み込みコードエディタと24時間対応のAIチューター)、Lua Academyコースの残りをアンロックするには、CoddyKit PROにアップグレードしてください。 Lua Academyコースには全4レッスンが含まれています。

「値としての関数」で何を学びますか?

関数を保存して渡します。 ブラウザで直接実行するハンズオンコードでLua Academyを演習し、24時間対応のAIチューターがレッスンを進める中での質問に答えます。

Lua Academyを始めるのに経験は必要ですか?

事前経験は必要ありません。CoddyKitのLua Academyは初級者から上級者向けに構成されているため、ここから始めるか最初から始めて、自分のペースで進むことができます。 これはレッスン1/4です。

「値としての関数」レッスンにはどのくらい時間がかかりますか?

ほとんどのCoddyKitレッスンは約5~10分かかります。各レッスンはコンパクトでインタラクティブなので、着実に進歩し、ウェブとアプリ全体で正確に前回の場所から再開できます。

このLua Academyレッスンでコードを書いて実行できますか?

はい。すべてのLua Academyレッスンに組み込みコードエディタが含まれているため、ブラウザでリアルコードを書いて実行し、即座のAIフィードバックを取得できます。ローカル設定は不要です。

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

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