曇。
夜更ししてプロジェクト・オイラーで遊んでいる。Ruby のメソッドで時々欲しくなるのが、配列の最後を切り落とすメソッド。pop は切り落とした内容が返されてしまうので、切り落とされた配列の方が返って欲しいのである。
class Array def chop a = self.dup a.pop a end end p [0, 1, 2, 3].chop #=> [0, 1, 2]
あるいはこういう実装でもよい。 上よりこちらの方が短く書けていてかつ高機能のように見えるが、たぶん上の方が速い。と予想して計測してみたら、こちらの方が速かった(約1.3倍)。こっちにしよう。
class Array def chop(n=1) self[0, self.size - n] end end p ["a", "b", "c"].chop #=>["a", "b"] p [0, 1, 2, 3, 4, 5].chop(2) #=>[0, 1, 2, 3]
破壊的なメソッドを作ってもよいだろう。
class Array def chop!(n=1) self.replace(self[0, self.size - n]) end end a = [0, 1, 2, 3, 4, 5] a.chop!(2) p a #=>[0, 1, 2, 3]
Ruby はモンキーパッチが超簡単である。モンキーパッチはあまり勧められないという人もいるけれど、こういうのなら特に問題はないだろう。言語を楽に拡張するようで、僕は好きである。ただ、既存のメソッドにモンキーパッチを当てるというのはむずかしい。
※参考:分別のあるRubyモンキーパッチャーになるために
まてよ、
class Array def chop(n=1) self[0..(- 1 - n)] end end p [0, 1, 2, 3, 4, 5].chop(2) #=>[0, 1, 2, 3]
でいいのか。これなら別にメソッドなしでもいけるな。範囲演算子でマイナスを使うと。にゃんと、見落としていたね。おもしろいことに、これだと引数をマイナスにすれば、先頭から引数分(の絶対値)だけ残して末尾を切り落とすことになる。ってそんなの使う人がいないけれど。だって [0, 1, 2, 3, 4, 5][0, 2] で充分だからな。読みやすいかどうかだけだね。
p [0, 1, 2, 3, 4, 5].chop(-2) #=>[0, 1]
#
Python のリスト(Ruby の配列)のスライスを Ruby で実装するのに没頭(参照)。苦労した。(AM3:25)
スティーヴ・エリクソンを読む。あんまりにも暗い話。