Journal InTime


2012-04-01 (Sun) [長年日記]

_ Feature #6242: Ruby should support lists

RubyはLISPなのでリストをサポートするべきだというチケットを登録。

チケットに添付したパッチでは、Listというクラスを導入して、NilClassとConsをListのサブクラスにしている。

最初、%S(1 2 3)のような形でS式をサポートしようかと思ったけど、このネタ自体を思い付いたのが今日であまり時間もなかったので、 S[1, 2, 3]のような形でお茶を濁してしまった。

ちゃんとしたS式の代りにcons演算子を追加してみた。 Haskellではconsは:、MLやScalaでは::のようだが、Rubyだとどちらも使えないので苦肉の策で:::を使うことにした。 ポイントは右結合であるということで、

1 ::: 2 ::: 3 ::: nil

は、

1 ::: (2 ::: (3 ::: nil))

という意味になる。

もう一つのポイントは、右側のオペランドがレシーバに、左側のオペランドが引数になるということ(たしかScalaがそうしていたと思う)。 つまり、上の式は、

(nil.:::(3)).:::(2).:::(1)

という意味になる。 左側をレシーバにすると、Objectに:::メソッドを追加しないといけなくなるし、ユーザ定義のリストクラスを作った時に:::を使えない。

後でfoldl/foldrを追加して、foldl/foldrを使って+, flatten/concat, map, flat_map/concat_map, filter, length/size, sum, reverseなどのメソッドを定義してみたが、Ruby(というかCだけど)で関数プログラミングができてなかなか楽しかった。

Tags: Ruby