webエンジニアの日常

RubyやPython, JSなど、IT関連の記事を書いています

メタプログラミングで遊んでみた(1)

メタプログラミング

メタプログラミングRuby

メタプログラミングRuby

を読んで遊んでみたくなった。 また同じタイトルで書くことがあるかわからないけど、とりあえず(1)を付けてみた。

eachに名前を付けてみる

例えば以下のようなコード

array = [1, 2, 3, 4, 5]
array.each do |n|
  p n * 2
end

処理の中身を見ればeachの中で何をやっているか分かるけど、もっと複雑になると分かりにくい。 そこで、method_missingを使えば、「~をするeachですよ」という書き方が出来そうだったのでやってみた。

class Array
  def method_missing(name, &block)
    if !block.nil? && name =~ /^each_/
      each{|i| block.call(i)}
    else
      super
    end
  end
end

のようにmethod_missingメソッドを改造すると、以下の用に使える

array = [1, 2, 3, 4, 5]
array.each_multiple_for_3 do |n|
  p n * 3
end

=>
3
6
9
12
15

eachを実装してみる

blockについても詳しく書いてあったので、練習ついでにeachメソッドを自力で実装してみた。 yieldを使っていないのは、明示的に引数であるということが書いてある方が好みだから。

class Array
  def each(index: 0, &block)
    p "in each method"
    return if index == self.size
    block.call(self[index])
    each(index: index.next, &block)
  end
end


array = [1, 2, 3]
array.each do |i|
  p i
end

=>
"in each method"
1
"in each method"
2
"in each method"
3
"in each method"