同じパターン変数による同値判定
各言語で試した結果は以下のとおり
Erlangの場合
できる
> case [1,1,1] of [X,X,X] -> "same"; _ -> "different" end. "same" > case [1,1,2] of [X,X,X] -> "same"; _ -> "different" end. "different"
Pureの場合
できる
> case [1,1,1] of [x,x,x] = "same"; _ = "different" end; "same" > case [1,1,2] of [x,x,x] = "same"; _ = "different" end; "different"
Prologの場合
できる
?- [1,1,1] = [X,X,X], write(same); write(different). same X = 1. ?- [1,1,2] = [X,X,X], write(same); write(different). different true.
Haskellの場合
ガード(|)が必要
Prelude> case [1,1,1] of {[x,x,x] -> "same"; _ -> "different"} Conflicting definitions for `x' In a case alternative Prelude> case [1,1,1] of {[x,y,z] | x==y && x==z -> "same"; _ -> "different"} "same" Prelude> case [1,1,2] of {[x,y,z] | x==y && x==z -> "same"; _ -> "different"} "different"
OCamlの場合
ガード(when)が必要
なお(|)は他の言語での(;)と同じ
# match [1,1,1] with [x,x,x] -> "same" | _ -> "different";; Error: Variable x is bound several times in this matching # match [1,1,1] with [x,y,z] when x==y && x==z -> "same" | _ -> "different";; - : string = "same" # match [1,1,2] with [x,y,z] when x==y && x==z -> "same" | _ -> "different";; - : string = "different"
Scalaの場合
ガード(if)が必要
scala> List(1,1,1) match {case List(x,x,x) => "same" case _ => "different"} <console>:5: error: x is already defined as value x scala> List(1,1,1) match {case List(x,y,z) if x==y && x==z > "same" case _ => "different"} res: java.lang.String = same scala> List(1,1,2) match {case List(x,y,z) if x==y && x==z > "same" case _ => "different"} res: java.lang.String = different
Gauche(util.match)の場合
述語パターン(? ...)が必要だが、述語パターン中でxを参照できないのがつらい。
苦し紛れに(apply =)を使ったが、もっと複雑な構造とマッチさせるときは使えない。
gosh> (use util.match) gosh> (match '(1 1 1) ((x y z) "same") (_ "different")) *** ERROR: Compile Error: duplicate variable in pattern ((x x x) "same") gosh> (match '(1 1 1) ((x (? (pa$ = x)) (? (pa$ = x))) "same") (_ "different")) *** ERROR: unbound variable: x gosh> (match '(1 1 1) ((? (pa$ apply =)) "same") (_ "different")) "same" gosh> (match '(1 1 2) ((? (pa$ apply =)) "same") (_ "different")) "different"
追記
こういうときは失敗継続が使える
gosh> (match '(1 1 1) ((x y z) (=> k) (if (= x y z) "same" (k))) (_ "different")) "same" gosh> (match '(1 1 2) ((x y z) (=> k) (if (= x y z) "same" (k))) (_ "different")) "different"
節が (pat (=> identifier) body …)の形式である場合、identifier は clause の失敗継続に束縛されます。これは引数をもたない手続きで、呼ばれると、あたかも、 pat の照合に失敗したかの如くマッチャーに戻り、match が残りの節について試行を続けます。それゆえ、body … 内部で追加のテストを実行することが可能で、もし、満足いくものでなければ、 (identifier) を呼ぶことで、照合結果を拒絶することができます。
http://practical-scheme.net/gauche/man/gauche-refj_164.html