表参道.rb #27 での発表に一部誤りがあったので訂正と補足
発表から一週間以上経ってしまっているんですが、発表中の発言に一部誤りがあったので訂正と補足。
pattern-match を使っているコードを説明する時に
「pattern-match は using PatternMatch
をすることで match
と with
が使えるようになり〜」
と発言していたんですが、正しくは
「pattern-match は using PatternMatch
をすることで match
が使える」
でした。
pattern-match で使用している refinements では match
のみが影響して with
は関係ありませんでした。
では、なぜ with
を使うことが出来るのかというと with
を呼び出しているブロックは内部で #instance_eval
されているためです。
#instance_eval
を経由してブロックを呼び出すことで、評価するコンテキストが別になりブロック内で with
を呼び出せるようになります。
class Env def with puts "with" end end def match &block # instance_eval で block を評価することで # block 内で Env のインスタンスメソッドを呼び出すことが出来る Env.new.instance_eval &block end match { with with with } # output: # with # with # with
この辺りの内部実装はもう少し解説すべきでしたね…申し訳ありませんでした。
ちなみに個人的には #match
メソッドだけなら『Object#match
で refinements する』のではなくて『module_function
と定義して PatternMatch.match
みたいな呼び出し』でもいいかなーとは思います。
PatternMatch.
の部分が煩わしければ include PatternMatch
とでもしておけばいいですしね。
まあここら辺はどちらがよいのかを考えるのがむずかしいところ…作りての好みもありますし。