上京エンジニアの葛藤

都会に染まる日々

Enumerable の メソッドを Ruby でいくつか再実装する

先日、銀座rails#9 にお邪魔したところ、とても興味深い LT を見ることができた

LT をされていたのは @okuramasafumi さんで、Enumerable モジュール内のメソッドを Ruby で再実装(ライブコーディング)し、どのメソッドを実装するのかもその場で募集して決めるという臨場感のある内容だった
ちなみに、LT 内では filter, zip の再実装が行われて、zip はあともう少しのところまでできていた

そして僕はこの LT に影響を受け一度自分で書いてみたので、こうしてこの記事を書いている

Enumerable とは

Enumerable は繰り返し処理を集めた組み込みライブラリで C言語で実装されている
繰り返し処理の便利メソッド群といったところだろうか
各メソッドの実装では全て each を用いて定義されているので、再実装する時には、each を用いて実装しなければならない

余談ですが、何て読むのがいいんですかね... イニューメラブル?
それとも イナメラブル?

Ruby 本体のソースはこれかな

Ruby で再実装

今回実装するのは以下の2つにした

  • select
  • find

それぞれ rubydocs のサンプルを元にテストコードを用意し、TDD で再実装してみた
テストが不足していることで考慮漏れなどがありそうで、ちょっと自信がない

github.com

select

select は、ブロック内の式で true と判定された要素の配列を返すメソッドである
また find_all, filter というエイリアスもある

Ruby で再実装したコードはこんな感じ

module Enumerable
  def my_select
    ary = []
    each do |item|
      if yield(item)
        ary << item
      end
    end
    ary
  end
end
  1. yield でブロックを呼び出す
  2. ブロック内の式で判定をして true の場合のみ 3の処理をする
    false の場合何もしない
  3. 新たに作成した配列に merge する
  4. 新たに作成した配列を返す

find

find は、ブロック内の式で true と判定された一番初めの要素を返すメソッドである
また detect というエイリアスもある

Ruby で再実装したコードはこんな感じ

module Enumerable
  def my_find
    each do |item|
      if yield(item)
        return item
      end
    end
    return nil
  end
end
  1. yield でブロックを呼び出す
  2. ブロック内の式で判定をして true の場合のみ該当の要素を即返す
    false の場合何もしない
  3. 存在しなければ nil を返す

まとめ

  • 簡単なメソッドを選んだのですぐに実装することができた

  • Ruby 始めてある程度書けるようになってきたけど、どう実装されているかよく分からんというレベル感で中級者に爪先だけ突っ込んでるぐらいの人には良さそうな課題だと感じた

  • この調子で他のメソッドも実装していきたい

ちなみにこの Ruby の再実装は Grow.rb という勉強会でやっているらしいので興味がある人は行ったほうがいい(自分も今度行く)
次は第二回目らしい
growrb.doorkeeper.jp

GitHubリポジトリもあった github.com