Concurrent Clean : 正格性について(2)
例を挙げて説明してみます。
lazy = x strict :: !a -> a strict a = a strict2 :: !(!a, !b) -> (!a, !b) strict2 (a, b) = (a, b) maketupple :: a b -> (a, b) maketupple a b = (a, b) idtupple :: !(a, b) -> (a, b) idtupple (a, b) = (a, b) 1: idtupple $ maketupple (strict lazy) (strict lazy) 2: idtupple $ strict2 $ maketupple lazy lazy
というようなことを書いたとして、xは正格評価されるかというと、そんなことはないんですね。
確かに、(strict x)が評価されるときには、xは正格評価されるのですが、(strict x)の値が必要になるまでは評価されないのです。
たとえば、1の式が評価されると、
idtupple $ maketupple (strict lazy) (strict lazy) idtupple ((strict lazy), (strict lazy)) ((strict lazy), (strict lazy))
となり、strict関数は評価されずに残るので、lazyは評価されません。
しかし、2の式では、
idtupple $ strict2 $ maketupple lazy lazy idtupple $ strict2 (lazy, lazy) idtupple $ strict2 (x, x) idtupple (x, x) (x, x)
と評価されて、xが出現します。
-
-
- -
-
ちなみに、idtuppleに正格性注釈が全くついていないと、1の評価結果は、
maketupple (strict lazy) (strict lazy)
になるし、2の評価結果は、
strict2 $ maketupple lazy lazy
になるだけです。