[lnkForumImage]
TotalShareware - Download Free Software

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


 

Forums >

comp.lang.ruby

Yet Another Rite Thought: method combination

gabriele renzi

11/17/2003 7:22:00 AM

I just looked at matz' slides and I don't have a clear understanding
of ho9w this is suposed to work.

Possibly this has been explained verbosely, But I can't get it from
the slide.

So, this is the example:

class Foo
def foo(*args) #1
p 'foo'
end
def foo:pre (*args ) #2
p 'pre'
end
def foo:post (*args) #3
p 'post'
end
def foo:wrap (*args) #4
p 'wrap pre'
super
p 'wrap post'
end
end

now: what are pre post and wrap?

Are this just generic (casual) names for the wrapping functions? (so
we could have def foo:bar)

Are they wrapping idioms ?
if true
what do they are for? Do the work as in :
pre called before the method
post called after the method
wrap could call super and get the old method
I suppose pre and post are actually useless this way, cause they
can be emulated with foo:wrap()
or do the work as
pre wraps the original method
post wraps the latest wrapping of the method
wrap ... ?


someone would please explain this to me ?
18 Answers

Gavin Sinclair

11/17/2003 1:23:00 PM

0

On Monday, November 17, 2003, 6:22:18 PM, gabriele wrote:

> I just looked at matz' slides and I don't have a clear understanding
> of ho9w this is suposed to work.

> Possibly this has been explained verbosely, But I can't get it from
> the slide.

> So, this is the example:

> class Foo
> def foo(*args) #1
> p 'foo'
> end
> def foo:pre (*args ) #2
> p 'pre'
> end
> def foo:post (*args) #3
> p 'post'
> end
> def foo:wrap (*args) #4
> p 'wrap pre'
> super
> p 'wrap post'
> end
> end

> now: what are pre post and wrap?

> [...]

> someone would please explain this to me ?


The slide demonstrates it adequately. Given the above code:

Foo.new.foo
# Output:
# wrap pre
# pre
# foo
# post
# wrap post

Gavin


Joey Gibson

11/17/2003 4:11:00 PM

0

Gavin Sinclair wrote:

>On Monday, November 17, 2003, 6:22:18 PM, gabriele wrote:
>
>
> someone would please explain this to me ?
>
>
>
>The slide demonstrates it adequately. Given the above code:
>
> Foo.new.foo
> # Output:
> # wrap pre
> # pre
> # foo
> # post
> # wrap post
>
>

This is a feature from CLOS that allows you to add hooks to arbitrary
methods. The names 'pre', 'post' and 'wrap' are predefined and can't be
changed. This isn't a generic way to sort of chain methods together;
it's sort of AOP-lite. For any method 'foo' you can define any
combination of foo:pre, foo:post and foo:wrap. According to Matz, you
can't change the parameters in a pre, can't change the return value in a
post, but you CAN do both in a wrap. The output snippet above shows the
order of calls if you define all three.

Joey

Robert Klemme

11/17/2003 4:21:00 PM

0


"Gavin Sinclair" <gsinclair@soyabean.com.au> schrieb im Newsbeitrag
news:1174425281.20031117234546@soyabean.com.au...
> On Monday, November 17, 2003, 6:22:18 PM, gabriele wrote:
>
> > I just looked at matz' slides and I don't have a clear understanding
> > of ho9w this is suposed to work.
>
> > Possibly this has been explained verbosely, But I can't get it from
> > the slide.
>
> > So, this is the example:
>
> > class Foo
> > def foo(*args) #1
> > p 'foo'
> > end
> > def foo:pre (*args ) #2
> > p 'pre'
> > end
> > def foo:post (*args) #3
> > p 'post'
> > end
> > def foo:wrap (*args) #4
> > p 'wrap pre'
> > super
> > p 'wrap post'
> > end
> > end

