Forum: Ruby-dev [ruby-trunk - Bug #7262][Open] module extension (#include/#prepend) in refinements

Posted by matz (Yukihiro Matsumoto) (Guest)
on 2012-11-01 22:13
(Received via mailing list)
Issue #7262 has been reported by matz (Yukihiro Matsumoto).

----------------------------------------
Bug #7262: module extension (#include/#prepend) in refinements
https://bugs.ruby-lang.org/issues/7262

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.
Posted by shugo (Shugo Maeda) (Guest)
on 2012-11-02 04:04
(Received via mailing list)
Issue #7262 has been updated by shugo (Shugo Maeda).


matz (Yukihiro Matsumoto) wrote:
>   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 `<main>'

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.
Posted by Yukihiro Matsumoto (Guest)
on 2012-11-02 09:50
(Received via mailing list)
$B$^$D$b$H(B $B$f$-$R$m$G$9(B


In message "Re: [ruby-dev:46351] [ruby-trunk - Bug #7262] module 
extension (#include/#prepend) in refinements"
    on Fri, 2 Nov 2012 12:04:27 +0900, "shugo (Shugo Maeda)" 
<redmine@ruby-lang.org> writes:

|$B$^$H$a$k$H!"(Brefinement$B$KBP$7$F%b%8%e!<%k$r(Binclude$B$9$k$3$H$O$G$-$k$,!"(B
|$B$=$N%b%8%e!<%k$G(BTemplate Method$B%Q%?!<%s$r;HMQ$7$F$$$k>l9g!"%F%s%W%l!<%H(B
|$B%a%=%C%I$,(Brefinement$B$GDj5A$5$l$F$$$F$b(Binclude$B$7$?%b%8%e!<%k$+$i$O8F$S(B
|$B=P$9$3$H$,$G$-$^$;$s!#(B
|
|$B$3$l$r5v$9$h$&$K$7$h$&$H;W$&$H!"(Blocal rebinding$B$,I,MW$K$J$C$F$7$^$&$H(B
|$B;W$$$^$9$,!"$I$&$G$7$g$&$+!#(B

$B%m!<%+%k%j%P%$%s%G%#%s%0$O:NMQ$7$J$$$H$$$&$N$OBgA0Ds$H$7$F7h(B
$B$a$?$3$H$J$N$G!"$3$NE@$O<h$j2<$2$^$9!#%F%s%W%l!<%H%a%=%C%I%Q(B
$B%?!<%s$r4^$`$b$N$rNcBj$K$7$?$N$O<:GT$G$7$?$M!#(B

$B$H$$$&$3$H$O!"DL>o$N%a%=%C%I$rDI2C$9$k$@$1$G$"$l$P(Brefinement
$BFb$G$N(Binclude/prepend$B$O!"8=>u$N$^$^$GM-8z$G$"$k$H$$$&M}2r$G(B
$B@5$7$$$G$7$g$&$+!#@5$7$1$l$P!"$3$NDs0F$O(Bclose$B$7$F$/$@$5$$!#(B

                                $B$^$D$b$H(B $B$f$-$R$m(B /:|)
Posted by shugo (Shugo Maeda) (Guest)
on 2012-11-02 10:11
(Received via mailing list)
Issue #7262 has been updated by shugo (Shugo Maeda).


匿名ユーザ wrote:
>  ということは、通常のメソッドを追加するだけであればrefinement
>  内でのinclude/prependは、現状のままで有効であるという理解で
>  正しいでしょうか。正しければ、この提案はcloseしてください。

prependの方はちょっと変な挙動になっているようなので少し考えさせてください。

class C
  def foo
    [:C]
  end
end

module M1
  def foo
    super << :M1
  end
end

module M2
  def foo
    super << :M2
  end
end

module M3
  refine C do
    include M1
    prepend M2

    def foo
      super << :M3
    end
  end
end

using M3
p C.new.foo #=> [:C, :M1, :M3, :M2, :M3]

----------------------------------------
Bug #7262: module extension (#include/#prepend) in refinements
https://bugs.ruby-lang.org/issues/7262#change-32219

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.
Posted by shugo (Shugo Maeda) (Guest)
on 2012-11-02 10:12
(Received via mailing list)
Issue #7262 has been updated by shugo (Shugo Maeda).

Status changed from Open to Assigned


----------------------------------------
Bug #7262: module extension (#include/#prepend) in refinements
https://bugs.ruby-lang.org/issues/7262#change-32220

Author: matz (Yukihiro Matsumoto)
Status: Assigned
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.
Posted by shugo (Shugo Maeda) (Guest)
on 2012-12-12 23:22
(Received via mailing list)
Issue #7262 has been updated by shugo (Shugo Maeda).

Status changed from Assigned to Closed

r38298とr38328で対応したのでcloseします。
期待と違う動作だったらreopenしてください。 > まつもとさん

----------------------------------------
Bug #7262: module extension (#include/#prepend) in refinements
https://bugs.ruby-lang.org/issues/7262#change-34679

Author: matz (Yukihiro Matsumoto)
Status: Closed
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.
Please log in before posting. Registration is free and takes only a minute.
Existing account (Switch to SSL-encrypted connection)
NEW: Do you have a Google/GoogleMail or Yahoo account? No registration required!
Log in with Google account | Log in with Yahoo account
No account? Register here.