Making a duck

Regarding duck-typing... Is there an easy way make a "duck"?
i.e. an object that responds to enough methods to be an
acceptable argument to a certain methods. For example, if I
have a method that takes aString and uses the #size and #[i]
methods, I could pass it something that looked just enough like
a String to work:

alphabet = Object.duck(:[],proc{|i|?a+i},:size,proc{26})

The implementation I came up with is this:

class Object
    def self.duck(*name_proc)
        duck = self.new
        duckclass = (class << duck;self;end)
        while not name_proc.empty?
            name,proc = name_proc.slice!(0,2)
            duckclass.send(:define_method,name,&proc)
        end
        duck
    end
end

Is there another way to do this? With all of the talk about
duck-typing, there would already be something out there to do
this.

···

__________________________________
Discover Yahoo!
Stay in touch with email, IM, photo sharing and more. Check it out!
http://discover.yahoo.com/stayintouch.html

Well, my way isn't really different, and I actually wouldn't use
either "my" way or yours, but in the spirit of ruby I propose this
revision:

  class Object
    def self.duck(methods = {})
      duck = self.new
      duckclass = (class << duck; self; end)
      methods.each do |name,proc|
        duckclass.send(:define_method, name, &proc)
      end
      duck
    end
  end

  alphabet = Object.duck(
    : => proc{ |i| ?a+i },
    :size => proc{ 26 }
  )

I simply replaced the array with a hash. Looks a bit cleaner to me.

Jacob Fugal

···

On 6/6/05, Eric Mahurin <eric_mahurin@yahoo.com> wrote:

Regarding duck-typing... Is there an easy way make a "duck"?
i.e. an object that responds to enough methods to be an
acceptable argument to a certain methods. For example, if I
have a method that takes aString and uses the #size and #[i]
methods, I could pass it something that looked just enough like
a String to work:

alphabet = Object.duck(:,proc{|i|?a+i},:size,proc{26})

The implementation I came up with is this:

class Object
    def self.duck(*name_proc)
        duck = self.new
        duckclass = (class << duck;self;end)
        while not name_proc.empty?
            name,proc = name_proc.slice!(0,2)
            duckclass.send(:define_method,name,&proc)
        end
        duck
    end
end

Is there another way to do this? With all of the talk about
duck-typing, there would already be something out there to do
this.

Eric Mahurin ha scritto:

Is there another way to do this? With all of the talk about
duck-typing, there would already be something out there to do
this.

There was some talk in the past about Object.new taking a block, which imho would be useful for this. Meanwhile what about using Struct.new with a block to define methods?

Hi --

Regarding duck-typing... Is there an easy way make a "duck"?
i.e. an object that responds to enough methods to be an
acceptable argument to a certain methods. For example, if I
have a method that takes aString and uses the #size and #[i]
methods, I could pass it something that looked just enough like
a String to work:

alphabet = Object.duck(:,proc{|i|?a+i},:size,proc{26})

The implementation I came up with is this:

class Object
   def self.duck(*name_proc)
       duck = self.new
       duckclass = (class << duck;self;end)
       while not name_proc.empty?
           name,proc = name_proc.slice!(0,2)
           duckclass.send(:define_method,name,&proc)
       end
       duck
   end
end

Is there another way to do this? With all of the talk about
duck-typing, there would already be something out there to do
this.

I've always understood "duck typing" to refer to a particular approach
to the handling of method calls on objects, so I personally wouldn't
expect a to see a correlation between the amount of talk about duck
typing and this kind of technique. Your technique looks to me like it
has more to do with the opposite end of the process: the preparation
and priming of an object, as a way of creating a situation favorable
to subsequent duck typing. I don't think what you've got here stands
in any unique or special relation to duck typing; after all, from the
duck typing perspective, a method that an object got from its original
Class is just as much part of the object's behavior as a method the
object got extended with later.

In fact... your technique actually calls to mind Module#extend. Do
you have a case where you'd prefer to do it the way you've done it
above, rather than defining the methods in a module and then extending
your object with it?

David

···

On Tue, 7 Jun 2005, Eric Mahurin wrote:

--
David A. Black
dblack@wobblini.net

Eric Mahurin wrote:

Regarding duck-typing... Is there an easy way make a "duck"?
i.e. an object that responds to enough methods to be an
acceptable argument to a certain methods. For example, if I
have a method that takes aString and uses the #size and #[i]
methods, I could pass it something that looked just enough like
a String to work:

