Set an instance variable before and after initialize

Discussion in 'Ruby' started by Martin Jansson, Jul 22, 2006.

  1. If possible, I would like to set a instance variable in an object before
    and after its initialize method is executed.

    I've been looking at Class#new but it doesn't seem to have access to a
    reference to the object in creation.

    A possible workaround would be to place the object in an already created
    hashtable. But I need to know if initialize has been completed or not
    even if callcc is used.

    This behavior must be shared by all objects in classes that inherit
    Object.

    I try to create Simula style corutines. In Simula all objects have three
    states of execution: active, passive and terminated. An active object is
    executing it's class body (think: Rubys Object#initialize on steroids).
    The first time an object is activated is when it's created with new.
    Within the class body you can call detach to make the object passive and
    pause execution of the class body. Execution is then continued after the
    point where the object was last activated. Within the class body you can
    also call resume wich make the object passive and activates another
    object. Execution is continued again when the other object become
    passive or terminated. Objects can also become active if the procedure
    call is called with the object as an argument. When execution reach the
    end of the objects class body, the object becomes terminated and can not
    be activated anymore.

    You can't do all the things you can do with callcc with this kind of
    corutines but it makes some otherwise hairy programming easy.

    --
    Posted via http://www.ruby-forum.com/.
     
    Martin Jansson, Jul 22, 2006
    #1
    1. Advertising

  2. Martin Jansson

    Dumaiu Guest

    The initialize() method, the constructor, is the earliest point at
    which you can manipulate an object, because prior to that it does not
    exist. Although I know diddly-doo about coroutines, it sounds to me
    like you'd be better off using instances of the hypothetical
    "Coroutine" class rather than the class body itself. Let an
    initialized Coroutine stay dormant until it is sent a call() message,
    or something like that, and then do its yielding and whatever else
    Coroutines do.
    There seems to be a coroutine implementation, according to Wikipedia,
    iff you can read Japanese.

    -J
     
    Dumaiu, Jul 23, 2006
    #2
    1. Advertising

  3. Martin Jansson

    Trans Guest

    Martin Jansson wrote:
    > If possible, I would like to set a instance variable in an object before
    > and after its initialize method is executed.
    >
    > I've been looking at Class#new but it doesn't seem to have access to a
    > reference to the object in creation.


    class Klass
    def self.new( *args, &blk )
    o = allocate
    o.instance_variable_set( "@foo", "anything")
    o.initialize( *args, &blk )
    o.instance_variable_set( "@bar", "anything")
    o
    end

    You could also you #instance_eval { @foo = "anything }

    T.
     
    Trans, Jul 23, 2006
    #3
  4. Trans wrote:
    > Martin Jansson wrote:
    >> If possible, I would like to set a instance variable in an object before
    >> and after its initialize method is executed.
    >>
    >> I've been looking at Class#new but it doesn't seem to have access to a
    >> reference to the object in creation.

    >
    > class Klass
    > def self.new( *args, &blk )
    > o = allocate
    > o.instance_variable_set( "@foo", "anything")
    > o.initialize( *args, &blk )
    > o.instance_variable_set( "@bar", "anything")
    > o
    > end
    >
    > You could also you #instance_eval { @foo = "anything }
    >
    > T.


    This break the chain of inheritance. You would have to reimplement all
    classes that you use; it would be more complicated to use then Thread
    even if it would have the advantage that you could circumvent some of
    Threads limitations. I'm not even sure that it would behave correctly.
    Class#new seem to do more then call allocate and initialize. But I could
    be wrong. Here is the C code for Class#new:

    VALUE
    rb_class_new_instance(argc, argv, klass)
    int argc;
    VALUE *argv;
    VALUE klass;
    {
    VALUE obj;

    obj = rb_obj_alloc(klass);
    rb_obj_call_init(obj, argc, argv);

    return obj;
    }

    I've looked at rb_obj_call_init, but I can't seem to find it at the
    moment.

    My current hack has an ActiveObject class that I use instead of Object.
    In this class I have a method called body instead of initialize.
    initialize is already used to set that damn variable and to call body
    and can not be rewritten. All this of course breaks the chain of
    inherritance.

    --
    Posted via http://www.ruby-forum.com/.
     
    Martin Jansson, Jul 23, 2006
    #4
  5. That won't work: initialize is private. And it might better to
    overwrite Object.new, so it works for all classes.

    What about singleton? (I mean "include Singleton".)

    gegroet,
    Erik V. - http://www.erikveen.dds.nl/

    ----------------------------------------------------------------

    class Object
    def self.new( *args, &blk )
    o = allocate
    o.instance_variable_set( "@foo", "anything")
    o.instance_eval{initialize( *args, &blk )}
    o.instance_variable_set( "@bar", "anything")
    o
    end
    end

    class Foo
    def initialize(baz)
    @baz = baz
    end

    def bar
    p @foo
    p @bar
    p @baz
    end
    end

    Foo.new(8).bar

    ----------------------------------------------------------------
     
    Erik Veenstra, Jul 23, 2006
    #5
  6. Martin Jansson

    Trans Guest

    Damn! You guys are sticklers! You want complete, universally
    applicable, 100% bug-free implementations for a general mailing list
    question. How much time do I have? ;-)

    T.
     
    Trans, Jul 23, 2006
    #6
  7. Think about this:

    Write once.
    Read never.
    Use everywhere.

    So, yes, "universally applicable" would be nice... ;]

    gegroet,
    Erik V. - http://www.erikveen.dds.nl/
     
    Erik Veenstra, Jul 23, 2006
    #7
  8. Martin Jansson

    Guest

    On Sun, 23 Jul 2006, Martin Jansson wrote:

    > If possible, I would like to set a instance variable in an object before and
    > after its initialize method is executed.


    let initialize help you do this then:


    harp:~ > cat a.rb
    module BeforeAfterInit
    module InstanceMethods
    def before_initialize *a, &b
    end
    def after_initialize *a, &b
    end
    def initialize *a, &b
    before_initialize *a, &b
    r = super
    after_initialize *a, &b
    r
    end
    end
    module ClassMethods
    def before &b
    define_method 'before_initialize', &b
    end
    def after &b
    define_method 'after_initialize', &b
    end
    end
    def self.included other
    other.module_eval{ include InstanceMethods }
    other.extend ClassMethods
    super
    end
    end

    class C
    include BeforeAfterInit

    before{ @a = 40 }
    after{ @b = 2 }

    def m() @a + @b end
    end

    p C.new.m



    harp:~ > ruby a.rb
    42


    regards.

    -a
    --
    suffering increases your inner strength. also, the wishing for suffering
    makes the suffering disappear.
    - h.h. the 14th dali lama
     
    , Jul 23, 2006
    #8
  9. Martin Jansson

    Ben Nagy Guest

    I have a couple of questions...

    > -----Original Message-----
    > From: [mailto:]
    > Sent: Sunday, July 23, 2006 9:34 PM
    > To: ruby-talk ML
    > Subject: Re: Set an instance variable before and after initialize
    >
    > On Sun, 23 Jul 2006, Martin Jansson wrote:
    >
    > > If possible, I would like to set a instance variable in an

    > object before and
    > > after its initialize method is executed.

    >
    > let initialize help you do this then:
    >
    >
    > harp:~ > cat a.rb
    > module BeforeAfterInit
    > module InstanceMethods
    > def before_initialize *a, &b
    > end
    > def after_initialize *a, &b
    > end
    > def initialize *a, &b
    > before_initialize *a, &b
    > r = super


    What does this construction (r=super) do? I tried removing both references
    to r and replacing it with a single 'super' and it seemed to behave
    identically.

    > after_initialize *a, &b
    > r
    > end
    > end
    > module ClassMethods
    > def before &b
    > define_method 'before_initialize', &b
    > end
    > def after &b
    > define_method 'after_initialize', &b
    > end
    > end
    > def self.included other
    > other.module_eval{ include InstanceMethods }
    > other.extend ClassMethods
    > super
    > end
    > end
    >
    > class C
    > include BeforeAfterInit
    >
    > before{ @a = 40 }
    > after{ @b = 2 }


    When I define an initialize method here without using super, it breaks
    (obvious, I guess), When I use super the before and after code gets run at
    the same time - in other words:

    def initialize
    p @a #should be set, but => nil
    super
    end

    So to my naive understanding this doesn't acheive the goal. What am I
    missing?

    > def m() @a + @b end
    > end
    >
    > p C.new.m
    >
    >
    >
    > harp:~ > ruby a.rb
    > 42


    Cheers,

    ben
     
    Ben Nagy, Jul 26, 2006
    #9
  10. Martin Jansson

    Guest

    On Wed, 26 Jul 2006, Ben Nagy wrote:

    > What does this construction (r=super) do? I tried removing both references
    > to r and replacing it with a single 'super' and it seemed to behave
    > identically.


    it says: return whatever super used to. it's just good form when you wrap a
    method.

    >> include BeforeAfterInit
    >>
    >> before{ @a = 40 }
    >> after{ @b = 2 }

    >
    > When I define an initialize method here without using super, it breaks
    > (obvious, I guess), When I use super the before and after code gets run at
    > the same time - in other words:
    >
    > def initialize
    > p @a #should be set, but => nil


    but why? you haven't called super yet. try calling it first.

    -a
    --
    suffering increases your inner strength. also, the wishing for suffering
    makes the suffering disappear.
    - h.h. the 14th dali lama
     
    , Jul 26, 2006
    #10
  11. Martin Jansson

    Ben Nagy Guest

    > -----Original Message-----
    > From: [mailto:]

    [...]
    > > def initialize
    > > p @a #should be set, but => nil

    >
    > but why? you haven't called super yet. try calling it first.


    Oh, I did that too. My point is that there is no 'before' and 'after' the
    code gets run at the same time and it's not possible to insert other code in
    between them, which was presumably the point?

    def initialize
    super
    p @b #should not be set yet, initialize method not finished...
    end

    ben
     
    Ben Nagy, Jul 26, 2006
    #11
  12. Martin Jansson

    Guest

    On Wed, 26 Jul 2006, Ben Nagy wrote:

    > Oh, I did that too. My point is that there is no 'before' and 'after' the
    > code gets run at the same time and it's not possible to insert other code in
    > between them, which was presumably the point?



    hmmm. you can actually do it with my first impl by including the module
    __after__ defining initialize. but this makes it easier:


    harp:~ > cat a.rb
    module BeforeAfterInit
    module InstanceMethods
    def before_initialize(*a, &b) end
    def after_initialize(*a, &b) end
    end
    module ClassMethods
    def before &b
    define_method 'before_initialize', &b
    private 'before_initialize'
    end
    def after &b
    define_method 'after_initialize', &b
    private 'after_initialize'
    end
    def new(*a, &b)
    (obj = allocate).instance_eval{
    before_initialize
    initialize *a, &b
    after_initialize
    self
    }
    end
    end
    def self.included other
    other.module_eval{ include InstanceMethods }
    other.extend ClassMethods
    super
    end
    end

    class C < ::Array
    include BeforeAfterInit

    before{ self << :before }
    after{ self << :after }

    def initialize
    self << :initialize
    end
    end

    p C.new


    harp:~ > ruby a.rb
    [:before, :initialize, :after]


    regards.


    -a
    --
    suffering increases your inner strength. also, the wishing for suffering
    makes the suffering disappear.
    - h.h. the 14th dali lama
     
    , Jul 26, 2006
    #12
    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. Tony Morris
    Replies:
    3
    Views:
    905
    Roedy Green
    Feb 4, 2006
  2. Gerard Flanagan
    Replies:
    3
    Views:
    471
    Terry Hancock
    Nov 19, 2005
  3. jubelbrus
    Replies:
    5
    Views:
    635
    JohnQ
    Jul 20, 2007
  4. Leon Bogaert
    Replies:
    19
    Views:
    347
    Robert Klemme
    Mar 23, 2008
  5. Cameron Vessey

    initialize instance variable problem

    Cameron Vessey, Aug 28, 2010, in forum: Ruby
    Replies:
    4
    Views:
    127
    Robert Klemme
    Aug 29, 2010
Loading...

Share This Page