override.rb

Discussion in 'Ruby' started by ara.t.howard@noaa.gov, Dec 28, 2006.

  1. Guest

    since the threads split all over the place i figured i'd start yet another.
    can people break this?


    harp:~ > cat a.rb
    class Module
    module OverRiding
    class << self
    def new
    Module.new{
    @added_methods = []
    @parent = nil

    class << self
    attr :added_methods
    attr :parent

    def method_added m
    super if defined? super
    ensure
    added_methods << m.to_s
    end

    def remove_method m
    super if defined? super
    ensure
    added_methods.delete_at(added_methods.rindex(m.to_s)) rescue nil
    end

    def add_parent m
    include(@parent = m)
    end

    def cache mname, m
    mname = mname.to_s
    const = mname.gsub(%r/[!]/,'__bang__').gsub(%r/[?]/,'__what__').upcase
    const_set const, m

    module_eval <<-code
    def #{ mname } *a, &b
    #{ const }.bind(self).call *a, &b
    end
    code
    end

    def walking_up
    m = self
    loop{
    yield m
    break unless((m=m.parent) rescue nil)
    }
    end
    end
    }
    end
    end
    end

    def overriding &b
    this = self
    m = OverRiding.new
    m.module_eval &b

    unless defined? @overriding
    @overriding = OverRiding.new
    m.added_methods.each do |mname|
    @overriding.cache mname, this.instance_method(mname)
    this.remove_method mname
    end
    end

    m.add_parent @overriding
    include m
    @overriding = m
    end
    alias_method 'override', 'overriding'

    def restore mname
    if defined? @overriding
    mname = mname.to_s
    @overriding.walking_up do |m|
    break( m.remove_method mname ) if m.added_methods.include?(mname)
    end
    end
    instance_method mname
    end

    def restoring *a, &b
    o = Object.new
    sc = class << o; self; end
    sc.module_eval{
    instance_methods.each{|m| remove_method m unless m[/^__/] rescue nil}
    define_method('method_missing'){|m, *a| a << m }
    }
    o.instance_eval &b
    a.flatten.compact.each{|m| restore m}
    end
    end




    if $0 == __FILE__
    class C
    c = new

    def m() 'a' end
    p c.m #=> 'a'

    override{ def m() super + 'b' end }
    p c.m #=> 'ab'

    override{ def m() super + 'c' end }
    p c.m #=> 'abc'

    override{ def m() super + 'd' end }
    p c.m #=> 'abcd'

    restore 'm'
    p c.m #=> 'abc'

    restore 'm'
    p c.m #=> 'ab'

    restore 'm'
    p c.m #=> 'a'
    end
    end


    harp:~ > ruby a.rb
    "a"
    "ab"
    "abc"
    "abcd"
    "abc"
    "ab"
    "a"


    -a
    --
    if you find yourself slandering anybody, first imagine that your mouth is
    filled with excrement. it will break you of the habit quickly enough. - the
    dalai lama
     
    , Dec 28, 2006
    #1
    1. Advertising

  2. Holy cow!

    Tell me, what do you want us to do with this, exactly? What are you
    challenging us to? Didn't get it. =/

    On 12/28/06, <> wrote:
    >
    > since the threads split all over the place i figured i'd start yet another.
    > can people break this?
    >
    >
    > harp:~ > cat a.rb
    > class Module
    > module OverRiding
    > class << self
    > def new
    > Module.new{
    > @added_methods = []
    > @parent = nil
    >
    > class << self
    > attr :added_methods
    > attr :parent
    >
    > def method_added m
    > super if defined? super
    > ensure
    > added_methods << m.to_s
    > end
    >
    > def remove_method m
    > super if defined? super
    > ensure
    > added_methods.delete_at(added_methods.rindex(m.to_s)) rescue nil
    > end
    >
    > def add_parent m
    > include(@parent = m)
    > end
    >
    > def cache mname, m
    > mname = mname.to_s
    > const = mname.gsub(%r/[!]/,'__bang__').gsub(%r/[?]/,'__what__').upcase
    > const_set const, m
    >
    > module_eval <<-code
    > def #{ mname } *a, &b
    > #{ const }.bind(self).call *a, &b
    > end
    > code
    > end
    >
    > def walking_up
    > m = self
    > loop{
    > yield m
    > break unless((m=m.parent) rescue nil)
    > }
    > end
    > end
    > }
    > end
    > end
    > end
    >
    > def overriding &b
    > this = self
    > m = OverRiding.new
    > m.module_eval &b
    >
    > unless defined? @overriding
    > @overriding = OverRiding.new
    > m.added_methods.each do |mname|
    > @overriding.cache mname, this.instance_method(mname)
    > this.remove_method mname
    > end
    > end
    >
    > m.add_parent @overriding
    > include m
    > @overriding = m
    > end
    > alias_method 'override', 'overriding'
    >
    > def restore mname
    > if defined? @overriding
    > mname = mname.to_s
    > @overriding.walking_up do |m|
    > break( m.remove_method mname ) if m.added_methods.include?(mname)
    > end
    > end
    > instance_method mname
    > end
    >
    > def restoring *a, &b
    > o = Object.new
    > sc = class << o; self; end
    > sc.module_eval{
    > instance_methods.each{|m| remove_method m unless m[/^__/] rescue nil}
    > define_method('method_missing'){|m, *a| a << m }
    > }
    > o.instance_eval &b
    > a.flatten.compact.each{|m| restore m}
    > end
    > end
    >
    >
    >
    >
    > if $0 == __FILE__
    > class C
    > c = new
    >
    > def m() 'a' end
    > p c.m #=> 'a'
    >
    > override{ def m() super + 'b' end }
    > p c.m #=> 'ab'
    >
    > override{ def m() super + 'c' end }
    > p c.m #=> 'abc'
    >
    > override{ def m() super + 'd' end }
    > p c.m #=> 'abcd'
    >
    > restore 'm'
    > p c.m #=> 'abc'
    >
    > restore 'm'
    > p c.m #=> 'ab'
    >
    > restore 'm'
    > p c.m #=> 'a'
    > end
    > end
    >
    >
    > harp:~ > ruby a.rb
    > "a"
    > "ab"
    > "abc"
    > "abcd"
    > "abc"
    > "ab"
    > "a"
    >
    >
    > -a
    > --
    > if you find yourself slandering anybody, first imagine that your mouth is
    > filled with excrement. it will break you of the habit quickly enough. - the
    > dalai lama
    >
    >
     
    Paulo Köch, Dec 28, 2006
    #2
    1. Advertising

  3. Trans Guest

    Ara wrote:
    > since the threads split all over the place i figured i'd start yet another.
    > can people break this?


    Interesting. I'll take a closer look at this tomorrow. In some ways it
    is similar to #instance_intercept which I've been working on:

    # = Instance Interception
    #
    # This code is in the spirit of class_extension, but performs instance
    # level method interception instead of class level method inheritance.

    class Module

    def instance_interception(&block)
    @instance_interception ||= Module.new do
    def self.append_features(mod)
    append_features_without_instance_interception( mod )
    end
    end
    @instance_interception.module_eval(&block) if block_given?
    @instance_interception
    end

    private :instance_interception

    alias_method :append_features_without_instance_interception,
    :append_features

    # Append features

    def append_features( mod )

    aspect = instance_interception
    aspect.__send__( :append_features_without_instance_interception,
    mod )

    aspect.instance_methods.each do |meth|
    if mod.method_defined?( meth )
    aspect.advise( mod, meth )
    end
    end

    append_features_without_instance_interception( mod )

    #if mod.instance_of? Module
    aspect.__send__( :append_features_without_instance_interception,
    mod.__send__:)instance_interception) )
    #end

    end

    # Apply the around advice.

    def advise( mod, meth )
    advice = instance_method( meth )
    instance_target = mod.instance_method(meth)
    mod.__send__( :define_method, meth ) { |*args| #, &blk|
    target = instance_target.bind( self )
    (class << target; self; end).class_eval { define_method( :super
    ){ call( *args ) } }
    advice.bind( self ).call( target, *args ) #, &blk )
    }
    end

    # TODO make method_added hook more robust so not aas to clobber
    others.
    # If a method is added to the module/class that is advised.

    def method_added( meth )
    return if @method_added_short
    if instance_interception.method_defined?( meth )
    include instance_interception
    @method_added_short = true
    instance_interception.advise( self, meth )
    @method_added_short = false
    end
    end

    end



    =begin test

    require 'test/unit'

    class TestModule < Test::Unit::TestCase

    module A

    def f ; "F" ; end
    def g ; "G" ; end

    instance_interception do
    def f( target, *args, &blk )
    '{' + target.super + '}'
    end
    def g( target, *args, &blk )
    '{' + target.super + '}'
    end
    end

    end

    class X
    def f ; super ; end
    include A
    def g ; super ; end
    end

    def test_1_01
    x = X.new
    assert_equal( "{F}", x.f )
    assert_equal( "{G}", x.g )
    end

    end

    =end
     
    Trans, Dec 28, 2006
    #3
  4. Guest

    On Thu, 28 Dec 2006, [UTF-8] Paulo K=C3=B6ch wrote:

    > Holy cow!
    >
    > Tell me, what do you want us to do with this, exactly? What are you
    > challenging us to? Didn't get it. =3D/
    >


    it is a candidate release which addresses both these threads:

    http://groups-beta.google.com/group/comp.lang.ruby/browse_frm/thread/a80=
    cd271e6896aab/8f728cbad498d432?lnk=3Draot#8f728cbad498d432

    http://groups-beta.google.com/group/comp.lang.ruby/browse_frm/thread/3f9=
    4b778d65045be/a25b7705ea5da80f#a25b7705ea5da80f


    afaikt it it the most flexible and complete solution. unless someone point=
    s
    out a flaw i'll gem it up tomorrow.

    regards.

    -a
    --=20
    if you find yourself slandering anybody, first imagine that your mouth is
    filled with excrement. it will break you of the habit quickly enough. - th=
    e
    dalai lama
     
    , Dec 28, 2006
    #4
  5. Pit Capitain Guest

    schrieb:
    > (... code to override and restore methods ...)


    Ara, though I find this very interesting I've not much time to figure it
    out myself, so could you please show us an example with #overriding and
    #restoring ?

    > can people break this?


    What do you mean by "break"?

    Regards,
    Pit
     
    Pit Capitain, Dec 28, 2006
    #5
  6. wrote:
    > since the threads split all over the place i figured i'd start yet another.
    > can people break this?

    well... yes! i ran it, and got:
    "a"
    a.rb:63:in `override': private method `remove_method' called for C:Class
    (NoMethodError)
    from a.rb:61:in `each'
    from a.rb:61:in `override'
    from a.rb:102

    then, once I fixed that:

    $ cat b.rb
    require 'a'

    class C
    c = new

    def M; 'a' end
    def m; 'A' end
    p c.M(), c.m

    override { def M; super + 'b' end; def m; super + 'B' end }
    p c.M(), c.m

    restore 'M'
    p c.M(), c.m

    restore 'm'
    p c.M(), c.m
    end

    $ ruby b.rb
    "a"
    "A"
    /a.rb:32: warning: already initialized constant M
    "Ab"
    "AB"
    "A"
    "AB"
    "A"
    "A"

    This code's a lot longer than the last one you sent, so it's gonna take
    me more time to figure it out.

    Devin
     
    Devin Mullins, Dec 28, 2006
    #6
  7. Guest

    Hi --

    On Fri, 29 Dec 2006, wrote:

    Whoops, it's one of those messages that won't quote back the text. Oh
    well :) All I wanted to ask was: do you think 'override' is the best
    name for this? The reason I ask is that "require 'override'" sounds
    like you're importing override ability into Ruby, without any
    indication of the enhancements that the package provides (i.e., the
    restoring ability).


    David

    --
    Q. What is THE Ruby book for Rails developers?
    A. RUBY FOR RAILS by David A. Black (http://www.manning.com/black)
    (See what readers are saying! http://www.rubypal.com/r4rrevs.pdf)
    Q. Where can I get Ruby/Rails on-site training, consulting, coaching?
    A. Ruby Power and Light, LLC (http://www.rubypal.com)
     
    , Dec 28, 2006
    #7
  8. Guest

    ---1400102478-551175305-1167325293=:5000
    Content-Type: MULTIPART/MIXED; BOUNDARY="-1400102478-551175305-1167325293=:5000"

    This message is in MIME format. The first part should be readable text,
    while the remaining parts are likely unreadable without MIME-aware tools.

    ---1400102478-551175305-1167325293=:5000
    Content-Type: TEXT/PLAIN; charset=US-ASCII; format=flowed

    On Thu, 28 Dec 2006, Devin Mullins wrote:

    > wrote:
    >> since the threads split all over the place i figured i'd start yet another.
    >> can people break this?

    > well... yes! i ran it, and got:
    > "a"
    > a.rb:63:in `override': private method `remove_method' called for C:Class
    > (NoMethodError)
    > from a.rb:61:in `each'
    > from a.rb:61:in `override'
    > from a.rb:102


    how odd. which ruby version?

    > then, once I fixed that:
    >
    > $ cat b.rb
    > require 'a'
    >
    > class C
    > c = new
    >
    > def M; 'a' end
    > def m; 'A' end
    > p c.M(), c.m
    >
    > override { def M; super + 'b' end; def m; super + 'B' end }
    > p c.M(), c.m
    >
    > restore 'M'
    > p c.M(), c.m
    >
    > restore 'm'
    > p c.M(), c.m
    > end
    >
    > $ ruby b.rb
    > "a"
    > "A"
    > ./a.rb:32: warning: already initialized constant M


    hmmm. i reworked to use a single constant table of methods.


    latest below and attached.

    -a
    --
    if you find yourself slandering anybody, first imagine that your mouth is
    filled with excrement. it will break you of the habit quickly enough. - the
    dalai lama


    class Module
    module OverRiding
    class << self
    def new
    Module.new{
    @added_methods = []
    @parent = nil

    class << self
    attr :added_methods
    attr :parent

    def method_added m
    super if defined? super
    ensure
    added_methods << m.to_s
    end

    def delete_method m
    remove_method m
    added_methods.delete_at(added_methods.rindex(m.to_s))
    end

    def add_parent m
    include(@parent = m)
    end

    def cache mname, m
    mname = mname.to_s
    const_set :METHODS____, {} unless const_defined? :METHODS____
    const_get:)METHODS____)[ mname ] = m
    module_eval <<-code
    def #{ mname } *a, &b
    METHODS____[ '#{ mname }' ].bind(self).call *a, &b
    end
    code
    end

    def walking_up
    m = self
    loop{
    yield m
    break unless((m=m.parent) rescue nil)
    }
    end
    end
    }
    end
    end
    end

    def overriding &b
    this = self
    m = OverRiding.new
    m.module_eval &b

    unless defined? @overriding
    @overriding = OverRiding.new
    m.added_methods.each do |mname|
    @overriding.cache mname, this.instance_method(mname)
    remove_method mname
    end
    end

    m.add_parent @overriding
    include m
    @overriding = m
    end
    alias_method 'override', 'overriding'

    def restoring *_a, &_b
    if _b # barewords will restore methods
    o = Object.new
    sc = class << o; self; end
    sc.module_eval{
    instance_methods.each{|m| remove_method m unless m[/^__/] rescue nil}
    define_method('method_missing'){|__m, *__a| _a << __m; self }
    }
    o.instance_eval &_b
    end
    _a.flatten.compact.map do |mname|
    if defined? @overriding
    mname = mname.to_s
    @overriding.walking_up do |m|
    break( m.delete_method mname ) if m.added_methods.include?(mname)
    end
    end
    instance_method mname
    end
    end
    alias_method 'restore', 'restoring'
    end




    if $0 == __FILE__

    class C
    c = new

    def m() 'a' end
    p c.m #=> 'a'

    override{ def m() super + 'b' end }
    p c.m #=> 'ab'

    override{ def m() super + 'c' end }
    p c.m #=> 'abc'

    override{ def m() super + 'd' end }
    p c.m #=> 'abcd'

    restore 'm'
    p c.m #=> 'abc'

    restore 'm'
    p c.m #=> 'ab'

    restore 'm'
    p c.m #=> 'a'
    end

    end
    ---1400102478-551175305-1167325293=:5000
    Content-Type: TEXT/PLAIN; charset=US-ASCII; name=override.rb
    Content-Transfer-Encoding: BASE64
    Content-ID: <>
    Content-Description:
    Content-Disposition: attachment; filename=override.rb

    Y2xhc3MgTW9kdWxlDQogIG1vZHVsZSBPdmVyUmlkaW5nDQogICAgY2xhc3Mg
    PDwgc2VsZg0KICAgICAgZGVmIG5ldw0KICAgICAgICBNb2R1bGUubmV3eyAN
    CiAgICAgICAgICBAYWRkZWRfbWV0aG9kcyA9IFtdIA0KICAgICAgICAgIEBw
    YXJlbnQgPSBuaWwNCg0KICAgICAgICAgIGNsYXNzIDw8IHNlbGYNCiAgICAg
    ICAgICAgIGF0dHIgOmFkZGVkX21ldGhvZHMNCiAgICAgICAgICAgIGF0dHIg
    OnBhcmVudA0KDQogICAgICAgICAgICBkZWYgbWV0aG9kX2FkZGVkIG0NCiAg
    ICAgICAgICAgICAgc3VwZXIgaWYgZGVmaW5lZD8gc3VwZXINCiAgICAgICAg
    ICAgIGVuc3VyZQ0KICAgICAgICAgICAgICBhZGRlZF9tZXRob2RzIDw8IG0u
    dG9fcw0KICAgICAgICAgICAgZW5kDQoNCiAgICAgICAgICAgIGRlZiBkZWxl
    dGVfbWV0aG9kIG0NCiAgICAgICAgICAgICAgcmVtb3ZlX21ldGhvZCBtDQog
    ICAgICAgICAgICAgIGFkZGVkX21ldGhvZHMuZGVsZXRlX2F0KGFkZGVkX21l
    dGhvZHMucmluZGV4KG0udG9fcykpDQogICAgICAgICAgICBlbmQNCg0KICAg
    ICAgICAgICAgZGVmIGFkZF9wYXJlbnQgbQ0KICAgICAgICAgICAgICBpbmNs
    dWRlKEBwYXJlbnQgPSBtKQ0KICAgICAgICAgICAgZW5kDQoNCiAgICAgICAg
    ICAgIGRlZiBjYWNoZSBtbmFtZSwgbQ0KICAgICAgICAgICAgICBtbmFtZSA9
    IG1uYW1lLnRvX3MNCiAgICAgICAgICAgICAgY29uc3Rfc2V0IDpNRVRIT0RT
    X19fXywge30gdW5sZXNzIGNvbnN0X2RlZmluZWQ/IDpNRVRIT0RTX19fXw0K
    ICAgICAgICAgICAgICBjb25zdF9nZXQoOk1FVEhPRFNfX19fKVsgbW5hbWUg
    XSA9IG0NCiAgICAgICAgICAgICAgbW9kdWxlX2V2YWwgPDwtY29kZQ0KICAg
    ICAgICAgICAgICAgIGRlZiAjeyBtbmFtZSB9ICphLCAmYg0KICAgICAgICAg
    ICAgICAgICAgTUVUSE9EU19fX19bICcjeyBtbmFtZSB9JyBdLmJpbmQoc2Vs
    ZikuY2FsbCAqYSwgJmINCiAgICAgICAgICAgICAgICBlbmQNCiAgICAgICAg
    ICAgICAgY29kZQ0KICAgICAgICAgICAgZW5kDQoNCiAgICAgICAgICAgIGRl
    ZiB3YWxraW5nX3VwDQogICAgICAgICAgICAgIG0gPSBzZWxmDQogICAgICAg
    ICAgICAgIGxvb3B7DQogICAgICAgICAgICAgICAgeWllbGQgbQ0KICAgICAg
    ICAgICAgICAgIGJyZWFrIHVubGVzcygobT1tLnBhcmVudCkgcmVzY3VlIG5p
    bCkNCiAgICAgICAgICAgICAgfQ0KICAgICAgICAgICAgZW5kDQogICAgICAg
    ICAgZW5kDQogICAgICAgIH0NCiAgICAgIGVuZA0KICAgIGVuZA0KICBlbmQN
    Cg0KICBkZWYgb3ZlcnJpZGluZyAmYg0KICAgIHRoaXMgPSBzZWxmDQogICAg
    bSA9IE92ZXJSaWRpbmcubmV3DQogICAgbS5tb2R1bGVfZXZhbCAmYg0KDQog
    ICAgdW5sZXNzIGRlZmluZWQ/IEBvdmVycmlkaW5nIA0KICAgICAgQG92ZXJy
    aWRpbmcgPSBPdmVyUmlkaW5nLm5ldw0KICAgICAgbS5hZGRlZF9tZXRob2Rz
    LmVhY2ggZG8gfG1uYW1lfA0KICAgICAgICBAb3ZlcnJpZGluZy5jYWNoZSBt
    bmFtZSwgdGhpcy5pbnN0YW5jZV9tZXRob2QobW5hbWUpDQogICAgICAgIHJl
    bW92ZV9tZXRob2QgbW5hbWUNCiAgICAgIGVuZA0KICAgIGVuZA0KDQogICAg
    bS5hZGRfcGFyZW50IEBvdmVycmlkaW5nDQogICAgaW5jbHVkZSBtIA0KICAg
    IEBvdmVycmlkaW5nID0gbQ0KICBlbmQNCiAgYWxpYXNfbWV0aG9kICdvdmVy
    cmlkZScsICdvdmVycmlkaW5nJw0KDQogIGRlZiByZXN0b3JpbmcgKl9hLCAm
    X2INCiAgICBpZiBfYiAjIGJhcmV3b3JkcyB3aWxsIHJlc3RvcmUgbWV0aG9k
    cw0KICAgICAgbyA9IE9iamVjdC5uZXcNCiAgICAgIHNjID0gY2xhc3MgPDwg
    bzsgc2VsZjsgZW5kDQogICAgICBzYy5tb2R1bGVfZXZhbHsNCiAgICAgICAg
    aW5zdGFuY2VfbWV0aG9kcy5lYWNoe3xtfCByZW1vdmVfbWV0aG9kIG0gdW5s
    ZXNzIG1bL15fXy9dIHJlc2N1ZSBuaWx9DQogICAgICAgIGRlZmluZV9tZXRo
    b2QoJ21ldGhvZF9taXNzaW5nJyl7fF9fbSwgKl9fYXwgX2EgPDwgX19tOyBz
    ZWxmIH0NCiAgICAgIH0NCiAgICAgIG8uaW5zdGFuY2VfZXZhbCAmX2INCiAg
    ICBlbmQNCiAgICBfYS5mbGF0dGVuLmNvbXBhY3QubWFwIGRvIHxtbmFtZXwN
    CiAgICAgIGlmIGRlZmluZWQ/IEBvdmVycmlkaW5nDQogICAgICAgIG1uYW1l
    ID0gbW5hbWUudG9fcw0KICAgICAgICBAb3ZlcnJpZGluZy53YWxraW5nX3Vw
    IGRvIHxtfA0KICAgICAgICAgIGJyZWFrKCBtLmRlbGV0ZV9tZXRob2QgbW5h
    bWUgKSBpZiBtLmFkZGVkX21ldGhvZHMuaW5jbHVkZT8obW5hbWUpDQogICAg
    ICAgIGVuZA0KICAgICAgZW5kDQogICAgICBpbnN0YW5jZV9tZXRob2QgbW5h
    bWUNCiAgICBlbmQNCiAgZW5kDQogIGFsaWFzX21ldGhvZCAncmVzdG9yZScs
    ICdyZXN0b3JpbmcnDQplbmQNCg0KDQoNCg0KaWYgJDAgPT0gX19GSUxFX18N
    Cg0KICBjbGFzcyBDDQogICAgYyA9IG5ldw0KDQogICAgZGVmIG0oKSAnYScg
    ZW5kDQogICAgcCBjLm0gIz0+ICdhJw0KDQogICAgb3ZlcnJpZGV7IGRlZiBt
    KCkgc3VwZXIgKyAnYicgZW5kIH0NCiAgICBwIGMubSAjPT4gJ2FiJw0KDQog
    ICAgb3ZlcnJpZGV7IGRlZiBtKCkgc3VwZXIgKyAnYycgZW5kIH0NCiAgICBw
    IGMubSAjPT4gJ2FiYycNCg0KICAgIG92ZXJyaWRleyBkZWYgbSgpIHN1cGVy
    ICsgJ2QnIGVuZCB9DQogICAgcCBjLm0gIz0+ICdhYmNkJw0KDQogICAgcmVz
    dG9yZSAnbScNCiAgICBwIGMubSAjPT4gJ2FiYycNCg0KICAgIHJlc3RvcmUg
    J20nDQogICAgcCBjLm0gIz0+ICdhYicNCg0KICAgIHJlc3RvcmUgJ20nDQog
    ICAgcCBjLm0gIz0+ICdhJw0KICBlbmQNCg0KZW5kDQo=

    ---1400102478-551175305-1167325293=:5000--
    ---1400102478-551175305-1167325293=:5000--
     
    , Dec 28, 2006
    #8
  9. Guest

    On Fri, 29 Dec 2006 wrote:

    > Hi --
    >
    > On Fri, 29 Dec 2006, wrote:
    >
    > Whoops, it's one of those messages that won't quote back the text. Oh
    > well :) All I wanted to ask was: do you think 'override' is the best
    > name for this? The reason I ask is that "require 'override'" sounds
    > like you're importing override ability into Ruby, without any
    > indication of the enhancements that the package provides (i.e., the
    > restoring ability).


    i'm not attached to the name at all. suggestions? whatever you come up with
    should imply:

    "the following block allows one to redefine methods in a functional way:
    which is to say 'super' will be scoped in any method re-definition so as to
    refer to the 'current' method of the same name"

    the method can be used multiple time in a stack-like way with 'restore'
    affecting the inverse operation.

    i want to avoid any 'stack-like' names since the inability to un-include a
    module in ruby and the fact that this impl is module inclusion based would be
    misleading. the impl sets up a sort of linked list of included/supered
    modules to provide the call up stack for nested supers.

    regards.

    -a
    --
    if you find yourself slandering anybody, first imagine that your mouth is
    filled with excrement. it will break you of the habit quickly enough. - the
    dalai lama
     
    , Dec 28, 2006
    #9
  10. Trans Guest

    wrote:
    > since the threads split all over the place i figured i'd start yet another.
    > can people break this?
    >
    > [snip code]


    Aren't you leaving residual emtpy modules behind when you ermove
    methods?

    T.
     
    Trans, Dec 28, 2006
    #10
  11. Guest

    On Fri, 29 Dec 2006, Trans wrote:

    >
    > wrote:
    >> since the threads split all over the place i figured i'd start yet another.
    >> can people break this?
    >>
    >> [snip code]

    >
    > Aren't you leaving residual emtpy modules behind when you ermove
    > methods?


    not really. basically the first call to override sets up a master parent
    module with the orginal methods


    object -> [master]

    and re-definition takes place in a module between the object and this master,
    thus super works

    object -> [redef] -> [master]

    subsquent redefs chain like so, preserving super semantics

    object -> [redef 2] -> [redef 1] -> [master]

    note that the modules are created not once per method, but once per call to
    'override'. therefore this

    class C
    def a() 'a' end
    def b() 'b' end
    def c() 'c' end

    override{
    def a() super.upcase end
    def b() super.upcase end
    def c() super.upcase end
    }
    end

    creates exactly two modules: the master and one redef. now if we do this

    class C
    override{
    def a() super.downcase end
    def b() super.downcase end
    def c() super.downcase end
    }
    end

    we've created just one more. something like

    object -> [redef 'downcase'] -> [redef 'upcase'] -> [master]

    now, say we do this

    class C
    restore{
    a and b
    }
    end

    then __only__ the methods 'a' and 'b' from [redef 'downcase'] are removed.
    the 'c' method still lives there.


    so, while it is a true statement that __each__ call to 'override' introduces a
    new mixin module, it is not true that __every__ call to 'restore' leaves an
    extraneous module mixed in, though it's possible that a given call to
    'restore' may indeed have that effect.

    make sense?

    -a
    --
    if you find yourself slandering anybody, first imagine that your mouth is
    filled with excrement. it will break you of the habit quickly enough. - the
    dalai lama
     
    , Dec 28, 2006
    #11
  12. wrote:
    > On Thu, 28 Dec 2006, Devin Mullins wrote:
    >> a.rb:63:in `override': private method `remove_method' called for

    > how odd. which ruby version?

    ruby 1.8.5 (2006-08-25) [i386-mswin32]

    (Yes, the "$" prompt in my last email was a lie. Mischevious!)

    > hmmm. i reworked to use a single constant table of methods.

    Will take a look. Looks to be cool-in-progress.

    Devin
     
    Devin Mullins, Dec 29, 2006
    #12
  13. Trans Guest

    wrote:

    >
    > so, while it is a true statement that __each__ call to 'override' introduces a
    > new mixin module, it is not true that __every__ call to 'restore' leaves an
    > extraneous module mixed in, though it's possible that a given call to
    > 'restore' may indeed have that effect.
    >
    > make sense?


    sure, it makes sense, but you do have that possibility. and i agree
    it's not such a big deal. just pointing it out. i also point out that
    the idea of override.rb is but a step from the idea of cuts. in fact
    implementation of overide using cuts is little more than:

    def override &block
    Cut.new(self,&block)
    end

    and my hacked-up pure ruby implementation of cuts is very similar in
    design that of override.rb.

    moving slightly off-topic. have you ever thought about the possibility
    of every method being as if it were it's own module?

    class X

    module A
    def a; "a"; end
    end
    include A

    module B
    def b; "b"; end
    end
    include B

    end

    the ablity to dynamically manipulate behavior goes way up.

    class X
    module A2
    def a; '{'+super+'}'; end
    end
    include A2
    end

    of course so does the overhead. (and the dynamic inclusion problem
    still lurks in the background).

    t.
     
    Trans, Dec 29, 2006
    #13
  14. Guest

    On Fri, 29 Dec 2006, Trans wrote:

    > sure, it makes sense, but you do have that possibility. and i agree
    > it's not such a big deal. just pointing it out. i also point out that
    > the idea of override.rb is but a step from the idea of cuts. in fact
    > implementation of overide using cuts is little more than:
    >
    > def override &block
    > Cut.new(self,&block)
    > end
    >
    > and my hacked-up pure ruby implementation of cuts is very similar in
    > design that of override.rb.


    i confess cuts are a bit heavyweight for my tastes. however - i aggree that
    the effect and even the impl to some respects is very similar.

    > moving slightly off-topic. have you ever thought about the possibility
    > of every method being as if it were it's own module?
    >
    > class X
    >
    > module A
    > def a; "a"; end
    > end
    > include A
    >
    > module B
    > def b; "b"; end
    > end
    > include B
    >
    > end


    yes. about 1 hour ago! ;-)

    > the ablity to dynamically manipulate behavior goes way up.
    >
    > class X
    > module A2
    > def a; '{'+super+'}'; end
    > end
    > include A2
    > end
    >
    > of course so does the overhead. (and the dynamic inclusion problem still
    > lurks in the background).


    indeed.

    no you've done it - my new project is in the works!

    more later....

    -a
    --
    if you find yourself slandering anybody, first imagine that your mouth is
    filled with excrement. it will break you of the habit quickly enough. - the
    dalai lama
     
    , Dec 29, 2006
    #14
    1. Advertising

Want to reply to this thread or ask your own question?

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. Guest
    Replies:
    2
    Views:
    564
    Natty Gur
    Jul 13, 2003
  2. Guest
    Replies:
    2
    Views:
    3,118
    Guest
    Jul 16, 2003
  3. Jon
    Replies:
    4
    Views:
    5,663
    Jonathan Williams
    Aug 7, 2003
  4. Gary Chamberlain

    Override the Encryption Key for Forms Auth

    Gary Chamberlain, Aug 27, 2003, in forum: ASP .Net
    Replies:
    0
    Views:
    328
    Gary Chamberlain
    Aug 27, 2003
  5. SStory
    Replies:
    3
    Views:
    2,432
    SStory
    Oct 30, 2003
Loading...

Share This Page