alphabet = Object.duck(:,proc{|i|?a+i},:size,proc{26})

Why aren't you satisfied with

class Alpha
  def (i) ?a+i end
  def size() 26 end
end
alphabet = Alpha.new

or

alphabet = Object.new
def alphabet.(i) ?a+i end
def alphabet.size() 26 end

You can even squeeze that on one line if you feel the need for it. I
mean, you don't generate those methods dynamically or get them from
somewhere else so why not just use the std approach?

Kind regards

    robert

Hi,

At Tue, 7 Jun 2005 01:00:23 +0900,
Eric Mahurin wrote in [ruby-talk:144691]:

Regarding duck-typing... Is there an easy way make a "duck"?
i.e. an object that responds to enough methods to be an
acceptable argument to a certain methods. For example, if I
have a method that takes aString and uses the #size and #[i]
methods, I could pass it something that looked just enough like
a String to work:

alphabet = Object.duck(:,proc{|i|?a+i},:size,proc{26})

I'd posted a feature called `behavior' in [ruby-dev:25772].

  alphabet = Object.behaving(:) {|i|(?a+i).chr}
  p alphabet[20] #=> "u"

···

--
Nobu Nakada

Hi --

> Regarding duck-typing... Is there an easy way make a
"duck"?
> i.e. an object that responds to enough methods to be an
> acceptable argument to a certain method. For example, if
I
> have a method that takes aString and uses the #size and
#[i]
> methods, I could pass it something that looked just enough
like
> a String to work:
>
> alphabet = Object.duck(:,proc{|i|?a+i},:size,proc{26})
>
> The implementation I came up with is this:
>
> class Object
> def self.duck(*name_proc)
> duck = self.new
> duckclass = (class << duck;self;end)
> while not name_proc.empty?
> name,proc = name_proc.slice!(0,2)
> duckclass.send(:define_method,name,&proc)
> end
> duck
> end
> end
>
>
> Is there another way to do this? With all of the talk
about
> duck-typing, it seems like there would already be something

out there to

do
> this.

I've always understood "duck typing" to refer to a particular
approach
to the handling of method calls on objects, so I personally
wouldn't
expect a to see a correlation between the amount of talk
about duck
typing and this kind of technique. Your technique looks to
me like it
has more to do with the opposite end of the process: the
preparation
and priming of an object, as a way of creating a situation
favorable
to subsequent duck typing. I don't think what you've got
here stands
in any unique or special relation to duck typing; after all,
from the
duck typing perspective, a method that an object got from its
original
Class is just as much part of the object's behavior as a
method the
object got extended with later.

Correct. I'm looking at the other side - making an object (a
"duck") that works well with a method using duck-typing.

In fact... your technique actually calls to mind
Module#extend. Do
you have a case where you'd prefer to do it the way you've
done it
above, rather than defining the methods in a module and then
extending
your object with it?

I was wanting to define the duck in-line with arbitrary procs
for the methods. I'll give you a more concrete example using a
duck-typed method. Take enum.include?(obj) for example. It
searchs in enum something that matches obj using obj==element.
Let's say I wanted to match with obj===element or
obj.include?(element), etc. I could do these:

enum.include?(Object.duck(:==,range.method(:===)))
enum.include?(Object.duck(:==,set.method(:include?)))
enum.include?(Object.duck(:==,hash.method(:)))
enum.include?(Object.duck(:==,proc{|element|...}))

A special case that is very easily handled right now is if your
duck typing method takes an argument that only needs to respond
to . For example:

def scan_while(aHash)
    loop {
        ...
        aHash[element] or break
        ...
    }
end

scan_while(hash)
scan_while(proc{|element|...})
scan_while(set.method(:include?))
scan_while(range.method(:===))
scan_while(obj.method(:==))

···

--- "David A. Black" <dblack@wobblini.net> wrote:

On Tue, 7 Jun 2005, Eric Mahurin wrote:

__________________________________
Discover Yahoo!
Get on-the-go sports scores, stock quotes, news and more. Check it out!
http://discover.yahoo.com/mobile.html

