[lnkForumImage]
TotalShareware - Download Free Software

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


 

Forums >

comp.lang.ruby

Changing enum_obj

Trans

6/24/2007 4:07:00 AM

Anyway to change an Enumerator's enum_obj in place? Enumerator doesn't
seem to support the #collect! method.

T.


10 Answers

James Gray

6/24/2007 4:27:00 AM

0

On Jun 23, 2007, at 11:07 PM, Trans wrote:

> Anyway to change an Enumerator's enum_obj in place? Enumerator doesn't
> seem to support the #collect! method.

Knowing that an object is Enumerable doesn't tell you anything about
how to edit it, so there's no way Enumerable could logically support
destructive operations.

James Edward Gray II


Trans

6/24/2007 4:33:00 AM

0



On Jun 24, 12:26 am, James Edward Gray II <j...@grayproductions.net>
wrote:
> On Jun 23, 2007, at 11:07 PM, Trans wrote:
>
> > Anyway to change an Enumerator's enum_obj in place? Enumerator doesn't
> > seem to support the #collect! method.
>
> Knowing that an object is Enumerable doesn't tell you anything about
> how to edit it, so there's no way Enumerable could logically support
> destructive operations.

Ah, of course.

Thanks,
T.


Trans

6/24/2007 5:05:00 AM

0

Well, I might as well bring up the reason I asked about enum_obj...

Spending some time improving Facets' Elementor class concept and
#every method, I find this possible utter simplification:

class Enumerable::Enumerator
def method_missing(sym, *args, &blk)
self.class.new(collect{ |e| e.send(sym, *args, &blk) })
end
end

Example:

a = [1,2,3]
e = a.to_enum
e += 3
e *= 2
e.to_a #=> [8,10,11]

T.


Robert Dober

6/24/2007 8:15:00 AM

0

On 6/24/07, Trans <transfire@gmail.com> wrote:
> Well, I might as well bring up the reason I asked about enum_obj...
>
> Spending some time improving Facets' Elementor class concept and
> #every method, I find this possible utter simplification:
>
> class Enumerable::Enumerator
> def method_missing(sym, *args, &blk)
> self.class.new(collect{ |e| e.send(sym, *args, &blk) })
> end
> end
>
> Example:
>
> a = [1,2,3]
> e = a.to_enum
> e += 3
> e *= 2
> e.to_a #=> [8,10,11]
>
> T.

Apart the magic dot notation that is *exactly* what I am doing in Labrador.
Well I cannot expect blocks in this way as they have the original
purpose and are sent to map.

module Enumerable

alias_method :__map_l1, :map
#
# The behavior of map {...} is unchanged.
# map(arg1, *rest) simply is translated to map{ |ele| ele.send(arg1, *rest) }
# map(arg1, *rest){...} is translated to map{|ele|
ele.send(arg1,*rest}.map{...}
# map without any arguments creates a Dispatcher Proxy that will
dispatch all messages
# to the elements of the receiver.
#
# All the following expressions evaluate therefore to the same result:
# ary=[*0..9]
# ary.map{ |x| x + 1}
# ary.map(:succ)
# ary.map.succ
# ary.map(:+, 1)
# ary.map + 1
def map *args, &blk
return Labrador::Dispatcher.new( self, :map ) if args.empty? && blk.nil?
return __map_l1( &blk ) if args.empty?
return __map_l1 { |x| x.send( *args ) } if blk.nil?
__map_l1 { |x| x.send( *args ) }.__map_l1( &blk )
end # def map *args, &blk

end # module Enumerable



Robert
--
You see things; and you say Why?
But I dream things that never were; and I say Why not?
-- George Bernard Shaw

Trans

6/24/2007 10:36:00 AM

0



On Jun 24, 4:15 am, "Robert Dober" <robert.do...@gmail.com> wrote:
> On 6/24/07, Trans <transf...@gmail.com> wrote:
>
>
>
> > Well, I might as well bring up the reason I asked about enum_obj...
>
> > Spending some time improving Facets' Elementor class concept and
> > #every method, I find this possible utter simplification:
>
> > class Enumerable::Enumerator
> > def method_missing(sym, *args, &blk)
> > self.class.new(collect{ |e| e.send(sym, *args, &blk) })
> > end
> > end
>
> > Example:
>
> > a = [1,2,3]
> > e = a.to_enum
> > e += 3
> > e *= 2
> > e.to_a #=> [8,10,11]
>
> > T.
>
> Apart the magic dot notation that is *exactly* what I am doing in Labrador.
> Well I cannot expect blocks in this way as they have the original
> purpose and are sent to map.
>
> module Enumerable
>
> alias_method :__map_l1, :map
> #
> # The behavior of map {...} is unchanged.
> # map(arg1, *rest) simply is translated to map{ |ele| ele.send(arg1, *rest) }
> # map(arg1, *rest){...} is translated to map{|ele|
> ele.send(arg1,*rest}.map{...}
> # map without any arguments creates a Dispatcher Proxy that will
> dispatch all messages
> # to the elements of the receiver.
> #
> # All the following expressions evaluate therefore to the same result:
> # ary=[*0..9]
> # ary.map{ |x| x + 1}
> # ary.map(:succ)
> # ary.map.succ
> # ary.map(:+, 1)
> # ary.map + 1
> def map *args, &blk
> return Labrador::Dispatcher.new( self, :map ) if args.empty? && blk.nil?
> return __map_l1( &blk ) if args.empty?
> return __map_l1 { |x| x.send( *args ) } if blk.nil?
> __map_l1 { |x| x.send( *args ) }.__map_l1( &blk )
> end # def map *args, &blk
>
> end # module Enumerable

