こちらを参考にしました。
EgisonはVer.4から構文が大きく変わったので書いたのですが、内容はほぼ同じです。
Egison とは?
Egison (エギソン) は強力なパターンマッチを特徴とするプログラミング言語です。
2011年に江木 聡志さんが東京大学大学院修士課程で開発を始めました。
インストール
公式サイトのドキュメントタブからインストール方法にたどり着けます。
Homebrew を使ったインストール
macOS で Homebrew を使っている方は
$ brew update
$ brew tap egison/egison
$ brew install egison egison-tutorial
でインストールできますが、ライブラリのディレクトリがおかしい様で、このままでは使えませんでした。
egisonは/usr/local/lib
にライブラリを探しに行く様ですが、homebrewでインストールしたら/opt/homebrew/lib/
にライブラリが入ります。(人によって違うかもしれません)
仕方ないので/usr/local/lib
にシンボリックリンクを貼ります。
cd /usr/local/lib
ln -s /opt/homebrew/lib/egison
egison-tutorialも同様の問題があるので、同様にシンボリックリンクを貼ります。
mkdir /usr/local/lib/egison-tutorial
cd /usr/local/lib/egison-tutorial
ln -s /opt/homebrew/lib/egison/lib
後は
$ egison
で Egison インタープリターが立ち上がります。
チュートリアルも使えます。
$ egison-tutorial
オンラインチュートリアルも使えます。
map 関数の例
haskellの場合
mymap :: (a -> b) -> [a] -> [b]
mymap _ [] = []
mymap f (x:xs) = f x : mymap f xs
*Main> mymap (*2) [2,3,4]
[4,6,8]
標準ライブラリにmapがあるので、ここではmymapとしています。
リストの先頭に対する関数適用と残りに対して再帰的に処理する事と、空リストの場合の記述を書いています。
haskellは宣言型プログラミング言語ではあるものの、これはやや手続き的な匂いがしますね。
egisonの場合
def mymap f xs :=
matchAll xs as list something with
| _ ++ $x :: _ -> f x
> mymap (* 2) [2,3,4]
[4, 6, 8]
listが空かどうかという場合分けをすることなく map を定義できています。
haskellより更に宣言的と言えるでしょう。
as
とwith
に挟まれた箇所をマッチャーと言います。
ここではlist something
がマッチャーで、なんらかのリストとしてパターンマッチします。
文字列のリストとしてパターンマッチするときは list string
のようにマッチャーを使い分けることができます。
adjacentMap の例
リストの隣接する 2 要素を二引数関数に渡していって、結果をリストで返す adjacentMap 関数です。
haskell では以下のようになるでしょうか。
adjacentMap :: (a -> a -> a) -> [a] -> [a]
adjacentMap _ [] = []
adjacentMap _ (_:[]) = []
adjacentMap f (x : y : zs) = f x y : adjacentMap f (y : zs)
*Main> adjacentMap (*) [1, 2, 3, 4, 5]
[2,6,12,20]
場合分けが増えてしまいますね。
一方、Egisonでは以下のようにより直感的です。
def adjacentMap f xs :=
matchAll xs as list something with
| _ ++ $x :: $y :: _ -> f x y
> adjacentMap (*) [1, 2, 3, 4, 5]
[2, 6, 12, 20]
もうちょっと複雑な例
↓こちらを参考
ポーカーの役判定
最初の2つのdef suit
とcard
がマッチャーで、トランプのカードに当たるデータをどのようにしてパターンマッチするのかを定義しています。
関数poker
で役を判定します。
この関数は一つの大きなマッチ式で定義されています。
ポーカーの役が全て簡潔なパターンで記述されています。
ストレートフラッシュ(同じスートで数字が連続する5枚のカードで構成された役)
[card $s $n, card #s #(n-1), card #s #(n-2), card #s #(n-3), card #s #(n-4)]
-> "Straight flush"
フルハウス(5枚の手札のうち3枚が同じ数字で、残り2枚もまた数字が揃っている役)
[card _ $m, card _ #m, card _ #m, card _ $n, card _ #n]
-> "Full house"
のように記述されています。
「手札のうち 3 枚の数字が m で残り 2 枚の数字が n ならフルハウス」と素直に読めると思います。