For the example I gave above, I think you are correct. The
examples I gave in response to David Black are probably better
ones. With those, a simple "def" won't cut it. You need
define_method. But, using define_method is cumbersome from an
object because you first need to make it have a singleton
class, then use "send" to access it from that class because it
it a private method. Another solution to the problem of
"making a duck" would be to have a
Object#define_singleton_method:

class Object
    def define_singleton_method(name,&block)
        klass = (class << self;self;end)
        klass.send(:define_method,name,&block)
        self
    end
end

Then, for example, you could do this to make a set be useful
for a method that uses == for comparison:

seteq = Object.new.
    define_singleton_method(:==,&set.method(:include?))

I'm not sure why this isn't in Object right now. It seems like
the rest of the *singleton_method* methods are there.

···

--- Robert Klemme <bob.news@gmx.net> wrote:

Eric Mahurin wrote:
> Regarding duck-typing... Is there an easy way make a
"duck"?
> i.e. an object that responds to enough methods to be an
> acceptable argument to a certain methods. For example, if
I
> have a method that takes aString and uses the #size and
#[i]
> methods, I could pass it something that looked just enough
like
> a String to work:
>
> alphabet = Object.duck(:,proc{|i|?a+i},:size,proc{26})

Why aren't you satisfied with

class Alpha
  def (i) ?a+i end
  def size() 26 end
end
alphabet = Alpha.new

or

alphabet = Object.new
def alphabet.(i) ?a+i end
def alphabet.size() 26 end

You can even squeeze that on one line if you feel the need
for it. I
mean, you don't generate those methods dynamically or get
them from
somewhere else so why not just use the std approach?

__________________________________
Discover Yahoo!
Find restaurants, movies, travel and more fun for the weekend. Check it out!
http://discover.yahoo.com/weekend.html

Looks like 2 approaches to doing the same thing. I do like the
hash interface a little better. From your code that I read, it
looks like you can do this:

alphabet = Object.new.behaving(: => proc{|i|?a+i}, size:
proc{26})

I didn't know about the ":symbol => value" shortcut of "symbol:
value". Or forgot about it. Very nice in this situation.

Is there an advantage to having a separate Behavior class as
opposed the solution I had: making a singleton Object directly?

I think having something like this readily available would
promote more (interesting) uses of duck-typing.

···

--- nobu.nokada@softhome.net wrote:

Hi,

At Tue, 7 Jun 2005 01:00:23 +0900,
Eric Mahurin wrote in [ruby-talk:144691]:
> Regarding duck-typing... Is there an easy way make a
"duck"?
> i.e. an object that responds to enough methods to be an
> acceptable argument to a certain methods. For example, if
I
> have a method that takes aString and uses the #size and
#[i]
> methods, I could pass it something that looked just enough
like
> a String to work:
>
> alphabet = Object.duck(:,proc{|i|?a+i},:size,proc{26})

I'd posted a feature called `behavior' in [ruby-dev:25772].

  alphabet = Object.behaving(:) {|i|(?a+i).chr}
  p alphabet[20] #=> "u"

--
Nobu Nakada

__________________________________
Discover Yahoo!
Stay in touch with email, IM, photo sharing and more. Check it out!
http://discover.yahoo.com/stayintouch.html

gabriele renzi <surrender_it@remove-yahoo.it> writes:

Eric Mahurin ha scritto:

Is there another way to do this? With all of the talk about
duck-typing, there would already be something out there to do
this.

There was some talk in the past about Object.new taking a block, which
imho would be useful for this. Meanwhile what about using Struct.new
with a block to define methods?

Wow, this is nice... but where is it documented?

I used to use code like this until now:

class Foo < Struct.new(:all, :my, :fields)
  def mymethod
    # ...
  end
end

···

--
Christian Neukirchen <chneukirchen@gmail.com> http://chneukirchen.org

Hi,

At Tue, 7 Jun 2005 11:59:47 +0900,
Eric Mahurin wrote in [ruby-talk:144750]:

Is there an advantage to having a separate Behavior class as
opposed the solution I had: making a singleton Object directly?

To allow sharing same behavior.

···

--
Nobu Nakada

Eric Mahurin wrote:

Eric Mahurin wrote:

Regarding duck-typing... Is there an easy way make a

"duck"?

i.e. an object that responds to enough methods to be an
acceptable argument to a certain methods. For example, if

I

have a method that takes aString and uses the #size and

#[i]

methods, I could pass it something that looked just enough

