Yet Another Rite Thought: method combination

G

gabriele renzi

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 ?
 
G

Gavin Sinclair

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
 
J

Joey Gibson

--------------000000030805040502010902
Content-Type: text/plain; charset=us-ascii; format=flowed
Content-Transfer-Encoding: 7bit

Gavin said:
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


--------------000000030805040502010902--
 
R

Robert Klemme

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
 
T

ts

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
 
R

Robert Klemme

ts said:
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
 
T

ts

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
 
G

gabriele renzi

il Mon, 17 Nov 2003 22:23:27 +0900, Gavin Sinclair
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 :(
 
S

Simon Strandgaard

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>
 
G

gabriele renzi

il Mon, 17 Nov 2003 23:47:31 +0100, Simon Strandgaard
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..
 
H

Hal Fulton

gabriele said:
il Mon, 17 Nov 2003 23:47:31 +0100, Simon Strandgaard
<[email protected]> ha scritto::





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..

I started that thread: http://ruby-talk.org/71948

Here are my comments on Matz's plan:

1. First of all, I will be happy with whatever Matz
decides. I will never flame the one who gave us Ruby.

2. I'm a little bothered by the use of 'super' also.
I once suggested 'prior'; but I can (now) see that
using super does not introduce ambiguity.

3. It strikes me that wrap is really the only one
necessary. It could do all the work of pre and post.
Yet I suppose the others are good from the standpoint
of clarity.

4. I'm a little bothered that 'post' is not able to
know the return value of the method even though the
method has returned. (In theory we could use a call
to super that simply accessed the return value rather
than making a real call.) This is a motivation for
me to use wrap more often than post.

Just my thoughts.

Hal
 
D

daz

Hal Fulton said:
Here are my comments on Matz's plan:

[...]

3. It strikes me that wrap is really the only one
necessary. It could do all the work of pre and post.
Yet I suppose the others are good from the standpoint
of clarity.

A similar argument might be made for attr_accessor
- making attr_reader & attr_writer unnecessary.

OK, there's a ton of reasons why "that's not the same
thing" (the best reason I can think of is that "they're
not the same thing";).

Whereas attr_* contains overlapping functionality,
hooking doesn't appear to suffer in the same way.

Wrap is a controlling 'outer' wrap. The combination of
pre/post would be a benign 'inner' wrap. Benign in the
sense that you could safely assume that you wouldn't
accidentally be changing the program's logic.

Here (#+#) is the statement I add when I'm about to wreck logic:

class Roo
def r
7 * 6
#+# print 'r done ... '
end
end
p Roo.new.r # -> 42
#+# p Roo.new.r # -> r done ... nil

If I understand :post, I should be able to add the method by:

class Roo
def r:post
print 'r done ... '
end
end
p Roo.new.r # -> r done ... 42

4. I'm a little bothered that 'post' is not able to
know the return value of the method even though the
method has returned.

But if :wrap is also defined, its back-end is about to get
control. If you want to know the return value, the only
sensible place to find out is in :wrap because you might
leave it as it is, or change it, and it can't(?) be
changed any later.
Just my thoughts.

Hal


I'm just adding by trivial example that :pre or :post will
be better to use when :wrap might be over-kill.

Acknowledgements to Guy and/or CLOS language.


daz
 
R

Robert Klemme

ts said:
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' ?

Well, def foo:wrap still defines a method, but if you insist, we can
change that, too. :))

Cheers

robert
 
T

ts

R> Well, def foo:wrap still defines a method,

Are you sure ?

Now how do you see that super don't follow the inheritence hierarchy ?

In the example, matz use only one class, difficult to speak about
inheritence with only one class


Guy Decoux
 
R

Robert Klemme

ts said:
R> Well, def foo:wrap still defines a method,

Are you sure ?

Well, it is not exactly a method like others, but it defines
functionality.
Now how do you see that super don't follow the inheritence hierarchy ?

In the example, matz use only one class, difficult to speak about
inheritence with only one class

:))

Exactly. That's why I think "super" is inappropriate here.

robert
 
T

ts

R> Exactly. That's why I think "super" is inappropriate here.

Can you give me an example with 2 classes (inheritance + wrappers) ?


Guy Decoux
 
R

Robert Klemme

ts said:
R> Exactly. That's why I think "super" is inappropriate here.

Can you give me an example with 2 classes (inheritance + wrappers) ?

No need for two classes.

class Foo
def bar
puts "bar"
end

def bar:wrap
puts "pre"

# invocation of bar here, no super class method involved,
# hence "super" is inappropriate IMHO
super

puts "post"
end
end

Cheers

robert
 
T

ts

R> class Foo
R> def bar
R> puts "bar"
R> end

def bar:pre
puts "pre"
end

R> def bar:wrap
R> puts "pre"

R> # invocation of bar here, no super class method involved,
R> # hence "super" is inappropriate IMHO

and bar:pre is not called


Guy Decoux
 

Ask a Question

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

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,744
Messages
2,569,484
Members
44,903
Latest member
orderPeak8CBDGummies

Latest Threads

Top