[lnkForumImage]
TotalShareware - Download Free Software

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


 

Forums >

comp.lang.ruby

ruby-dev summary 24298-24353

SASADA Koichi

9/29/2004 1:39:00 PM

Hi all,

This is ruby-dev summary 24298-24353.


[ruby-dev:24302] Invoke Proc object with any method name

Nowake proposed that a Proc object should be invoked with
any method name like that:

m = Proc.new( :to_s ) { 'test1' }
p m.to_s # => 'test1'

This scheme is enabled with following code:

class MethodProc < Proc
def initialize( *method_name, &procedure )
super( &procedure )
m = Module.new
method_name.each do | i |
m.__send__( :define_method, i, &procedure )
end
self.extend( m )
end
end

He made a point that it is helphul that a Proc object can
be handled as polymorphic.

Matz amazed about this idea. This issue is still open.



# ruby-dev summary index:
# http://i.loveruby.net/en/ruby-dev-su...


See you at RubyConf2004.

Regards,
--
// SASADA Koichi at atdot dot net
//





29 Answers

Nathaniel Talbott

9/29/2004 2:24:00 PM

0

On Sep 29, 2004, at 09:38, SASADA Koichi wrote:

> [ruby-dev:24302] Invoke Proc object with any method name
>
> Nowake proposed that a Proc object should be invoked with
> any method name like that:
>
> m = Proc.new( :to_s ) { 'test1' }
> p m.to_s # => 'test1'

<snip>

> He made a point that it is helphul that a Proc object can
> be handled as polymorphic.
>
> Matz amazed about this idea.

Me too... I haven't found a place to use it since I read about it two
minutes ago, but it sends a tingle down my spine just thinking about
it. It is definitely polymorphic Ruby goodness. Maybe we can convince
Nowake to submit an RCR?


> See you at RubyConf2004.

Looking forward to it...


Nathaniel
Terralien, Inc.