like

a String to work:

alphabet = Object.duck(:,proc{|i|?a+i},:size,proc{26})

Why aren't you satisfied with

class Alpha
  def (i) ?a+i end
  def size() 26 end
end
alphabet = Alpha.new

or

alphabet = Object.new
def alphabet.(i) ?a+i end
def alphabet.size() 26 end

You can even squeeze that on one line if you feel the need
for it. I
mean, you don't generate those methods dynamically or get
them from
somewhere else so why not just use the std approach?

For the example I gave above, I think you are correct. The
examples I gave in response to David Black are probably better
ones. With those, a simple "def" won't cut it. You need
define_method. But, using define_method is cumbersome from an
object because you first need to make it have a singleton
class, then use "send" to access it from that class because it
it a private method. Another solution to the problem of
"making a duck" would be to have a
Object#define_singleton_method:

class Object
    def define_singleton_method(name,&block)
        klass = (class << self;self;end)
        klass.send(:define_method,name,&block)
        self
    end
end

Btw, you can also use class eval:

class Object
    def define_singleton_method(name,&block)
        klass = (class << self;self;end).class_eval do
          define_method(name,&block)
        end
        self
    end
end

and also

o=Object.new
class <<o;self;end.class_eval do
  def bax() "bar" end
end
o.bax

Then, for example, you could do this to make a set be useful
for a method that uses == for comparison:

seteq = Object.new.
    define_singleton_method(:==,&set.method(:include?))

This does not work. You cannot transfer a method from one class to
another:

09:14:01 [ruby]: cat define.rb

class Foo
  def test() bar() end
  def bar() "FOO::BAR" end
end

class Bar
  def bar() "BAR::BAR" end
end

bar = Bar.new
bar_kl = (class<<bar;self;end)
bar_kl.send(:define_method, :xxx, Foo.new.method(:test))
bar_kl.send(:public, :xxx)

bar.xxx()
09:15:33 [ruby]: ruby define.rb
define.rb:16:in `xxx': bind argument must be an instance of Foo
(TypeError)
        from define.rb:16

I'm not sure why this isn't in Object right now. It seems like
the rest of the *singleton_method* methods are there.

Probably because it doesn't work - at least not completely the way you
like to have it. Btw, and if you're borrowing implementations from other
classes then you can directly use an instance of that class...

Kind regards

    robert

···

--- Robert Klemme <bob.news@gmx.net> wrote:

So is Struct.new(&block) equivalent to:

StructClass = Struct.new
StructClass.instance_eval(&block)
StructClass

So you could do this to make an object using == to map to ===
of a range.

alpha = ('a'..'z')
alphaeq =
Struct.new(:dummy){define_method(:==,&alpha.method(:===))}.new

Actually it looks like you can do the same thing with Class:

alpha = ('a'..'z')
alphaeq = Class.new{define_method(:==,&alpha.method(:===))}.new

This is still pretty verbose, but it seems like a descent
solution. I'll use this until something better comes along.

···

--- Christian Neukirchen <chneukirchen@gmail.com> wrote:

gabriele renzi <surrender_it@remove-yahoo.it> writes:
> Eric Mahurin ha scritto:
>
>> Is there another way to do this? With all of the talk
about
>> duck-typing, there would already be something out there to
do
>> this.
>
> There was some talk in the past about Object.new taking a
block, which
> imho would be useful for this. Meanwhile what about using
Struct.new
> with a block to define methods?

Wow, this is nice... but where is it documented?

I used to use code like this until now:

class Foo < Struct.new(:all, :my, :fields)
  def mymethod
    # ...
  end
end

__________________________________
Discover Yahoo!
Stay in touch with email, IM, photo sharing and more. Check it out!
http://discover.yahoo.com/stayintouch.html

If you put an & in front of your "Foo.new.method(:test)" (like
what I did), or .to_proc it will work fine.

···

--- Robert Klemme <bob.news@gmx.net> wrote:

Eric Mahurin wrote:
> --- Robert Klemme <bob.news@gmx.net> wrote:
>
>> Eric Mahurin wrote:
>>> Regarding duck-typing... Is there an easy way make a
>> "duck"?
>>> i.e. an object that responds to enough methods to be an
>>> acceptable argument to a certain methods. For example,
if
>> I
>>> have a method that takes aString and uses the #size and
>> #[i]
>>> methods, I could pass it something that looked just
enough
>> like
>>> a String to work:
>>>
>>> alphabet = Object.duck(:,proc{|i|?a+i},:size,proc{26})
>>
>> Why aren't you satisfied with
>>
>> class Alpha
>> def (i) ?a+i end
>> def size() 26 end
>> end
>> alphabet = Alpha.new
>>
>> or
>>
>> alphabet = Object.new
>> def alphabet.(i) ?a+i end
>> def alphabet.size() 26 end
>>
>> You can even squeeze that on one line if you feel the need
>> for it. I
>> mean, you don't generate those methods dynamically or get
>> them from
>> somewhere else so why not just use the std approach?
>
> For the example I gave above, I think you are correct. The
> examples I gave in response to David Black are probably
better
> ones. With those, a simple "def" won't cut it. You need
> define_method. But, using define_method is cumbersome from
an
> object because you first need to make it have a singleton
> class, then use "send" to access it from that class because
it
> it a private method. Another solution to the problem of
> "making a duck" would be to have a
> Object#define_singleton_method:
>
> class Object
> def define_singleton_method(name,&block)
> klass = (class << self;self;end)
> klass.send(:define_method,name,&block)
> self
> end
> end

Btw, you can also use class eval:

class Object
    def define_singleton_method(name,&block)
        klass = (class << self;self;end).class_eval do
          define_method(name,&block)
        end
        self
    end
end

and also

o=Object.new
class <<o;self;end.class_eval do
  def bax() "bar" end
end
o.bax

> Then, for example, you could do this to make a set be
useful
> for a method that uses == for comparison:
>
> seteq = Object.new.
> define_singleton_method(:==,&set.method(:include?))

This does not work. You cannot transfer a method from one
class to
another:

09:14:01 [ruby]: cat define.rb

class Foo
  def test() bar() end
  def bar() "FOO::BAR" end
end

class Bar
  def bar() "BAR::BAR" end
end

bar = Bar.new
bar_kl = (class<<bar;self;end)
bar_kl.send(:define_method, :xxx, Foo.new.method(:test))
bar_kl.send(:public, :xxx)

bar.xxx()
09:15:33 [ruby]: ruby define.rb
define.rb:16:in `xxx': bind argument must be an instance of
Foo
(TypeError)
        from define.rb:16

