問題と実装例:https://qiita.com/sumim/items/f26902f2b813c075a619
以前
https://qiita.com/Nabetani/items/a02c922a21ce357b62da
に実装していたんだけど、sumim さんが「ついカッとなった」部分に対応するために再実装。
[
[:fizz, "Fizz", ->(x){ x%3==0 }],
[:buzz, "Buzz", ->(x){ x%5==0 }],
[:pezz, "Pezz", ->(x){ x%7==0 }],
[:hozz, "Aho", ->(x){ x.to_s.include?(?3)}],
].each do |name, text, proc|
Numeric.class_eval do
define_method name do
if proc[self]
text.dup.tap{ |x| # ここで dup しないと大変なことになる
this=self; # ここで this に受けるのがなんか悔しい
x.define_singleton_method( :val ){ this }
}
else
self
end
end
end
String.class_eval do
define_method name do
self.tap{ self << text if proc[self.val] }
end
end
end
基本的に同じ戦略で書けたのでちょっとホッとした。
「text.dup.tap
」の dup
がちょっとトリッキー。
ここでトリッキーになるのは、self << text
という具合に String
の副作用を利用しているから。
ここで +
の類ではなく副作用のある <<
を使っているのは、x.define_singleton_method
で生やしたメソッドを維持するため。
副作用のお陰で define_singleton_method
を二度書かずに済んでいる。
DRY でしょ?