Are we cool? method_missing in enumerator

Can anyone demonstrate problems with the following?

  # Adds immediate elementwise ability to Enumerator.
  # Any non-enumeration method is passed on to each.

···

#
  # [1,2,3].to_enum(:map) + 3
  # => [4,5,6]
  #
  # Note there may be a few essential methods this can not
  # be used on, such as #object_id.

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

I like the simplicity of this and would rather use it than add an
another class layer, but I need to be sure I'm not overlooking any
potential dangers with doing so.

Thanks,
T.

Cool indeed! The only thing that comes to mind at the moment is a
certain inconsistency that this creates: all methods implemented in
the Enumerator are methods operating on the collection while methods
invoked by your extension are invoked per instance in the collection.
I am not sure whether that actually disqualifies the change as a std
lib change...

Btw, your sample would be equally simple by doing [1,2,3].map {|x|
x+3} - it's even less typing. :wink:

Kind regards

robert

···

2007/7/17, Trans <transfire@gmail.com>:

Can anyone demonstrate problems with the following?

  # Adds immediate elementwise ability to Enumerator.
  # Any non-enumeration method is passed on to each.
  #
  # [1,2,3].to_enum(:map) + 3
  # => [4,5,6]
  #
  # Note there may be a few essential methods this can not
  # be used on, such as #object_id.

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

I like the simplicity of this and would rather use it than add an
another class layer, but I need to be sure I'm not overlooking any
potential dangers with doing so.

Hmm I do it like this in Labrador, but on map directly and I add a
class overlay so that indeed things like #object_id can be dispatched

irb(main):002:0> require 'labrador/enum'
=> true
irb(main):003:0> [1,2,3].map.object_id
=> [3, 5, 7]
irb(main):004:0>

I would indeed be very interested in dangers of this, but my
announcement went unnoticed, quite normal given the undocumented and
unstructured state of Labrador -- I work less than 1h/w for it :(.

I really do not like -- or know -- this to_enum stuff, it seems way to
verbose for me.
Attention I am not going to influence the community I just want to
find some fellow soul who likes my style. (Notably Magic Dot)

Sorry if I am hijacking a little bit, just say a word and I'll go away...

Robert

···

On 7/17/07, Trans <transfire@gmail.com> wrote:

Can anyone demonstrate problems with the following?

  # Adds immediate elementwise ability to Enumerator.
  # Any non-enumeration method is passed on to each.
  #
  # [1,2,3].to_enum(:map) + 3
  # => [4,5,6]
  #
  # Note there may be a few essential methods this can not
  # be used on, such as #object_id.

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

I like the simplicity of this and would rather use it than add an
another class layer, but I need to be sure I'm not overlooking any
potential dangers with doing so.

--
I always knew that one day Smalltalk would replace Java.
I just didn't know it would be called Ruby
-- Kent Beck

I might test that it can still throw missing method exception if the called method isn't supposed to be doing what you're making it do (ie, perhaps it was a typo)

Sam

Trans wrote, On 7/17/2007 9:01 AM:

···

Can anyone demonstrate problems with the following?

  # Adds immediate elementwise ability to Enumerator.
  # Any non-enumeration method is passed on to each.
  #
  # [1,2,3].to_enum(:map) + 3
  # => [4,5,6]
  #
  # Note there may be a few essential methods this can not
  # be used on, such as #object_id.

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

I like the simplicity of this and would rather use it than add an
another class layer, but I need to be sure I'm not overlooking any
potential dangers with doing so.

Thanks,
T.

Btw, your sample would be equally simple by doing [1,2,3].map {|x|
x+3} - it's even less typing. :wink:

I offer
irb(main):001:0> require 'labrador/enum'
=> true
irb(main):002:0> (1..3).map + 3
=> [4, 5, 6]
irb(main):003:0> (1..3).map(:+, 3)
=> [4, 5, 6]

Kind regards

robert

Robert

···

On 7/17/07, Robert Klemme <shortcutter@googlemail.com> wrote:

--
I always knew that one day Smalltalk would replace Java.
I just didn't know it would be called Ruby
-- Kent Beck

Yea, that's the "danger" part, because it's going to try to apply that
typo to the enumerable's elements. I many cases that will no doubt
fail --in which case maybe it wouldn't hurt to but it in a begin
rescue clause in order to give a more comprehensible error message.
OTOH, some typos might get through, in which case testing is key.

I think I've come up with a good alternative that is safer, but still
reads well (as of 1.9):

  arr.map.x + 3

What do you think?

T.

···

On Jul 18, 8:01 am, Sammy Larbi <s...@powersource.com> wrote:

I might test that it can still throw missing method exception if the
called method isn't supposed to be doing what you're making it do (ie,
perhaps it was a typo)

Sam

Trans wrote, On 7/17/2007 9:01 AM:

> Can anyone demonstrate problems with the following?

> # Adds immediate elementwise ability to Enumerator.
> # Any non-enumeration method is passed on to each.
> #
> # [1,2,3].to_enum(:map) + 3
> # => [4,5,6]
> #
> # Note there may be a few essential methods this can not
> # be used on, such as #object_id.

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

> I like the simplicity of this and would rather use it than add an
> another class layer, but I need to be sure I'm not overlooking any
> potential dangers with doing so.

Yep. This works with my implementation too as of Ruby 1.9+ because the
enumerable methods will return an enumerator if no block is given.

T.

···

On Jul 17, 7:22 am, "Robert Dober" <robert.do...@gmail.com> wrote:

On 7/17/07, Robert Klemme <shortcut...@googlemail.com> wrote:

> Btw, your sample would be equally simple by doing [1,2,3].map {|x|
> x+3} - it's even less typing. :wink:

I offer
irb(main):001:0> require 'labrador/enum'
=> true
irb(main):002:0> (1..3).map + 3
=> [4, 5, 6]
irb(main):003:0> (1..3).map(:+, 3)
=> [4, 5, 6]

This being true, where exactly is the difference between

enum.map{ |e| e.typo }
and
enum.map(:typo)

<snip>
Robert

···

On 7/18/07, Trans <transfire@gmail.com> wrote:

On Jul 18, 8:01 am, Sammy Larbi <s...@powersource.com> wrote:
> I might test that it can still throw missing method exception if the
> called method isn't supposed to be doing what you're making it do (ie,
> perhaps it was a typo)

--
I always knew that one day Smalltalk would replace Java.
I just didn't know it would be called Ruby
-- Kent Beck

Trans wrote:

I think I've come up with a good alternative that is safer, but still
reads well (as of 1.9):

  arr.map.x + 3

What do you think?

I'll throw out this idea from a thread not so long ago:

arr.map.it + 3

:wink:
Daniel

Hi --

···

On Thu, 19 Jul 2007, Trans wrote:

I think I've come up with a good alternative that is safer, but still
reads well (as of 1.9):

arr.map.x + 3

What do you think?

I'm afraid there's too much "invisible ink" there for me.

David

--
* Books:
   RAILS ROUTING (new! http://www.awprofessional.com/title/0321509242\)
   RUBY FOR RAILS (http://www.manning.com/black\)
* Ruby/Rails training
     & consulting: Ruby Power and Light, LLC (http://www.rubypal.com)

Hmm... that's very good point!

T.

···

On Jul 18, 1:48 pm, "Robert Dober" <robert.do...@gmail.com> wrote:

On 7/18/07, Trans <transf...@gmail.com> wrote:

> On Jul 18, 8:01 am, Sammy Larbi <s...@powersource.com> wrote:
> > I might test that it can still throw missing method exception if the
> > called method isn't supposed to be doing what you're making it do (ie,
> > perhaps it was a typo)

This being true, where exactly is the difference between

enum.map{ |e| e.typo }
and
enum.map(:typo)

That's a great way to put it! With your (other) own words, I think
this is unbalanced. Too much coolness, to few readability.

Kind regards

robert

···

2007/7/19, dblack@wobblini.net <dblack@wobblini.net>:

Hi --

On Thu, 19 Jul 2007, Trans wrote:

> I think I've come up with a good alternative that is safer, but still
> reads well (as of 1.9):
>
> arr.map.x + 3
>
> What do you think?

I'm afraid there's too much "invisible ink" there for me.

Well, what does that mean? Clearly you find it uncomfortable in some
manner. Is it just the magic-dot again? Or something else? Is the
original

  arr.map + 3

okay? Or are both too much "invisible ink". What is wrong with it/them
more concretely?

Thanks,
T.

···

On Jul 19, 2:45 am, dbl...@wobblini.net wrote:

Hi --

On Thu, 19 Jul 2007, Trans wrote:
> I think I've come up with a good alternative that is safer, but still
> reads well (as of 1.9):

> arr.map.x + 3

> What do you think?

I'm afraid there's too much "invisible ink" there for me.

Robert Dober wrote, On 7/18/2007 3:48 PM:

···

On 7/18/07, Trans <transfire@gmail.com> wrote:

On Jul 18, 8:01 am, Sammy Larbi <s...@powersource.com> wrote:
> I might test that it can still throw missing method exception if the
> called method isn't supposed to be doing what you're making it do (ie,
> perhaps it was a typo)

This being true, where exactly is the difference between

enum.map{ |e| e.typo }
and
enum.map(:typo)

<snip>
Robert

Good point. I guess I was thinking of something unrelated to the map call: Where you've got the magic behavior working fine, but somewhere later on you have a method typo, but that gets caught by method_missing and throws some different strange error instead of method missing.

Sam

> Hi --
>
> > I think I've come up with a good alternative that is safer, but still
> > reads well (as of 1.9):
>
> > arr.map.x + 3
>
> > What do you think?
>
> I'm afraid there's too much "invisible ink" there for me.

Well, what does that mean? Clearly you find it uncomfortable in some
manner. Is it just the magic-dot again? Or something else? Is the
original

  arr.map + 3

okay? Or are both too much "invisible ink". What is wrong with it/them
more concretely?

At a glance, I can't tell if arr is a object with an attribute named map
that you're adding 3 to (and never storing). Does this return a value, or
does it modify in place? If it returns a value, then you'd end up with a
statement like

new_arr = arr.map + 3

without knowing a lot of specifics about arr, map, and this magic, I would
totally assume that map is an attribute of arr, and you're adding 3 to it.

This sort of shortcut is the kind of thing I would use in a DSL where
certain context is assumed, but wouldn't use in day to day programming, it's
just too ambiguous.

Thanks,

···

On 7/19/07, Trans <transfire@gmail.com> wrote:

On Jul 19, 2:45 am, dbl...@wobblini.net wrote:
> On Thu, 19 Jul 2007, Trans wrote:
T.

--
===Tanner Burson===
tanner.burson@gmail.com
http://www.tannerburson.com

This is indeed true, the art might be to find the balance (how is it
going David? :wink: between conciseness and readability.
Your DSL example is excellent because it restricts users to a circle
talking the same jargon, more generally I think one has to think about
who will read the code.
Consistency comes in too ( I did not do it on purpose ) if you write
all your code like that a potential new team member or maintainer will
learn your ways quickly...

Robert

···

On 7/19/07, Tanner Burson <tanner.burson@gmail.com> wrote:

On 7/19/07, Trans <transfire@gmail.com> wrote:
>
> On Jul 19, 2:45 am, dbl...@wobblini.net wrote:
> > Hi --
> >
> > On Thu, 19 Jul 2007, Trans wrote:
> > > I think I've come up with a good alternative that is safer, but still
> > > reads well (as of 1.9):
> >
> > > arr.map.x + 3
> >
> > > What do you think?
> >
> > I'm afraid there's too much "invisible ink" there for me.
>
> Well, what does that mean? Clearly you find it uncomfortable in some
> manner. Is it just the magic-dot again? Or something else? Is the
> original
>
> arr.map + 3
>
> okay? Or are both too much "invisible ink". What is wrong with it/them
> more concretely?

At a glance, I can't tell if arr is a object with an attribute named map
that you're adding 3 to (and never storing). Does this return a value, or
does it modify in place? If it returns a value, then you'd end up with a
statement like

new_arr = arr.map + 3

without knowing a lot of specifics about arr, map, and this magic, I would
totally assume that map is an attribute of arr, and you're adding 3 to it.

This sort of shortcut is the kind of thing I would use in a DSL where
certain context is assumed, but wouldn't use in day to day programming, it's
just too ambiguous.

--
I always knew that one day Smalltalk would replace Java.
I just didn't know it would be called Ruby
-- Kent Beck