__________________________________
Discover Yahoo!
Use Yahoo! to plan a weekend, have fun online and more. Check it out!
http://discover.yahoo.com/

I'm not sure how much application this would have over the
conventional class definition approach.

At first I didn't think this would work because I thought you
wouldn't be able to create any instance variables using
define_method. I thought any @ variables in a proc would refer
to the @ variable in the original context, but define_method
apparently rebinds them to the object.

···

--- nobu.nokada@softhome.net wrote:

At Tue, 7 Jun 2005 11:59:47 +0900,
Eric Mahurin wrote in [ruby-talk:144750]:
> Is there an advantage to having a separate Behavior class
as
> opposed the solution I had: making a singleton Object
directly?

To allow sharing same behavior.

__________________________________
Discover Yahoo!
Use Yahoo! to plan a weekend, have fun online and more. Check it out!
http://discover.yahoo.com/

Eric Mahurin ha scritto:

gabriele renzi <surrender_it@remove-yahoo.it> writes:

Eric Mahurin ha scritto:

Is there another way to do this? With all of the talk

about

duck-typing, there would already be something out there to

do

this.

There was some talk in the past about Object.new taking a

block, which

imho would be useful for this. Meanwhile what about using

Struct.new

with a block to define methods?

Wow, this is nice... but where is it documented?

nowhere, it seem. But I remebered it was discussed on ruby-core and tried it :slight_smile:

<snip>

So is Struct.new(&block) equivalent to:

StructClass = Struct.new
StructClass.instance_eval(&block)
StructClass

no, class_eval, and you have to submit at least one arg to Struct.new :confused:

···

--- Christian Neukirchen <chneukirchen@gmail.com> wrote:

Eric Mahurin wrote:

Eric Mahurin wrote:

Eric Mahurin wrote:

Regarding duck-typing... Is there an easy way make a

"duck"?

i.e. an object that responds to enough methods to be an
acceptable argument to a certain methods. For example, if I
have a method that takes aString and uses the #size and

#[i]