Ah, so you overloaded #map with this functionality. That's similar to
what I had done, but I used a different method name, #every, which is
defined:

module Enumerable
def every
@_functor_every ||= Functor.new do |op,*args|
self.collect{ |a| a.send(op,*args) }
end
end
end

Both are limited in one common respect. They can't be chained along
without repeated invocation, eg. it's not

[1,2,3].map * 6 + 4

We have to do:

([1,2,3].map * 6).map + 4

Not quite as bad for #map, as opposed to #every, being shorter, but it
would still be nice to chain. Of course, to do that one must
explicitly #to_a the final result per my original Enumerator example.

One thing you might want to consider, Ruby 1.9+ returns an Enumerator
for #map without a block, could pose some compatibility issues in the
future. Though, I have to admit I'm not quite sure what a #map based
Enumerator is good for -- when you run #each on it, it acts like
#map !!!

T.


Robert Dober

6/24/2007 11:05:00 AM

0

On 6/24/07, Trans <transfire@gmail.com> wrote:
>
>
> On Jun 24, 4:15 am, "Robert Dober" <robert.do...@gmail.com> wrote:
> > On 6/24/07, Trans <transf...@gmail.com> wrote:
> >
> >
> >
> > > Well, I might as well bring up the reason I asked about enum_obj...
> >
> > > Spending some time improving Facets' Elementor class concept and
> > > #every method, I find this possible utter simplification:
> >
> > > class Enumerable::Enumerator
> > > def method_missing(sym, *args, &blk)
> > > self.class.new(collect{ |e| e.send(sym, *args, &blk) })
> > > end
> > > end
> >
> > > Example:
> >
> > > a = [1,2,3]
> > > e = a.to_enum
> > > e += 3
> > > e *= 2
> > > e.to_a #=> [8,10,11]
> >
> > > T.
> >
> > Apart the magic dot notation that is *exactly* what I am doing in Labrador.
> > Well I cannot expect blocks in this way as they have the original
> > purpose and are sent to map.
> >
> > module Enumerable
> >
> > alias_method :__map_l1, :map
> > #
> > # The behavior of map {...} is unchanged.
> > # map(arg1, *rest) simply is translated to map{ |ele| ele.send(arg1, *rest) }
> > # map(arg1, *rest){...} is translated to map{|ele|
> > ele.send(arg1,*rest}.map{...}
> > # map without any arguments creates a Dispatcher Proxy that will
> > dispatch all messages
> > # to the elements of the receiver.
> > #
> > # All the following expressions evaluate therefore to the same result:
> > # ary=[*0..9]
> > # ary.map{ |x| x + 1}
> > # ary.map(:succ)
> > # ary.map.succ
> > # ary.map(:+, 1)
> > # ary.map + 1
> > def map *args, &blk
> > return Labrador::Dispatcher.new( self, :map ) if args.empty? && blk.nil?
> > return __map_l1( &blk ) if args.empty?
> > return __map_l1 { |x| x.send( *args ) } if blk.nil?
> > __map_l1 { |x| x.send( *args ) }.__map_l1( &blk )
> > end # def map *args, &blk
> >
> > end # module Enumerable
>
> Ah, so you overloaded #map with this functionality. That's similar to
> what I had done, but I used a different method name, #every, which is
> defined:
Facets is great but Labrador is mine, what does that mean: I have the
luxury to do things that scale badly and break compatibility, -- I
have to make the documentation clear about this in the next version.
Facets is a General Purpose Library and cannot afford that luxury, so
it is very clear why you have #every -- a tempting idea not to
overload map, even in an experimental package as my dog package. Yet
another advantage, I just change the name, nobody can complain...
OTH I am surprised that #every corresponds to #map, from its naming on
would say it should correspond to #each.
>
> module Enumerable
> def every
> @_functor_every ||= Functor.new do |op,*args|
> self.collect{ |a| a.send(op,*args) }
> end
> end
> end
>
I gotta look at your Functors again, maybe I can steal a little bit from you;)
> Both are limited in one common respect. They can't be chained along
> without repeated invocation, eg. it's not
>
> [1,2,3].map * 6 + 4
That is even broken in Labrador, so much work to do :(

irb(main):001:0> require 'labrador'
=> true
irb(main):002:0> [1,2,3].map + 2
=> [3, 4, 5]
irb(main):003:0> [1,2,3].map + 2 * 3
=> [7, 8, 9] *** Arrrgh
>
> We have to do:
>
> ([1,2,3].map * 6).map + 4
>
> Not quite as bad for #map, as opposed to #every, being shorter, but it
> would still be nice to chain. Of course, to do that one must
> explicitly #to_a the final result per my original Enumerator example.

>
> One thing you might want to consider, Ruby 1.9+ returns an Enumerator
> for #map without a block, could pose some compatibility issues in the
> future.
That is a good thing, and thanks for pointing it out, looking for a
different name for #map now ;)
Though, I have to admit I'm not quite sure what a #map based
> Enumerator is good for -- when you run #each on it, it acts like
> #map !!!
>
> T.
>
Cheers
Robert

--
You see things; and you say Why?
But I dream things that never were; and I say Why not?
-- George Bernard Shaw

Trans

6/24/2007 11:34:00 AM

0

> That is even broken in Labrador, so much work to do :(
>
> irb(main):001:0> require 'labrador'
> => true
> irb(main):002:0> [1,2,3].map + 2
> => [3, 4, 5]
> irb(main):003:0> [1,2,3].map + 2 * 3
> => [7, 8, 9] *** Arrrgh

I think that's right, * takes precedence. So you're getting the result
of '+ 6'.

T.


Trans

6/24/2007 11:39:00 AM

0



On Jun 24, 12:32 am, Trans <transf...@gmail.com> wrote:
> On Jun 24, 12:26 am, James Edward Gray II <j...@grayproductions.net>
> wrote:
>
> > On Jun 23, 2007, at 11:07 PM, Trans wrote:
>
> > > Anyway to change an Enumerator's enum_obj in place? Enumerator doesn't
> > > seem to support the #collect! method.
>
> > Knowing that an object is Enumerable doesn't tell you anything about
> > how to edit it, so there's no way Enumerable could logically support
> > destructive operations.
>
> Ah, of course.

Wait. Yes, the #collect! method isn't going to fly, but if I could
just reassign enum_object -- that would actually better.

T.


Trans

6/24/2007 12:06:00 PM

0


On Jun 24, 7:05 am, "Robert Dober" <robert.do...@gmail.com> wrote:
> Facets is great but Labrador is mine, what does that mean: I have the
> luxury to do things that scale badly and break compatibility, -- I
> have to make the documentation clear about this in the next version.
> Facets is a General Purpose Library and cannot afford that luxury, so
> it is very clear why you have #every -- a tempting idea not to
> overload map, even in an experimental package as my dog package. Yet
> another advantage, I just change the name, nobody can complain...
> OTH I am surprised that #every corresponds to #map, from its naming on
> would say it should correspond to #each.

Yes, but #each is taken too ;) I though about #each? though.


> > module Enumerable
> > def every
> > @_functor_every ||= Functor.new do |op,*args|
> > self.collect{ |a| a.send(op,*args) }
> > end
> > end
> > end
>
> I gotta look at your Functors again, maybe I can steal a little bit from you;)

Basic Functor is easy:

class Functor
private *instance_methods
def initialize(&function)
@function = function
end
def method_missing(sym,*args,&blk)
@function.call(sym,*args,&blk)
end
end

Facets' is a little more fleshed out than that, but that's all one
needs. And I still think it worthy of inclusion in Ruby's standard
library.

> That is a good thing, and thanks for pointing it out, looking for a
> different name for #map now ;)
> Though, I have to admit I'm not quite sure what a #map based> Enumerator is good for -- when you run #each on it, it acts like
> > #map !!!

I may have a solution for you:

require 'enumerator'

class Enumerable::Enumerator
def method_missing(sym,*args,&blk)
each{ |x| x.send(sym,*args,&blk) }
end
end

With 1.9+ you'll get what you want (mostly). For 1.8, you just need to
override map to return the Enumerator (just like 1.9 does). Btw, if
you do the same for #select:

[1,2,3].select < 2 #=> [1]

Oh, I am soooo tempted to put this in Facets.

T.


Robert Dober

6/24/2007 1:03:00 PM

0

>
> I think that's right, * takes precedence. So you're getting the result
> of '+ 6'.
Oops , thx Tom.
>
> T.
>
>
>


--
You see things; and you say Why?
But I dream things that never were; and I say Why not?
-- George Bernard Shaw