[lnkForumImage]
TotalShareware - Download Free Software

Confronta i prezzi di migliaia di prodotti.
Asp Forum
 Home | Login | Register | Search 


 

Forums >

comp.lang.ruby

initialize always

T. Onoma

11/27/2004 5:27:00 PM

It is rather a common occurrence that I find myself creating a mixin module
that has instance vars in it, for example:

module Example
def add( ex )
@examples << ex
end
end

class X
include Examples
end

Now the class that includes this module requires @examples to be predefined.
But short of adding @examples = [] to the #initialize method of the class
(which would ruin the goal of using the module to begin with) one ends up
doing something like:

module Example
def add( ex )
( @examples || [] ) << ex
end
end

But this seems quite computationally wasteful to me. Another alternative is to
add an intialize to the module and a super call to the class:

module Example
def initialize
@examples = []
end
def add( ex )
@examples << ex
end
end

class X
include Examples
def initialize
super()
end
end

But again, by having to modify the class we're defeating the one of the basic
purposes of module "componentization": SOC.

So I was thinking/wondering if it were possible to have an a variant
initializer that _always_ calls super? it would make sense to have one for
both begin and end positions. So the above example becomes:

module Example
def initialize_pre
@examples = []
end
def add( ex )
@examples << ex
end
end

class X
include Examples
end

When X.new is called initialize_pre automatically proceeds the #initialize
method. #initialize_post would do the same for when the #initialize method
finishes. Of course these would automatically work their way up the entire
class/module chain.

BTW this is not necessarily the same as method wraps (consider the subtle
differences) --rather these are strictly callbacks of initialization.

Thoughts?
T.


15 Answers

T. Onoma

11/27/2004 5:31:00 PM

0

On Saturday 27 November 2004 12:26 pm, trans. (T. Onoma) wrote:
| module Example
|     def add( ex )
|       ( @examples || [] ) << ex
|     end
|   end

Make that:

    ( @examples ||= [] ) << ex

T.



Florian Gross

11/27/2004 6:35:00 PM

0

trans. (T. Onoma) wrote:

> So I was thinking/wondering if it were possible to have an a variant
> initializer that _always_ calls super? it would make sense to have one for
> both begin and end positions. So the above example becomes:
>
> module Example
> def initialize_pre
> @examples = []
> end
> def add( ex )
> @examples << ex
> end
> end

Rite will have AOP-style method:pre, :post and :wrap hooks. However I'd
also like to see a solution for this quite common problem before the
release of Ruby 2. Maybe there already is a good way of doing this that
I'm just not aware of.

T. Onoma

11/27/2004 8:06:00 PM

0

On Saturday 27 November 2004 01:37 pm, Florian Gross wrote:
| trans. (T. Onoma) wrote:
| > So I was thinking/wondering if it were possible to have an a variant
| > initializer that _always_ calls super? it would make sense to have one
| > for both begin and end positions. So the above example becomes:
| >
| > module Example
| > def initialize_pre
| > @examples = []
| > end
| > def add( ex )
| > @examples << ex
| > end
| > end
|
| Rite will have AOP-style method:pre, :post and :wrap hooks. However I'd
| also like to see a solution for this quite common problem before the
| release of Ruby 2. Maybe there already is a good way of doing this that
| I'm just not aware of.

I doubt that's a good thing. To me pre, post and wrap are pretty much hacks.
And I do not believe these hooks will even work here. Consider:

module M
def initialize:pre
print "A"
end
def initialize
print "M"
end
end

class C
include M
def initialize
super
print "C"
end
end

C.new ; puts

what will be the output?

T.


Sam Stephenson

11/27/2004 11:01:00 PM

0

On Sun, 28 Nov 2004 02:26:53 +0900, trans. (T. Onoma)
<transami@runbox.com> wrote:
> So I was thinking/wondering if it were possible to have an a variant
> initializer that _always_ calls super? it would make sense to have one for
> both begin and end positions. So the above example becomes:
>
> module Example
> def initialize_pre
> @examples = []
> end
> def add( ex )
> @examples << ex
> end
> end
>
> class X
> include Examples
> end
>
> When X.new is called initialize_pre automatically proceeds the #initialize
> method. #initialize_post would do the same for when the #initialize method
> finishes. Of course these would automatically work their way up the entire
> class/module chain.
>
> BTW this is not necessarily the same as method wraps (consider the subtle
> differences) --rather these are strictly callbacks of initialization.
>
> Thoughts?
> T.
>
>

