Hi,

2010/11/30 Charles Oliver Nutter <headius / headius.com>:
> The global serial number approach in 1.9 means that any change that
> flip that serial number cause all caches everywhere to invalidate.
> Normally this only happens on method definition or module inclusion,
> which is why defining methods or including modules at runtime is
> strongly discouraged for performance reasons.

Sorry I'm not sure that I could follow your argument about performance,
so I may miss your point.

I guess that casual users will execute all refinements immediately after
program is started, like class definition and method definition.
Thus, the global serial number approach will work well for refinement
in main use cases, I think.
In the sense, nested function by using refinements may be a problem.


> And one last case that's a problem: author's intent. If I write a
> block of code that does "1 + 1", I intend for that code to do normal
> Fixnum#+, and I intend for the result to be 2. It should not be
> possible for a caller to change the intent of my code just because I
> passed it in a bock. This has been my argument against using blocks as
> bindings, and it's another argument against instance_eval being able
> to force refinments into "someone else's code".

This is not a problem, but rather improvement.  There is already open
class which so often breaks your intent.  Refinements may also break
your intent, but it is less often and more controllable than open class.


> Now, some positive reinforcement for "using" being a keyword and
> instance_eval not propagating refinements.

I'm not against your proposal, but I wonder if it does not make sense
because we can still write: eval("using FooExt")
To address your concern, `using' keyword should have a block:

  using FooExt
    # FooExt enabled
  end
  # FooExt disabled

I don't like this syntax because of more indentation, though.


> I can try to come up with a concrete example of the problems with the
> current proposal and implementation, but the concurrency cases would
> be difficult to show.

I might find serious concurrency problem of Shugo's patch, though I'm
not sure that this is what you mean.  Indeed, we may have to give up
propagating refinements via block.

  class C
    def test; p :test; end
  end
  module FooExt
    refine(C) { def test; p :foo; end }
  end
  module BarExt
    refine(C) { def test; p :bar; end }
  end
  f = proc do
    sleep 1
    C.new.test
  end
  FooExt.class_eval(&f)                    #=> :foo (expected)
  BarExt.class_eval(&f)                    #=> :bar (expected)
  [ Thread.new { FooExt.class_eval(&f) },  #=> :foo (expected)
    Thread.new { BarExt.class_eval(&f) }   #=> :foo (not expected)
  ].each {|t| t.join }

-- 
Yusuke Endoh <mame / tsg.ne.jp>