From: "shugo (Shugo Maeda)" Date: 2012-11-02T12:04:27+09:00 Subject: [ruby-dev:46351] [ruby-trunk - Bug #7262] module extension (#include/#prepend) in refinements Issue #7262 has been updated by shugo (Shugo Maeda). matz (Yukihiro Matsumoto) wrote: > refinementの中でモジュールのincludeやprependがしたい(かつ、そのスコープの範囲内だけで有効にしたい)なんて思ったんですが、きっと困難ですよね。 > 「無理」と思ったら遠慮なくrejectしてください。 > > module Experiment > refine String do > include Enumerable > def foo; p :foo; end > end > end > > using Experiment > "foo".foo > "foo".each(&:p) # 以下では"refinement"はrefineのブロック中のselfになる匿名モジュールを指します。 Enumerableにはeachは定義されていないので、以下のようにしたいということでしょうか。 module Experiment refine String do include Enumerable def foo; p :foo; end def each; each_line; end end end using Experiment "foo".foo p "foo\nbar".map { |i| i.upcase } 実はinclude自体は使えるのですが、上のコードは今の仕様ではエラーになります。 $ ruby /tmp/t.rb :foo /tmp/t.rb:11:in `map': undefined method `each' for "foo\nbar":String (NoMethodError) from /tmp/t.rb:11:in `
' Enumerableのmap自体はrefinementが有効なスコープで呼べるのですが、 mapの中でeachを呼ぶ時にEnumerable#mapの中ではrefinementが有効で ないためeachが見つかりません。 まとめると、refinementに対してモジュールをincludeすることはできるが、 そのモジュールでTemplate Methodパターンを使用している場合、テンプレート メソッドがrefinementで定義されていてもincludeしたモジュールからは呼び 出すことができません。 これを許すようにしようと思うと、local rebindingが必要になってしまうと 思いますが、どうでしょうか。 ---------------------------------------- Bug #7262: module extension (#include/#prepend) in refinements https://bugs.ruby-lang.org/issues/7262#change-32204 Author: matz (Yukihiro Matsumoto) Status: Open Priority: Normal Assignee: shugo (Shugo Maeda) Category: core Target version: 2.0.0 ruby -v: ruby 2.0.0dev (2012-11-01 trunk 37415) [i486-linux] refinementの中でモジュールのincludeやprependがしたい(かつ、そのスコープの範囲内だけで有効にしたい)なんて思ったんですが、きっと困難ですよね。 「無理」と思ったら遠慮なくrejectしてください。 module Experiment refine String do include Enumerable def foo; p :foo; end end end using Experiment "foo".foo "foo".each(&:p) Matz. -- http://bugs.ruby-lang.org/