束縛済み変数でパターンマッチングの続き

Erlangは絶賛勉強中であり、また新たな事実が発見された。
Erlangではマッチングに使うためのパターンを、無名関数でも複数書くことができる。
あと、束縛済み変数をマッチングのパターンに便利に使えるのは、新たにスコープが生成されないで複数のパターンが書けるときで、
それはreceive文しかないと思ったが、case文でも同じことができた。
説明不足で何を言っているか分からんという感じだと思われるので、Haskellの場合と比較しながらコードを書いてみる。
Haskellでcase文。

f x y = 
    case x of
        y -> True
        _ -> False

case文は独立したスコープを持つ。それにそもそも遅延評価が基本で、
Erlangのように逐次実行でだらだらと順番に束縛していく、ということはありえない。
case文のパターンに現れてるyは、外側の関数fの引数のyとは当然違う。
なので、fのcase文は最初のパターンが必ずマッチし、戻り値は必ずTrueになる。
遅延評価なので、fの引数は評価すらされない。

Main> f 1 2
True
Main> f 2 2
True
Main> f 4 3
True
Main> f (error "") (error "")
True

Erlangでは、case文は独立したスコープを持たない。
case文の一つ目のパターンにある変数Yは、外側の関数fの引数にすでに束縛されている。

 -module(md2).
 -export([f/2]).
f(X, Y) -> 
    case X of
        Y -> true;
        _ -> false
    end.

なので、case文の一つ目のパターンは、マッチしたりしなかったりする。

3> c(md2).
{ok,md2}
4> md2:f(1,2).
false
5> md2:f(2,2).
true

無名関数の場合は、独立したスコープを持ち、引数となっている変数名は、外側の環境の同じ名前の変数名を隠蔽して、
あらたな未束縛の変数扱いになる。なので、

 -module(md3).
 -export([f/1,g/1,g2/1,h/1]).

f(X) -> 
    fun
        (X) -> true;
        (_) -> false
    end.

上記のような定義だと、一つ目のパターンに必ずマッチする。

19> (md3:f(1))(2).
true
20> (md3:f(1))(1).
true

ガードを使えばもちろんできる。が、雑然とした感じ。これができるだけでも十分便利だが。

g(X) ->
    fun
        (Y) when Y =:= X -> true;
        (_) -> false
    end.

これだとマッチしたりしなかったり、が実現できる。

21> (md3:g(1))(2).
false
22> (md3:g(1))(1).
true

case文をつかうと、入れ子になってしまうが、ガードを使わなくてすむ。

g2(X) ->
    fun(Y) ->
        case Y of 
            X -> true;
            _ -> false
        end
    end.

動きは同じ。

21> (md3:g2(1))(2).
false
22> (md3:g2(1))(1).
true

次のような場合、Xに関しては隠蔽が起こらない。
ので、X=Yのところで、マッチに失敗しうる。
失敗すると、badmatchってことになる。

h(X) ->
    fun 
        (Y) -> X = Y;
        (_) -> false
    end.
23> (md3:h(1))(1).
1
24> (md3:h(1))(2).
 =ERROR REPORT==== 20-Mar-2008::00:41:26 ===
 Error in process <0.30.0> with exit value: {{badmatch,2},[{md3,'-h/1-fun-0-',2},
 {shell,exprs,6},{shell,eval_loop,3}]}
 ** exited: {{badmatch,2},
             [{md3,'-h/1-fun-0-',2},{shell,exprs,6},{shell,eval_loop,3}]} **

Erlangの変数の仕組みは、癖があるけど面白い。
こういうタイプの言語って他にもあるんだろうか?