methods, I could pass it something that looked just enough like
a String to work:

alphabet = Object.duck(:,proc{|i|?a+i},:size,proc{26})

Why aren't you satisfied with

class Alpha
  def (i) ?a+i end
  def size() 26 end
end
alphabet = Alpha.new

or

alphabet = Object.new
def alphabet.(i) ?a+i end
def alphabet.size() 26 end

You can even squeeze that on one line if you feel the need
for it. I
mean, you don't generate those methods dynamically or get
them from
somewhere else so why not just use the std approach?

For the example I gave above, I think you are correct. The
examples I gave in response to David Black are probably

better

ones. With those, a simple "def" won't cut it. You need
define_method. But, using define_method is cumbersome from

an

object because you first need to make it have a singleton
class, then use "send" to access it from that class because

it

it a private method. Another solution to the problem of
"making a duck" would be to have a
Object#define_singleton_method:

class Object
    def define_singleton_method(name,&block)
        klass = (class << self;self;end)
        klass.send(:define_method,name,&block)
        self
    end
end

Btw, you can also use class eval:

class Object
    def define_singleton_method(name,&block)
        klass = (class << self;self;end).class_eval do
          define_method(name,&block)
        end
        self
    end
end

and also

o=Object.new
class <<o;self;end.class_eval do
  def bax() "bar" end
end
o.bax

Then, for example, you could do this to make a set be

useful

for a method that uses == for comparison:

seteq = Object.new.
    define_singleton_method(:==,&set.method(:include?))

This does not work. You cannot transfer a method from one
class to
another:

09:14:01 [ruby]: cat define.rb

class Foo
  def test() bar() end
  def bar() "FOO::BAR" end
end

class Bar
  def bar() "BAR::BAR" end
end

bar = Bar.new
bar_kl = (class<<bar;self;end)
bar_kl.send(:define_method, :xxx, Foo.new.method(:test))
bar_kl.send(:public, :xxx)