I find the "super" a bit strange here. It looks like it was implied that
for all methods "foo" there is an implicit "foo:wrap" defined by the Ruby
runtime in a super class of the actual class. I'd prefer another keyword,
such as "previous", "original" or so since the semantics differ. Or did I
get the meaning of "super" in this context wrong?

Regards

robert

ts

11/17/2003 4:39:00 PM

0

>>>>> "R" == Robert Klemme <bob.news@gmx.net> writes:

R> I find the "super" a bit strange here. It looks like it was implied that
R> for all methods "foo" there is an implicit "foo:wrap" defined by the Ruby
R> runtime in a super class of the actual class.

well, I've not understood

super is in Foo#foo:wrap : this mean that if ruby call foo:wrap
then it exist at least the method Foo#foo which will be called latter

super, in this case, just assume that it exist another wrapper or the
original method.

R> I'd prefer another keyword,
R> such as "previous", "original" or so since the semantics differ.

call-next-method :-)))

R> Or did I
R> get the meaning of "super" in this context wrong?

probably,


Guy Decoux





Robert Klemme

11/17/2003 5:01:00 PM

0


"ts" <decoux@moulon.inra.fr> schrieb im Newsbeitrag
news:200311171638.hAHGcvO07164@moulon.inra.fr...
> >>>>> "R" == Robert Klemme <bob.news@gmx.net> writes:
>
> R> I find the "super" a bit strange here. It looks like it was implied
that
> R> for all methods "foo" there is an implicit "foo:wrap" defined by the
Ruby
> R> runtime in a super class of the actual class.
>
> well, I've not understood
>
> super is in Foo#foo:wrap : this mean that if ruby call foo:wrap
> then it exist at least the method Foo#foo which will be called latter
>
> super, in this case, just assume that it exist another wrapper or the
> original method.

Yeah, but "super" generally refers to the same method defined in another
class up the inheritance hierarchy. That's a chain different from the
wrapping chain.

> R> I'd prefer another
keyword,
> R> such as "previous", "original" or so since the semantics differ.
>
> call-next-method :-)))

or the even more typing friendly "invoke-next-wrapper-or-original-method"
:-)))

(Sorry, I couldn't find something more longish.)

> R> Or
did I
> R> get the meaning of "super" in this context wrong?
>
> probably,

Not from what you wrote: "super" invokes whatever is next in the wrapping
chain at whose end the original method resides. Thanks anyway.

Cheers

robert

ts

11/17/2003 5:18:00 PM

0

>>>>> "R" == Robert Klemme <bob.news@gmx.net> writes:

R> Not from what you wrote: "super" invokes whatever is next in the wrapping
R> chain at whose end the original method resides.

Can you explain me why you see a problem with `super' but don't see a
problem with `def' ?


Guy Decoux




gabriele renzi

11/17/2003 8:36:00 PM

0

il Mon, 17 Nov 2003 22:23:27 +0900, Gavin Sinclair
<gsinclair@soyabean.com.au> ha scritto::

>On Monday, November 17, 2003, 6:22:18 PM, gabriele wrote:
>
>> I just looked at matz' slides and I don't have a clear understanding
>> of ho9w this is suposed to work.

>
>The slide demonstrates it adequately. Given the above code:
>
> Foo.new.foo
> # Output:
> # wrap pre
> # pre
> # foo
> # post
> # wrap post
>

I'm dumb I can admit thois :)
But, This could work both with idea #2 or #3.
The point is: if #2 is right (pre is called before the method. post is
called after the real method. wrap can call super.) what is the need
for pre and post? thay can be easily done transparently with wrap?

Does foo:post add itself to the first foo() definition or to the
latest redefinition?

what is the 'method resolution order' for method wrapping?

wrap->post->pre?

pre->post->wrap?

latest-definition-wins ?

if I did:

class Foo
def foo:wrap (*args) #4
p 'wrap pre'
super
p 'wrap post'
end
def foo(*args) #1
p 'foo'
end
def foo:pre (*args ) #2
p 'pre'
end
def foo:post (*args) #3
p 'post'
end
end

