5.1 関数の本質

関数は、入力を受け取り、処理し、結果を返します。

入力 → 関数 → 出力
def add(a: int, b: int) -> int:
    return a + b

関数を比較するときは、次を確認します。

引数の型
戻り値の型
デフォルト引数
可変長引数
名前付き引数
関数を値として扱えるか
外側の変数を捕捉できるか
副作用を持つか

5.2 第一級関数

関数を通常の値として扱える言語では、関数を変数へ代入したり、別の関数へ渡したりできます。

def double(value):
    return value * 2

operation = double
result = operation(10)

関数を引数として渡せます。

numbers = [1, 2, 3]

result = map(double, numbers)

これを第一級関数と呼びます。


5.3 高階関数

関数を受け取る、または関数を返す関数です。

def apply_twice(function, value):
    return function(function(value))
result = apply_twice(lambda x: x * 2, 3)
# 12

mapfilterreduceも高階関数です。


5.4 クロージャ

外側のスコープにある変数を保持する関数です。

def create_multiplier(factor):
    def multiply(value):
        return value * factor

    return multiply

double = create_multiplier(2)
print(double(10))

multiplyは、create_multiplierの実行終了後もfactorを保持します。

クロージャは次の用途で使われます。

コールバック
イベント処理
状態のカプセル化
非同期処理
関数型処理

5.5 純粋関数と副作用

純粋関数には二つの性質があります。

同じ入力なら必ず同じ出力を返す
外部状態を変更しない
def add(a, b):
    return a + b

副作用を持つ関数は、外部世界へ影響を与えます。

def save_user(user):
    database.insert(user)

代表的な副作用は次です。

ファイルの読み書き
データベース更新
ネットワーク通信
画面出力
グローバル変数変更
現在時刻や乱数への依存

副作用は必要ですが、計算部分と分離するとテストしやすくなります。