[ruby-core:69905] [CommonRuby - Feature #7747] Expanded API for Binding semantics

From: 2851820660@...
Date: 2015-07-09 05:10:15 UTC
List: ruby-core #69905
Issue #7747 has been updated by 11 22.


http://www.software-rating.com/
http://www.smartlogi.com/ =C2=A0
http://www.shareorder.com/=20=20
http://www.gzs168.com/ =C2=A0
http://www.aimooimage.com/=20=20=20=20
http://www.chinatowngate.net/

----------------------------------------
Feature #7747: Expanded API for Binding semantics
https://bugs.ruby-lang.org/issues/7747#change-53324

* Author: Joshua Ballanco
* Status: Open
* Priority: Normal
* Assignee:=20
----------------------------------------
=3Dbegin
Currently, the only way to create a new instance of Binding is to get a cop=
y of the current scope's binding, or ask some other object for its binding.=
 In either case, the binding object returned always has semantics identical=
 to the original binding. In other words, a binding object used with eval i=
s capable of (not necessarily an exhaustive list):

* redefining methods on the binding target
* defining new methods on the binding target
* getting/setting instance variables
* getting/creating new constants

This feature proposal would introduce a new mechanism for creating a bindin=
g and adjusting its relationship with the source binding. For example, if y=
ou have a class (({Foo})) defined like so:

    class Foo
      def say
        puts "hello!"
      end
    end

Then you would be able to create a new binding that ((*won't*)) propagate n=
ew definitions to the parent binding like so:

    new_binding =3D Binding.new(Foo)
    new_binding.propagate =3D false
    new_binding.eval("def shout; puts 'HI!'; end")
=20=20=20=20
    Foo.new.say #=3D> "hello!"
    Foo.new.shout #=3D> No Method Error
    new_binding.eval("Foo.new.say") #=3D> "hello"
    new_binding.eval("Foo.new.shout") #=3D> "HI!"

If, additionally, we introduce a way to merge or combine bindings, then thi=
s API could actually be used to implement refinements in pure Ruby like so =
(note I am also assuming that (({Binding#eval})) gains the ability to take =
a block):

    class Module
      def refine(klass, &block)
        @refined_bindings ||=3D {}
        refinement_binding =3D Binding.new(klass)
        refinement_binding.propagate =3D false
        refinement_binding.shadow =3D true
        refinement_binding.eval &block
        (@refined_bindings[self.name] ||=3D []) << refinement_binding
      end
=20=20=20=20
      def using(mod)
        @refined_bindings[mod].each { |refinement| self.binding.merge(refin=
ement) }
      end
    end

Following is the preliminary list of additional APIs I am tentatively propo=
sing (though I expect this to change with additional discussion):

* (({Binding.new(an_object)})) - creates a new Binding object that "inherit=
s" the binding of the argument; essentially equivalent to (({an_object.send=
(:binding).dup}))
* (({Binding#propagate}))/(({Binding#propagate=3D})) - boolean; determines =
whether new method, class, or Constant defs are propagated into the "parent=
" binding's scope
* (({Binding#shadow}))/(({Binding#shadow=3D})) - boolean; sets whether or n=
ot new values for existing methods/constants/variables can be set
* (({Binding#freeze})) - causes the Binding to capture all existing methods=
/constants/variables in scope at call time, and "disconnect" from the paren=
t binding, so that any updates to definitions or values are no longer refle=
cted into the "child" binding
* (({Binding#merge(other_binding)})) - combines the method/constant/variabl=
e bindings in (({other_binding})) with the receiver; effectively shadows th=
e "parent" of (({other_binding})) within the receiver binding
=3Dend




--=20
https://bugs.ruby-lang.org/

In This Thread