Foo.new.foo would give the same output or would it give

pre
wrap pre
foo
wrap post
post

?

sorry for being stupid :(

Lyle Johnson

11/17/2003 8:51:00 PM

0

gabriele renzi wrote:

> The point is: if #2 is right (pre is called before the method. post is
> called after the real method. wrap can call super.) what is the need
> for pre and post? they can be easily done transparently with wrap?

Based on what I heard Matz say during the presentation, you are correct
that the 'pre' and 'post' methods' behavior can be emulated with the
'wrap' method, i.e. this:

class Foo
def foo; p "foo"; end
def foo:pre; p "pre"; end
def foo:post; p "post"; end
end

and this:

class Foo
def foo
p "foo"
end
def foo:wrap
p "pre"
result = super
p "post"
result
end
end

would produce equivalent results.

> Does foo:post add itself to the first foo() definition or to the
> latest redefinition?

This was not specified (I think).

> what is the 'method resolution order' for method wrapping?
>
> wrap->post->pre?
>
> pre->post->wrap?
>
> latest-definition-wins?

Not sure I understand. "wrap" (if it exists) is the entry point, so it
has the first shot. Inside foo:wrap, if you call super (i.e. invoke the
wrapped method), it will call foo:pre (if it exists), then foo, then
foo:post (if it exists).

> if I did:
>
> class Foo
> def foo:wrap (*args) #4
> p 'wrap pre'
> super
> p 'wrap post'
> end
> def foo(*args) #1
> p 'foo'
> end
> def foo:pre (*args ) #2
> p 'pre'
> end
> def foo:post (*args) #3
> p 'post'
> end
> end
>
> Foo.new.foo would give the same output or would it give
>
> pre
> wrap pre
> foo
> wrap post
> post
>
> ?

For this example, Foo.new.foo would print:

wrap pre
pre
foo
post
wrap post

> sorry for being stupid :(

Not stupid. And hopefully I haven't given you bad information here ;)

Lyle

Simon Strandgaard

11/17/2003 10:48:00 PM

0

On Mon, 17 Nov 2003 07:22:01 +0000, gabriele renzi wrote:

> I just looked at matz' slides and I don't have a clear understanding
> of ho9w this is suposed to work.
>
> Possibly this has been explained verbosely, But I can't get it from
> the slide.
>
> So, this is the example:
>
> class Foo
> def foo(*args) #1
> p 'foo'
> end
> def foo:pre (*args ) #2
> p 'pre'
> end
> end

How about something like ?

This is only a partial example.. I have no clue how to do it with proc's.
But there should be a convertion from yield-block to proc.

server> ruby a.rb
before #test
42
after #test
server> expand -t2 a.rb
class Object
def self.def_pre(*args)
args.each{|symbol|
begin
meth = instance_method(symbol)
rescue => e
$stderr.puts "ERROR: symbol2method failure, " + e.inspect
next
end
name = symbol.id2name
org = "_defpre_"+name
arguments = (meth.arity != 0) ? "(*a,&b)" : "(&b)"
module_eval <<MSG
alias #{org} #{name}
def #{name}#{arguments}
$stdout.puts("before ##{name}")
#{org}#{arguments}
$stdout.puts("after ##{name}")
ensure
$debug = nil
end
private :#{org}
MSG
}
end
end

class A
def test; p 42 end
end

class B < A
def_pre :test #{ puts "pre" }
end

B.new.test
server>


--
Simon Strandgaard

gabriele renzi

11/18/2003 12:54:00 AM

0

il Mon, 17 Nov 2003 23:47:31 +0100, Simon Strandgaard
<qj5nd7l02@sneakemail.com> ha scritto::


>How about something like ?

there was already a working implementation of method wrapping.. google
for
'how I'd like method $x to work'
$x is something like 'wrapping' 'hook' 'decoration'

Just this is ruby code and not interprter level..