関数プログラミングのアプローチ (2)

参照透明

前回の続きを進める前に、関数的というものを定義しておく必要があるかと思います。関数的なプログラムとはどういうプログラムなのでしょうか?
関数的なプログラムとは参照透明性が確保されたプログラムのことで、参照透明とは

Referential transparency is a property of parts of computer programs. An expression is said to be referentially transparent if it can be replaced with its value without changing the program (in other words, yielding a program that has the same effects and output on the same input).
Wikipedia "Referential transparency"

ということで、次の2点が成立するように記述されたプログラムは関数的と言えると思います。

  • 同じ引数に適用した関数は、同じ結果を返す
  • 評価順序を変えても結果が変わらない

先のモンテカルロシミュレーションの例では、関数的でない部分は乱数生成器のところです。

# xorshift 128 bit
x, y, z, w, t = 123456789, 362436069, 521288629, 88675123, 1
def rand ():
    global x,y,z,w,t
    t=(x^(x<<11)) & 0xffffffff
    x=y & 0xffffffff
    y=z & 0xffffffff
    z=w & 0xffffffff
    w=(w^(w>>19))^(t^(t>>8)) & 0xffffffff
    return w

この関数は、評価するたびに違う値を返すので、参照透明ではないといえます。評価順序という観点で言うと、次の式を考えたとき

x,y = rand(),rand()

最初のrand()を評価してから次のrand()を評価したときと、2つめのrand()を評価してから1つめを評価したときでは、x,yの値が変わるので、参照透明ではないといえます。
そこで、この関数を参照透明であるように書き換えたうえで、プログラム全体をそれにあわせて書き換えていく必要があるのです。