redefining methods

D

dohzya

Le mardi 31 juillet 2007 à 23:48 +0900, ara.t.howard a écrit :
i was playing with this last night, thought some here might be
interested:

http://drawohara.tumblr.com/post/7241442

cheers.

a @ http://drawohara.com/

Just for the syntax, I don't like :
---
redefining :foo do
def foo(*a, &b) super.reverse end
end
---
I prefer :
---
redefining :foo do |*a, &b|
super.reverse
end
---
Greater, it isn't ?
---

However, there is an other way :
---
redefining :foo do |&old| # &old or old, see after
def foo(*a, &b) old.call.reverse end
end
 
A

ara.t.howard

Le mardi 31 juillet 2007 =E0 23:48 +0900, ara.t.howard a =E9crit :

Just for the syntax, I don't like :

absolutely. and when define_method takes a block that would indeed =20
by the way to do it.
---

However, there is an other way :
---
redefining :foo do |&old| # &old or old, see after
def foo(*a, &b) old.call.reverse end
end
---

this can't work though - old is not in scope inside foo - only with =20
define_method would that be possible, but there you lose the ability =20
to define methods which themselves take blocks...
and maybe...
---
redefining :foo do |*olds| # list, ordered (asc or desc ?)
def foo(*a, &b) (olds.shift.call + olds.shift.call).reverse end
# maybe add a shortcut for shift.call...
end
---

again - same issue with scoping. although i agree and more closure =20
based solution would be nice. for now though - i don't think it's =20
possible. i'd be very happy to be proven wrong though! ;-)

kind regards.

a @ http://drawohara.com/
 
P

Pit Capitain

2007/7/31 said:
i was playing with this last night, thought some here might be
interested:

http://drawohara.tumblr.com/post/7241442

Hi Ara, since I don't know the implementation of Rails'
alias_method_chain, I can't comment on which is better, so just a few
remarks concerning your code:

* Syntax: like =C9tienne, I, too, don't like that it is necessary to
repeat the method name in both the #redefining call and the method
definition. Couldn't you just call #redefining without an argument and
look in the new module which methods have been defined there?

* Implementation: I haven't checked in detail, but I think you could
get problems with the class variable when there's a class hierarchy.

* Implementation: currently, the method chains are only used as a flag
whether to create the "initial" module or not. Do you plan to use it
for other things? Otherwise you don't need an array with all the
intermediate modules.

Btw. nice use of the BEGIN block!

Regards,
Pit
 
B

Bil Kleb

Pit said:
Btw. nice use of the BEGIN block!

Yes.

That was a question that came up at the Advanced Ruby Studio
in Reston a couple weeks ago: of what practical use are those
BEGIN/END things anyway? ;)

Regards,
 
A

ara.t.howard

* Syntax: like =C9tienne, I, too, don't like that it is necessary to
repeat the method name in both the #redefining call and the method
definition. Couldn't you just call #redefining without an argument and
look in the new module which methods have been defined there?

indeed you could/would. just playing now. patches welcome! ;-)
* Implementation: I haven't checked in detail, but I think you could
get problems with the class variable when there's a class hierarchy.

yeah - a class instance var would be the way to go - i was just =20
saving on typing for demo..
* Implementation: currently, the method chains are only used as a flag
whether to create the "initial" module or not. Do you plan to use it
for other things? Otherwise you don't need an array with all the
intermediate modules.

hmmm - you mean use only the two: the initial and subsequent? i =20
think that would work... i was indeed thinking of being able to call =20
a 'specific super' though...
Btw. nice use of the BEGIN block!

i like the idiom, but the error reporting and require semantics stink =20=

- it's nice for examples though ;-)

cheers.

a @ http://drawohara.com/
 
A

ara.t.howard

Hi Ara, since I don't know the implementation of Rails'
alias_method_chain, I can't comment on which is better, so just a few
remarks concerning your code:

