Forum: Ruby-core Re: [ruby-trunk - Feature #4085] Refinements and nested methods

18a797893e6768e048c1d15429f96bb4?d=identicon&s=25 Shugo Maeda (Guest)
on 2012-11-30 04:00
(Received via mailing list)
Your mail seems to be failed to synced into bugs.ruby-lang.org, so I
reply by e-mail.

2012/11/30 Yukihiro Matsumoto <matz@ruby.or.jp>:
> |So, the current behavior of main.using need not be changed, right?
> |Technically, the current behavior of main.using is not file scope.
> |The scope of main.using is from the point where using is *called at runtime* to
the end of that file.
> |For example,
(snip)
> In that sense, I don't think we need to change the behavior.  What I
> meant by "file scope" was that refinement only available until end of
> the file.

I see.

> |* It may be better not to support nested module to simplify things.
> |  I think support for nested modules are important for refinement users, but
are not so important
> |  for refinement authors.
>
> I don't think nested modules are important.  We can drop them, at
> least for 2.0 to simplify things.

OK.

> |    end
> |  It may be better to limit refinement activation in refine blocks to
refinements to be defined by the refine blocks theselves, to simplify things. 
If
there's no refinement activation in refine blocks, recursive methods cannot be
defined, so the refinement to be defined should be activated at least.
>
> I am not sure if I understand you correctly.  I thought method look-up
> should be done in run-time.  So only I can say it that refinement M
> will be available in both refine blocks in the above example.

In the current implementation the activated refinement table of a
module is shared by the code in that module definition
including refine blocks using cref.
However, to limit refinement activation only in refine blocks, cref
can't be used for that purpose, so a little hack is needed.
I think it's possible, at least in CRuby, to store hidden table in a
module, and share that table in refine blocks.

> Fundamentally you cannot expect passing proc to lambda work correctly.
I see.

> |  using M2
> |  C.new.foo #=> ?
> |
> |I think it's better to just calls M2 and C, not M1, to simplify things.
> |super chain is too complex here.
>
> I was thinking of M2->M1->C, but M2->C is simpler and acceptable.

M2->M1->C may be possible, but I worry that it makes super chain more
complex.

> |it might be better not to call A and B.
> |
> |I'm starting to think it might be better to limit super to call only the
original method in the refined class to simplify the spec.
>
> So do you mean refined method appear only once in method look-up chain?

I mean that all refinements appear in the method lookup 1.blah, but
the only first found one is used, and succeeding super in C outside
the scope of using are not affected by other refinements A and B.
make sense?

> |For example,
> |
> |class X; def blah; puts 'X'; end
> |module A; refine(X) { def blah; puts 'A'; super; end }; end
> |module B; refine(X) { def blah; puts 'B'; super; end }; end
> |module C; refine(X) { def blah; puts 'C'; super; end }; end
> |using A; using B; using C
> |1.blah
>
> X.new.blah # <= do you mean X here?

Yes.

> |Only C and X is called in the above code.
> |At first, I thought that stacking refinements and super chain are useful for
aspect oriented programming.
> |But refinements have no local rebinding, so it might not be a real use case of
refinements.
>
> Fair enough. If we can warn users for conflicted refinements like
> above, it's even better.

I'd like to hear other opinions, especially Charles' one.
This topic is locked and can not be replied to.