One way to get this behavior now would be to implement
Module#included, using it with Kernel.set_trace_func to watch
instantiation for the including class, and having it call your
initialize_pre and initialize_post methods.

But since it's possible to have only one tracer at a time, that seems
like a pretty inflexible solution.

Sam


T. Onoma

11/27/2004 11:48:00 PM

0

Not sure I explained this well enough. Let me elaborate just a tad.

On Saturday 27 November 2004 03:06 pm, trans. (T. Onoma) wrote:
| Consider:
|
| module M
| def initialize:pre
| print "A"
| end
| def initialize
| print "M"
| end
| end
|
| class C
| include M
| def initialize
| super
| print "C"
| end
| end
|
| C.new ; puts
|
| what will be the output?

Of course the answer is

#-> AMC

But why? Now consider the slight change:

class C
include M
def initialize
print "C"
super
end
end

Is the result CAM or ACM ?

HTH,
T.


Florian Gross

11/27/2004 11:52:00 PM

0

trans. (T. Onoma) wrote:

> Not sure I explained this well enough. Let me elaborate just a tad.
>
> On Saturday 27 November 2004 03:06 pm, trans. (T. Onoma) wrote:
> | Consider:
> |
> | module M
> | def initialize:pre
> | print "A"
> | end
> | def initialize
> | print "M"
> | end
> | end
> |
> | class C
> | include M
> | def initialize
> | super
> | print "C"
> | end
> | end
> |
> | C.new ; puts
> |
> | what will be the output?
>
> Of course the answer is
>
> #-> AMC

I'm not sure it is that. I'm waiting for somebody that knows how this
will be handled in Rite to answer. I can see AMC being a valid answer of
course, but I am not sure if it will be the one Rite gives.

Robert Klemme

11/29/2004 9:23:00 AM

0


"trans. (T. Onoma)" <transami@runbox.com> schrieb im Newsbeitrag
news:200411271226.46187.transami@runbox.com...
> It is rather a common occurrence that I find myself creating a mixin
module
> that has instance vars in it, for example:
>
> module Example
> def add( ex )
> @examples << ex
> end
> end
>
> class X
> include Examples
> end
>
> Now the class that includes this module requires @examples to be
predefined.
> But short of adding @examples = [] to the #initialize method of the
class
> (which would ruin the goal of using the module to begin with) one ends
up
> doing something like:
>
> module Example
> def add( ex )
> ( @examples || [] ) << ex
> end
> end
>
> But this seems quite computationally wasteful to me. Another alternative
is to
> add an intialize to the module and a super call to the class:
>
> module Example
> def initialize
> @examples = []
> end
> def add( ex )
> @examples << ex
> end
> end
>
> class X
> include Examples
> def initialize
> super()
> end
> end
>
> But again, by having to modify the class we're defeating the one of the
basic
> purposes of module "componentization": SOC.
>
> So I was thinking/wondering if it were possible to have an a variant
> initializer that _always_ calls super? it would make sense to have one
for
> both begin and end positions. So the above example becomes:
>
> module Example
> def initialize_pre
> @examples = []
> end
> def add( ex )
> @examples << ex
> end
> end
>
> class X
> include Examples
> end
>
> When X.new is called initialize_pre automatically proceeds the
#initialize
> method. #initialize_post would do the same for when the #initialize
method
> finishes. Of course these would automatically work their way up the
entire
> class/module chain.
>
> BTW this is not necessarily the same as method wraps (consider the
subtle
> differences) --rather these are strictly callbacks of initialization.
>
> Thoughts?
> T.

I think I did an RCR on this matter but I can't find it. Maybe I was stuck
or it got lost somewhere. I'll have to dig into this at home. If I find
the info I'll get back. From what I remember basically the idea was to
automatically invoke super under certain circumstances. The idea was to
do that depending on the argument list and the presence of an explicite
"super".