* Syntax: like =C9tienne, I, too, don't like that it is necessary to
repeat the method name in both the #redefining call and the method
definition. Couldn't you just call #redefining without an argument and
look in the new module which methods have been defined there?

* Implementation: I haven't checked in detail, but I think you could
get problems with the class variable when there's a class hierarchy.

* Implementation: currently, the method chains are only used as a flag
whether to create the "initial" module or not. Do you plan to use it
for other things? Otherwise you don't need an array with all the
intermediate modules.

Btw. nice use of the BEGIN block!

Regards,
Pit


updated:

http://drawohara.tumblr.com/post/7241442

i played some cannot seem to come up with a way to avoid having the =20
stack of modules and also maintain super semantics across multiple =20
invocations - anyone else have a go?


a @ http://drawohara.com/
 
R

Robert Dober

i was playing with this last night, thought some here might be
interested:

http://drawohara.tumblr.com/post/7241442

cheers.

a @ http://drawohara.com/
As Etienne and Pit pointed it out (guys are you using 1.9 and pointing
fingers at us ;)?) the &blk sntax in block is really missing.
This is a big issue here

if method_chain.empty?
m = Module.new do
class_variable_set "@@#{ method }", this.module_eval{
instance_method method }
module_eval "def #{ method }(*a, &b) @@#{ method
}.bind(self).call(*a, &b) end"
end
remove_method method
include m
end
As it is soo easy to have a class with @@#{method} in your class :(
I do not see any solution, if only we could use closures with a
define_method m do |*args,&blk|

I know I am not DROP here :(

BTW
I would write

def method_chains
@method_chains ||= Hash.new
end

Cheers
Robert

P.S.
Nice work :)
 
P

Pit Capitain

2007/7/31 said:
i played some cannot seem to come up with a way to avoid having the
stack of modules and also maintain super semantics across multiple
invocations - anyone else have a go?

Ara, I didn't mean you don't need a stack of modules, but you don't
need to store the modules in an array (yet).
just playing now. patches welcome! ;-)

Not a patch, but a slightly different implementation based on your idea:

class C
def foo() 'f' end
def bar() 'b' end
def foobar() foo + bar end
end
c = C.new
p c.foobar # => "fb"

class C
redefining do
def foo() super + 'oo' end
end
end
p c.foobar # => "foob"

class C
redefining do
def bar() super + 'ar' end
end
end
p c.foobar # => "foobar"

class C
redefining do
def foo() super.reverse end
def bar() super.reverse end
end
end
p c.foobar # => "oofrab"


### the implementation

BEGIN {
class Class
def redefining &block
unless defined? @_org
org_mod = Module.new
@_org = { :mod => org_mod }
include org_mod
end

m = Module.new(&block)

(m.instance_methods(false) & instance_methods(false)).each do |method|
@_org[method] = instance_method method
@_org[:mod].module_eval <<-EOC
def #{method}(*a, &b)
org = self.class.instance_variable_get("@_org")
org["#{method}"].bind(self).call(*a, &b)
end
EOC
remove_method method
end

include m
end
end
}

I used the old way of getting at the original method (storing it
somewhere), because I'm not sure whether the garbage collector could
remove it if you only remember it's object_id.

Regards,
Pit
 
A

ara.t.howard

Ara, I didn't mean you don't need a stack of modules, but you don't
need to store the modules in an array (yet).


Not a patch, but a slightly different implementation based on your
idea:

class C

I used the old way of getting at the original method (storing it
somewhere), because I'm not sure whether the garbage collector could
remove it if you only remember it's object_id.

Regards,
Pit

updated (and new commenting finally ;-) )

http://drawohara.tumblr.com/post/7241442

nice work pit!

a @ http://drawohara.com/
 
P

Pit Capitain

2007/8/1 said:
(...)
nice work pit!

Thanks, Ara, but it's still your original idea and design. I only
changed a part of the implementation.

Regards,
Pit
 

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

No members online now.

Forum statistics

Threads
473,774
Messages
2,569,596
Members
45,143
Latest member
SterlingLa
Top