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:
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.
> 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:
> 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?
On Tue, 7 Jun 2005, 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:
> 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?
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:
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?
> > 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:
> > 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:
__________________________________ Discover Yahoo! Get on-the-go sports scores, stock quotes, news and more. Check it out! http://discover.yahoo.com/mobile.html
> 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:
> 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
Then, for example, you could do this to make a set be useful for a method that uses == for comparison:
I'm not sure why this isn't in Object right now. It seems like the rest of the *singleton_method* methods are there.
__________________________________ Discover Yahoo! Find restaurants, movies, travel and more fun for the weekend. Check it out! http://discover.yahoo.com/weekend.html
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:
> 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:
> I'd posted a feature called `behavior' in [ruby-dev:25772].
> alphabet = Object.behaving(:[]) {|i|(?a+i).chr} > p alphabet[20] #=> "u"
> -- > Nobu Nakada
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:
Eric Mahurin wrote: > --- Robert Klemme <bob.n...@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:
>> 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:
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...
> Eric Mahurin wrote: > > --- Robert Klemme <bob.n...@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:
> >> 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:
--- nobu.nok...@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.
__________________________________ Discover Yahoo! Use Yahoo! to plan a weekend, have fun online and more. Check it out! http://discover.yahoo.com/
Eric Mahurin wrote: > --- nobu.nok...@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.
Eric Mahurin wrote: > --- Robert Klemme <bob.n...@gmx.net> wrote:
>> Eric Mahurin wrote: >>> --- Robert Klemme <bob.n...@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:
>>>> 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:
>> 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
> Eric Mahurin wrote: > > --- nobu.nok...@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.
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.
__________________________________ Discover Yahoo! Get on-the-go sports scores, stock quotes, news and more. Check it out! http://discover.yahoo.com/mobile.html
gabriele renzi <surrender...@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
> gabriele renzi <surrender...@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
> --- Robert Klemme <bob.n...@gmx.net> wrote: >> Eric Mahurin wrote: >> > --- nobu.nok...@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.
> 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
> > 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).
because you can get a handle on that rebound Proc. You might want to pass it around or whatever.
> > 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?
As a replacement for many string evals - which are ugly, inefficient, and possibly dangerous. Many (most?) times that you need to eval a string it is because you need to pull in some local variables to help define the string to be evaled. Here is the first example of a string eval in the 1.8 library I found:
for element in %w[ HTML HEAD BODY P PLAINTEXT DT DD LI OPTION tr th td ] methods += <<-BEGIN + nO_element_def(element) + <<-END def #{element.downcase}(attributes = {}) BEGIN end END end eval(methods)
This could be replaced by:
for element in %w[ HTML HEAD BODY P PLAINTEXT DT DD LI OPTION tr th td ] define_method(element.downcase.to_sym , proc { |attributes={}| nO_element_def(element) }.unbind_locals # replace element with constant ) end
Much cleaner, huh?
> 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.
Transferring locals might be pretty easy, but transferring the meaning of self would be more difficult, I think. At least without making a new Binding (and then you'd still need a way to rebind it to the original proc).
> > 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
Interesting. I assumed that since class_eval/instance_eval/module_eval all returned the same "self" that they did the same thing. The only difference I see is in "def <method> ...". With class_eval, it defines instance methods and with instance_eval, it defines class methods. That's kind of strange. Some kind of magic is going on here other than the changing of self.
I was hoping that instance_eval could be used to define class methods using #define_method, but #define_method does the same with both - defines instance methods. Anybody know of an equivalent to #define_method for making class methods? I couldn't figure out any way to define a class method from a proc - just out of curiosity.
>>>>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.
I think of self as a dynamic variable, outside of lexical scope and that makes me think..
> 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
.. would dynamic variables be enough? Christian Neukirchen has a nifty implementation of them on his blog.
<snip>
> 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.
if you define a method in a class_eval/module_eval block on object X ruby will define it in instances of X while if you use instance_eval you'd define the method on the object X
> Eric Mahurin ha scritto: > > 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
> ... would dynamic variables be enough? Christian Neukirchen > has a nifty > implementation of them on his blog.
From what I saw, this didn't seem much different than another space for global variables. The main ability I was wanting was to be able to replace local variables with their current value in a proc. I think this would make the ugly *eval(string) methods rarely needed. I just looked through the stdlib and found almost every occurence of *eval(string) and found almost every one looks kind of like this:
name = ... var = ... eval("def #{name} .... #{var} .... end")
This would work:
name = ... var = ... define_method(name.to_sym,proc{.... var ....}.unbind)
assuming that Proc#unbind replaced "var" with its current value.
A define_class_method method would also be useful. Otherwise there would be no equivalent to the above when doing eval("def self.#{name} .... end").
__________________________________ Discover Yahoo! Find restaurants, movies, travel and more fun for the weekend. Check it out! http://discover.yahoo.com/weekend.html
Eric Mahurin wrote: > --- Robert Klemme <bob.n...@gmx.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".
>> Why do you want rebind if the other approach is much simpler?
>> #instance_eval *always* rebinds self (and only self).
> because you can get a handle on that rebound Proc. You might > want to pass it around or whatever.
I see. Although I don't have a use case for this at hand and in fact never missed that. But that might be just my personal experience.
>>> 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?
> As a replacement for many string evals - which are ugly, > inefficient, and possibly dangerous. Many (most?) times that > you need to eval a string it is because you need to pull in > some local variables to help define the string to be evaled. > Here is the first example of a string eval in the 1.8 library I > found:
> for element in %w[ HTML HEAD BODY P PLAINTEXT DT DD > LI OPTION tr th td ] > methods += <<-BEGIN + nO_element_def(element) + <<-END > def #{element.downcase}(attributes = {}) > BEGIN > end > END > end > eval(methods)
> This could be replaced by:
> for element in %w[ HTML HEAD BODY P PLAINTEXT DT DD > LI OPTION tr th td ] > define_method(element.downcase.to_sym , > proc { |attributes={}| > nO_element_def(element) > }.unbind_locals # replace element with constant > ) > end
> Much cleaner, huh?
Not really (at least to my eyes). Also, there are some issues:
- I don't know what nO_element_def does exactly, but it will have to be rewritten to not create a string with ruby code
- Your version might be less efficient.
- There might be subtle differences because "element" is pulled into the closure
- Also, unbind_locals will remove "element" from the procs bindings
>> 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.
> Transferring locals might be pretty easy, but transferring the > meaning of self would be more difficult, I think. At least > without making a new Binding (and then you'd still need a way > to rebind it to the original proc).
Why do you think that self is special? If there is a general mechanism to transfer state (i.e. bindings) into a binding, any variable can be rebound. I imagine something like
> Interesting. I assumed that since > class_eval/instance_eval/module_eval all returned the same > "self" that they did the same thing. The only difference I see > is in "def <method> ...". With class_eval, it defines instance > methods and with instance_eval, it defines class methods. > That's kind of strange. Some kind of magic is going on here > other than the changing of self.
Definitely.
> I was hoping that instance_eval could be used to define class > methods using #define_method, but #define_method does the same > with both - defines instance methods. Anybody know of an > equivalent to #define_method for making class methods? I > couldn't figure out any way to define a class method from a > proc - just out of curiosity.
Since a class method is just an instance method of the class:
>> class Foo;end => nil >> class <<Foo >> define_method(:bar) {"bar"} >> end
> >> When do you think will unbind_locals be useful?
> > As a replacement for many string evals - which are ugly, > > inefficient, and possibly dangerous. Many (most?) times > that > > you need to eval a string it is because you need to pull in > > some local variables to help define the string to be > evaled. > > Here is the first example of a string eval in the 1.8 > library I > > found:
> > for element in %w[ HTML HEAD BODY P PLAINTEXT DT DD > > LI OPTION tr th td ] > > methods += <<-BEGIN + nO_element_def(element) + <<-END > > def #{element.downcase}(attributes = {}) > > BEGIN > > end > > END > > end > > eval(methods)
> > This could be replaced by:
> > for element in %w[ HTML HEAD BODY P PLAINTEXT DT DD > > LI OPTION tr th td ] > > define_method(element.downcase.to_sym , > > proc { |attributes={}| > > nO_element_def(element,attributes) > > }.unbind_locals # replace element with constant > > ) > > end
> > Much cleaner, huh?
> Not really (at least to my eyes). Also, there are some > issues:
> - I don't know what nO_element_def does exactly, but it will > have to be > rewritten to not create a string with ruby code
Yep. I wasn't paying attention very well. Here is its definition (this is from cgi.rb, BTW):
def nOE_element_def(element, append = nil) s = <<-END "<#{element.upcase}" + attributes.collect{|name, value| next unless value " " + CGI::escapeHTML(name) + if true == value "" else '="' + CGI::escapeHTML(value) + '"' end }.to_s + ">" END s.sub!(/\Z/, " +") << append if append s end def nO_element_def(element) nOE_element_def(element, <<-END) if block_given? yield.to_s + "</#{element.upcase}>" else "" end END end
Here would be the evaluating (instead of generating) version:
def nOE_element_def(element,attributes) "<#{element.upcase}" + attributes.collect{|name, value| next unless value " " + CGI::escapeHTML(name) + if true == value "" else '="' + CGI::escapeHTML(value) + '"' end }.to_s + ">" end def nO_element_def(element,attributes) nOE_element_def(element,attributes) + if block_given? yield.to_s + "<#{element.upcase}>" else "" end end
> - Your version might be less efficient.
If you flatten the hierarchy, you should be able to get the same efficiency:
for element in %w[ HTML HEAD BODY P PLAINTEXT DT DD LI OPTION tr th td ] define_method(element.downcase.to_sym , proc { |attributes={}| "<#{element.upcase}" + attributes.collect{|name, value| next unless value " " + CGI::escapeHTML(name) + if true == value "" else '="' + CGI::escapeHTML(value) + '"' end }.to_s + ">" + if block_given? yield.to_s + "<#{element.upcase}>" else "" end }.unbind_locals # replace element with constant ) end
> - There might be subtle differences because "element" is > pulled into the > closure
> - Also, unbind_locals will remove "element" from the procs > bindings
I'm assuming that unbind_locals will simply replace any local variables (external to the proc) with what their current value is: element will become "HTML", "HEAD", "BODY", etc.
> >> 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.
> > Transferring locals might be pretty easy, but transferring > the > > meaning of self would be more difficult, I think. At least > > without making a new Binding (and then you'd still need a > way > > to rebind it to the original proc).
> Why do you think that self is special? If there is a general > mechanism to > transfer state (i.e. bindings) into a binding, any variable > can be > rebound. I imagine something like
I was assuming that with local variables, you just be moving the value from one binding to another - not aliasing. The problem is that you can't assign to "self". If you really could do the above, then this:
binding.bind(:self => whatever)
would be equivalent to:
self = whatever
I don't that would be a trivial thing to implement. But, if this "bind" created a new binding (i.e. non-destructive instead of destructive), it would seem more feasible:
But then you are back to where you started - you still have a bind the proc to a different binding (probably returning a new proc).
> > Anybody know of an > > equivalent to #define_method for making class methods? I > > couldn't figure out any way to define a class method from a > > proc - just out of curiosity.
> Since a class method is just an instance method of the class:
> >> class Foo;end > => nil > >> class <<Foo > >> define_method(:bar) {"bar"} > >> end
Thanks! That works, but I wanted the proc to have visibility to the local variables. I think this would be more useful:
class Foo;end (class<<Foo;self;end).send(:define_method,:bar) {"bar"}
> Thanks for the interesting exchange!
and thanks for your ideas.
.. back to my original topic - making a duck. For my stuff, I think I've decided to have 2 ways of doing it:
# make a duck using methods from obj myDuck = obj.duck(newSym, oldSym, ...)
# make a duck using arbitrary procs myDuck = duck(methSym => methProc, ...)
One of the applications I'm looking at now is for a method that looks like this:
Cursor#scan(value)
where value is String/Array like. All it needs is to respond to #[int] which should return an object that responds to #==. Although this #scan may look like it just matches to a verbatim String/Array, you could also do something like this to match to some digits:
# make == look like === digit = (?0..?9).duck(:==,:===) # match to a string of 4 digits # Proc responds to [] like a String/Array cursor.scan(proc{|i|(i<4)? digit : nil})
Do people do things like this with duck-typing? Or are most just all talk. Doing something like the above is where I see the power.
__________________________________ Discover Yahoo! Use Yahoo! to plan a weekend, have fun online and more. Check it out! http://discover.yahoo.com/