bar.xxx()
09:15:33 [ruby]: ruby define.rb
define.rb:16:in `xxx': bind argument must be an instance of
Foo
(TypeError)
        from define.rb:16

If you put an & in front of your "Foo.new.method(:test)" (like
what I did), or .to_proc it will work fine.

Darn, though I had the & in there. However, there's another problem which
I originally wanted to demonstrate with this setup: methods might not
behave as one would expect:

16:31:16 [ruby]: cat define.rb

class Foo
  def test() bar() end
  def bar() "FOO::BAR" end
end

class Bar
  def bar() "BAR::BAR" end
end

bar = Bar.new
bar_kl = (class<<bar;self;end)
bar_kl.send(:define_method, :xxx, &Foo.new.method(:test))
bar_kl.send(:public, :xxx)

p bar.xxx()
16:31:16 [ruby]: ruby define.rb
"FOO::BAR"

Foo::test is still bound to Foo::bar and you probably would rather see
Bar::bar being called.

Kind regards

    robert

···

--- Robert Klemme <bob.news@gmx.net> wrote:

--- Robert Klemme <bob.news@gmx.net> wrote:

Eric Mahurin wrote:

At Tue, 7 Jun 2005 11:59:47 +0900,
Eric Mahurin wrote in [ruby-talk:144750]:

Is there an advantage to having a separate Behavior class

as

opposed the solution I had: making a singleton Object

directly?

To allow sharing same behavior.

I'm not sure how much application this would have over the
conventional class definition approach.

At first I didn't think this would work because I thought you
wouldn't be able to create any instance variables using
define_method. I thought any @ variables in a proc would refer
to the @ variable in the original context, but define_method
apparently rebinds them to the object.

I always remind myself that the binding of "self" changes - even for each
method invocation. This explains pretty good why this works as it should.

16:31:18 [ruby]: ruby x.rb
4
666
666
16:38:10 [ruby]: cat x.rb
o=Object.new
def o.size() 666 end
x="test"

class<<o;self;end.class_eval do
  define_method(:test) do
    puts x.size
    puts self.size
    puts size
  end
end

o.test
16:38:14 [ruby]:

Kind regards

    robert

···

--- nobu.nokada@softhome.net wrote:

define_method, instance_eval, class_eval, module_eval, and
maybe others seem to have this special ability - rebind the
meaning of self (but not locals) for a Proc. This brings us
back to the topic I talked about earlier - unbind/rebind procs.
It would be nice if we could do the same thing to a Proc that
these methods can do internally:

aProc.rebind_self(obj) -> aNewProc # rebind what self is

With this, "obj.instance_eval(&proc)" would be equivalent to
"proc.rebind_self(obj).call". Other useful rebindings may be:

aProc.rebind_locals(binding) -> aNewProc
aProc.rebind_all(binding) -> aNewProc
# replace local variables with their current values
aProc.unbind_locals -> aNewProc

BTW, I don't see the value that class_eval and module_eval
provide over instance_eval. classes and modules can be treated
like instances just like any other object.

···

--- Robert Klemme <bob.news@gmx.net> wrote:

Eric Mahurin wrote:
> --- nobu.nokada@softhome.net wrote:
>> At Tue, 7 Jun 2005 11:59:47 +0900,
>> Eric Mahurin wrote in [ruby-talk:144750]:
>>> Is there an advantage to having a separate Behavior class
>> as
>>> opposed the solution I had: making a singleton Object
>> directly?
>>
>> To allow sharing same behavior.
>
> I'm not sure how much application this would have over the
> conventional class definition approach.
>
> At first I didn't think this would work because I thought
you
> wouldn't be able to create any instance variables using
> define_method. I thought any @ variables in a proc would
refer
> to the @ variable in the original context, but
define_method
> apparently rebinds them to the object.

I always remind myself that the binding of "self" changes -
even for each
method invocation. This explains pretty good why this works
as it should.

__________________________________
Discover Yahoo!
Get on-the-go sports scores, stock quotes, news and more. Check it out!
http://discover.yahoo.com/mobile.html

"Eric Mahurin" <eric_mahurin@yahoo.com> schrieb im Newsbeitrag news:20050607162716.28170.qmail@web41115.mail.yahoo.com...

Eric Mahurin wrote:
>> At Tue, 7 Jun 2005 11:59:47 +0900,
>> Eric Mahurin wrote in [ruby-talk:144750]:
>>> Is there an advantage to having a separate Behavior class
>> as
>>> opposed the solution I had: making a singleton Object
>> directly?
>>
>> To allow sharing same behavior.
>
> I'm not sure how much application this would have over the
> conventional class definition approach.
>
> At first I didn't think this would work because I thought
you
> wouldn't be able to create any instance variables using
> define_method. I thought any @ variables in a proc would
refer
> to the @ variable in the original context, but
define_method
> apparently rebinds them to the object.

I always remind myself that the binding of "self" changes -
even for each
method invocation. This explains pretty good why this works
as it should.

define_method, instance_eval, class_eval, module_eval, and
maybe others seem to have this special ability - rebind the
meaning of self (but not locals) for a Proc. This brings us
back to the topic I talked about earlier - unbind/rebind procs.
It would be nice if we could do the same thing to a Proc that
these methods can do internally:

aProc.rebind_self(obj) -> aNewProc # rebind what self is

With this, "obj.instance_eval(&proc)" would be equivalent to
"proc.rebind_self(obj).call".

Why do you want rebind if the other approach is much simpler? #instance_eval *always* rebinds self (and only self).

Other useful rebindings may be:

aProc.rebind_locals(binding) -> aNewProc
aProc.rebind_all(binding) -> aNewProc
# replace local variables with their current values
aProc.unbind_locals -> aNewProc

When do you think will unbind_locals be useful? A proc typically needs some of the variables bound. As for the rebindings, I would prefer a general mechanism to transfer state from one binding to another. Then one could implement all your rebind* methods in terms of that general mechanism plus do more. Alternatively one could think about conversion methods Binding <-> Hash.

BTW, I don't see the value that class_eval and module_eval
provide over instance_eval. classes and modules can be treated
like instances just like any other object.

class_eval and instance_eval are not equivalent:

class Foo;end

=> nil

Foo.class_eval do

?> def bar() "bar" end

end

=> nil

Foo.new.bar

=> "bar"

Foo.instance_eval do

?> def bax() "bax" end

end

=> nil

Foo.new.bax

NoMethodError: undefined method `bax' for #<Foo:0x10179ee0>
        from (irb):12

Kind regards

    robert

···

--- Robert Klemme <bob.news@gmx.net> wrote:

> --- nobu.nokada@softhome.net wrote: