Robert Dober
6/24/2007 11:05:00 AM
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