<:((><



Robert Klemme

9/29/2004 2:38:00 PM

0


"SASADA Koichi" <ko1@atdot.net> schrieb im Newsbeitrag
news:20040929223720.2b31e9be%ko1@atdot.net...
> Hi all,
>
> This is ruby-dev summary 24298-24353.
>
>
> [ruby-dev:24302] Invoke Proc object with any method name
>
> Nowake proposed that a Proc object should be invoked with
> any method name like that:
>
> m = Proc.new( :to_s ) { 'test1' }
> p m.to_s # => 'test1'
>
> This scheme is enabled with following code:
>
> class MethodProc < Proc
> def initialize( *method_name, &procedure )
> super( &procedure )
> m = Module.new
> method_name.each do | i |
> m.__send__( :define_method, i, &procedure )
> end
> self.extend( m )
> end
> end
>
> He made a point that it is helphul that a Proc object can
> be handled as polymorphic.
>
> Matz amazed about this idea. This issue is still open.

Just out of curiosity (and because I can't read Japanese) is there any
advantage of using a Module over using the singleton class? As far as I
can see "self.extend(m)" creates the singleton class anyway.

Thinking a bit about this there could be numerous alternative approaches,
some of which might be more efficient. My suggestion would be this:

module Kernel
private
def MethodProc(*method_names, &b)
raise ArgumentError, "No block given" unless b

class <<b; self end.class_eval do
method_names.each {|m| alias_method m.to_sym, :call }
end

b
end
end


Kind regards

robert

Paul Brannan

9/29/2004 2:38:00 PM

0

On Wed, Sep 29, 2004 at 10:38:55PM +0900, SASADA Koichi wrote:
> Nowake proposed that a Proc object should be invoked with
> any method name like that:
>
> m = Proc.new( :to_s ) { 'test1' }
> p m.to_s # => 'test1'

I know what the sample implementation does, but how would/should the
final version respond to:

p m.call()

Also, it took me a while to figure out what was meant by the above
code. What advantage does it give over:

m = Object.new
m.define_singleton_method(:to_s) { 'test1' }

(I know no such method exists, but I think it probably should...)

Paul



T. Onoma

9/29/2004 7:42:00 PM

0

On Wednesday 29 September 2004 10:23 am, Nathaniel Talbott wrote:
> Me too... I haven't found a place to use it since I read about it two
> minutes ago, but it sends a tingle down my spine just thinking about
> it. It is definitely polymorphic Ruby goodness. Maybe we can convince
> Nowake to submit an RCR?

Nice! I just ran into a possible use. Sometimes set_trace_func returns nil for
a binding. Passing this nil to methods expecting a binding causes further
exception handling needs. Blech! With the above I could pass on a "fake
binding" without having to create an actual FakeBinding class. Not bad.

Anyone see any issues with this?

Oh, and also, why is set_trace_func turning up with nil binding?

Thanks!
T.


Paul Brannan

9/29/2004 8:46:00 PM

0

On Thu, Sep 30, 2004 at 04:42:02AM +0900, trans. (T. Onoma) wrote:
> Oh, and also, why is set_trace_func turning up with nil binding?

Can you post a short sample that produces this?

Paul



T. Onoma

9/30/2004 2:05:00 AM

0

On Wednesday 29 September 2004 04:45 pm, Paul Brannan wrote:
> On Thu, Sep 30, 2004 at 04:42:02AM +0900, trans. (T. Onoma) wrote:
> > Oh, and also, why is set_trace_func turning up with nil binding?
>
> Can you post a short sample that produces this?

Thanks for asking, since I may not have bothered to do this otherwise. It
looks like the binding is nil the same time that the class is false --on
'end' events. At least that's when it turns up with this example:

01 set_trace_func proc{ |e, f, l, m, b, k|
02 puts "#{e}, #{f}, #{l}, #{m}, #{k}" if ! b
03 }
04
05 module T
06 # setup
07 class Test
08 def initialize; @example = true; end
09 def test; "Okay!"; end
10 end
11 end
12
13 t = T::Test.new
14 t.test
15 t.test

Which returns:

end, t.rb, 7, , false
end, t.rb, 5, , false

I'm not sure why this would be. Isn't there always a context? Also I find the
line numbers odd (I added for easy reading), those mark where the 'class'
event occurs.

T.


Robert Klemme

9/30/2004 5:54:00 AM

0


"Nathaniel Talbott" <nathaniel@talbott.ws> schrieb im Newsbeitrag
news:2819AA48-1223-11D9-95A4-000A95CD7A8E@talbott.ws...

> Me too... I haven't found a place to use it since I read about it two
> minutes ago, but it sends a tingle down my spine just thinking about it.
> It is definitely polymorphic Ruby goodness. Maybe we can convince Nowake
> to submit an RCR?

Possible uses are simple adaptors that adapt just one method like these:

1. Condition

ODD = MethodProc(:===) {|x| x % 2 != 0}
....

case n
when ODD
...
when ...
end


2. Fake Classes

Consider an object pool that needs a class instance as factory (i.e. to
create new instances). We can use a MethodProc instead:

class Pool
def initialize(cl)
@cl = cl
@pool = []
end

def get() @pool.shift || @cl.new end
def put(x) @pool << x end
end

pl = Pool.new( MethodProc(:new) { %w{a b c} } )


But the second example shows a more general pattern: what we need here is an
Adaptor because we might want to check the type of the object returned via
Class#=== to make sure only proper instances go into the Pool. In Ruby we
often use singleton methods to do method adptions, but there might be usages
where we don't want to change an instance. Here's a sample implementation:

class Adaptor
def initialize(obj, mappings)
@obj = obj
scl = class<<self; self end

# delegation of all public methods
obj.public_methods.each do |m|
m = m.to_sym

unless mappings[m]
scl.class_eval { define_method(m) { |*a| @obj.send(m,*a) } }
end
end

# remapping
mappings.each do |m,mapped|
case mapped
when Symbol
scl.class_eval { define_method(m) {|*a| @obj.send(mapped,*a) } }
when Proc
scl.class_eval { define_method(m,&mapped) }
else
raise ArgumentError, "Must be Proc or Symbol"
end
end
end
end

With this we can do

>> sample = %w{aa bb cc}
=> ["aa", "bb", "cc"]
>> fake_class = Adaptor.new(sample, :new => :dup, :=== => :==)
=> ["aa", "bb", "cc"]
>> x = fake_class.new
=> ["aa", "bb", "cc"]
>> "Is an instance of? #{fake_class === x}"
=> "Is an instance of? true"
>> x.id == sample.id
=> false

Now we can modify Pool#put to a more appropriate implementation:

class Pool
def put(x)
raise ArgumentError, "illegal type" unless @cl === x
@pool << x
end
end

>> pl = Pool.new fake_class
=> #<Pool:0x101b65d8 @cl=["aa", "bb", "cc"], @pool=[]>
>> pl.get
=> ["aa", "bb", "cc"]
>> pl.put( pl.get )
=> [["aa", "bb", "cc"]]
>> pl.put( "foo" )
ArgumentError: illegal type
from (irb):55:in `put'
from (irb):62
from (null):0
>> pl.put( pl.get << "x" )
ArgumentError: illegal type
from (irb):55:in `put'
from (irb):63
from (null):0

I'm not sure though whether there are many applications of this pattern in
Ruby because we have per instance method definitions with singleton classes.
What do others think?

Kind regards

robert

T. Onoma

9/30/2004 11:42:00 PM

0

> "SASADA Koichi" <ko1@atdot.net> schrieb im Newsbeitrag
> news:20040929223720.2b31e9be%ko1@atdot.net...
>
> > Hi all,
> >
> > This is ruby-dev summary 24298-24353.
> >
> >
> > [ruby-dev:24302] Invoke Proc object with any method name
> >
> > Nowake proposed that a Proc object should be invoked with
> > any method name like that:
> >
> > m = Proc.new( :to_s ) { 'test1' }
> > p m.to_s   # => 'test1'
> >
> > This scheme is enabled with following code:
> >
> > class MethodProc < Proc
> >   def initialize( *method_name, &procedure )
> >     super( &procedure )
> >     m = Module.new
> >     method_name.each do | i |
> >       m.__send__( :define_method, i, &procedure )
> >     end
> >     self.extend( m )
> >   end
> > end
> >
> > He made a point that it is helphul that a Proc object can
> > be handled as polymorphic.
> >
> > Matz amazed about this idea. This issue is still open.

http://jakarta.apache.org/commons/sandbo...

T.



Yukihiro Matsumoto

10/1/2004 12:18:00 AM

0

Hi,

In message "Re: ruby-dev summary 24298-24353"
on Fri, 1 Oct 2004 08:42:15 +0900, "trans. (T. Onoma)" <transami@runbox.com> writes:

|> > He made a point that it is helphul that a Proc object can
|> > be handled as polymorphic.
|> >
|> > Matz amazed about this idea. This issue is still open.
|
|http://jakarta.apache.org/commons/sandbo...

Hmm, "fanctor". I like the name.

matz.


T. Onoma

10/1/2004 12:53:00 AM

0

On Thursday 30 September 2004 08:17 pm, Yukihiro Matsumoto wrote:
> Hi,
>
> In message "Re: ruby-dev summary 24298-24353"
>
> on Fri, 1 Oct 2004 08:42:15 +0900, "trans. (T. Onoma)"
<transami@runbox.com> writes:
> |> > He made a point that it is helphul that a Proc object can
> |> > be handled as polymorphic.
> |> >
> |> > Matz amazed about this idea. This issue is still open.
> |
> |http://jakarta.apache.org/commons/sandbo...
>
> Hmm, "fanctor". I like the name.

Is a new class required? I think, Proc could add this feature and remain
backward compatible.

T.