関数型言語のパターンマッチはifやswitch/case文の代わりではあるが、仕組み的にはオーバーロードに近い気がする
変な事を書いてすみません。
タイトルからして訳が分からないと思うのですが、私が最近思っている、パターンマッチに関する考察です。
単純に、よくパターンマッチはifやswitch/case文を書かなくて済む。と言う話があるのですが、使っていくうちに、パターンマッチは単純なifやswitch/case文の置き換えでは無いと思う時があるのです。
例えば、mergesortを自作すると、以下のようになるのですが、ifやswitch/caseで同じように再帰で書こうとすると、結構ごちゃごちゃすると思います。
(まあ、その辺はオブジェクト指向的な別のやり方があると思いますが)
mergesort [] = [] mergesort [z] = [z] mergesort zs = merge (mergesort xs) (mergesort ys) where (xs,ys) = mysplitAt (mylength zs `div` 2) zs merge xs [] = xs merge [] ys = ys merge (x:xs) (y:ys) | x < y = x:merge xs (y:ys) merge (x:xs) (y:ys) = y:merge (x:xs) ys mytake 0 _ = [] mytake _ [] = [] mytake n (x:xs) = x:mytake (n - 1) xs mydrop 0 xs = xs mydrop _ [] = [] mydrop n (_:xs) = mydrop (n - 1) xs mysplitAt n xs = (mytake n xs, mydrop n xs) mylength = mylength' 0 where mylength' v [] = v mylength' v (_:xs) = mylength' (v + 1) xs
オブジェクト指向のオーバーロードと全く使い道が違うのは承知なのですが、こう、同じ関数名がズラズラ並ぶと、オーバーロードを引数の数だけじゃなく、値でも同名の違う関数(メソッド)を呼べるようにしたのがパターンマッチなんじゃないか?と、思ってしまう時があります。
まあ、パターンマッチは、あくまで「同じ型の違う値」で機能するので(そして、引数の数は同じじゃないといけないので)、本当に、概念的には全く違うんですけど・・・
仕組み的には、ifやswitch/case文よりも、近いものを何故かオーバーロードに感じてしまう私です。
そう言えば、LLだと型が無いからなのか、オーバーロード使った事ないですね・・・。
そもそも、コンパイラばかり使ってたので、LLの経験自体が少ないですが。