Kind regards

robert

T. Onoma

11/30/2004 4:45:00 AM

0

On Monday 29 November 2004 04:22 am, Robert Klemme wrote:
| I think I did an RCR on this matter but I can't find it. Maybe I was stuck
| or it got lost somewhere. I'll have to dig into this at home. If I find
| the info I'll get back. From what I remember basically the idea was to
| automatically invoke super under certain circumstances. The idea was to
| do that depending on the argument list and the presence of an explicite
| "super".

Cool. Let me know.

T.


Robert Klemme

12/15/2004 12:45:00 PM

0


"Robert Klemme" <bob.news@gmx.net> schrieb im Newsbeitrag
news:310832F34jr8cU1@uni-berlin.de...
>
> "trans. (T. Onoma)" <transami@runbox.com> schrieb im Newsbeitrag
> news:200411271226.46187.transami@runbox.com...
> > It is rather a common occurrence that I find myself creating a mixin
> module
> > that has instance vars in it, for example:
> >
> > module Example
> > def add( ex )
> > @examples << ex
> > end
> > end
> >
> > class X
> > include Examples
> > end
> >
> > Now the class that includes this module requires @examples to be
> predefined.
> > But short of adding @examples = [] to the #initialize method of the
> class
> > (which would ruin the goal of using the module to begin with) one ends
> up
> > doing something like:
> >
> > module Example
> > def add( ex )
> > ( @examples || [] ) << ex
> > end
> > end
> >
> > But this seems quite computationally wasteful to me. Another
alternative
> is to
> > add an intialize to the module and a super call to the class:
> >
> > module Example
> > def initialize
> > @examples = []
> > end
> > def add( ex )
> > @examples << ex
> > end
> > end
> >
> > class X
> > include Examples
> > def initialize
> > super()
> > end
> > end
> >
> > But again, by having to modify the class we're defeating the one of
the
> basic
> > purposes of module "componentization": SOC.
> >
> > So I was thinking/wondering if it were possible to have an a variant
> > initializer that _always_ calls super? it would make sense to have one
> for
> > both begin and end positions. So the above example becomes:
> >
> > module Example
> > def initialize_pre
> > @examples = []
> > end
> > def add( ex )
> > @examples << ex
> > end
> > end
> >
> > class X
> > include Examples
> > end
> >
> > When X.new is called initialize_pre automatically proceeds the
> #initialize
> > method. #initialize_post would do the same for when the #initialize
> method
> > finishes. Of course these would automatically work their way up the
> entire
> > class/module chain.
> >
> > BTW this is not necessarily the same as method wraps (consider the
> subtle
> > differences) --rather these are strictly callbacks of initialization.
> >
> > Thoughts?
> > T.
>
> I think I did an RCR on this matter but I can't find it. Maybe I was
stuck
> or it got lost somewhere. I'll have to dig into this at home. If I find
> the info I'll get back. From what I remember basically the idea was to
> automatically invoke super under certain circumstances. The idea was to
> do that depending on the argument list and the presence of an explicite
> "super".

Finally today I found a sheet of paper while cleaning my desk. (It's good
to do that once in a while. :-))

It hadn't made it to an RCR though. The suggestion would have been this:
if a Module defines method initialize without an argument list then
implicitely change that to be initialise(*a,&b) and implicitely add super
as first line in the method: Thus

module Foo
def initialize
@bar = 0
end
end

becomes

module Foo
def initialize(*a,&b)
super
@bar = 0
end
end

Note: identifiers for arguments and block may have to be generated to be
unique.

All other cases (i.e. combinations of with / without argument list and
with / without occurrence of "super" in the body of this method) should
remain unchanged, because they would cause too much hassle.

Pro: this change allows for easy initialization of instance variables
needed by modules even if there are multiple modules included:

class Base
def initialize(x)
@x = x
end
end

class Test < Base
include Foo
include Bar

def initialize(a, b)
super(a)
@b = b
end
end

What do others think?

Kind regards

robert

dblack

12/15/2004 1:06:00 PM

0