ruby-core@ruby-lang.org archive (unofficial mirror)
 help / color / mirror / Atom feed
* [ruby-core:41213] [ruby-trunk - Bug #5663][Open] Combined map/select method
@ 2011-11-22 20:37 Yehuda Katz
  2011-11-22 20:43 ` [ruby-core:41215] [ruby-trunk - Bug #5663] " Rodrigo Rosenfeld Rosas
                   ` (45 more replies)
  0 siblings, 46 replies; 62+ messages in thread
From: Yehuda Katz @ 2011-11-22 20:37 UTC (permalink / raw
  To: ruby-core


Issue #5663 has been reported by Yehuda Katz.

----------------------------------------
Bug #5663: Combined map/select method
http://redmine.ruby-lang.org/issues/5663

Author: Yehuda Katz
Status: Open
Priority: Normal
Assignee: 
Category: 
Target version: 
ruby -v: ruby 1.9.3p0 (2011-11-08 revision 33661) [x86_64-darwin11.2.0]


It is pretty common to want to map over an Enumerable, but only include the elements that match a particular filter. A common idiom is:

enum.map { |i| i + 1 if i.even? }.compact

It is of course also possible to do this with two calls:

enum.select { |i| i.even? }.map { |i| i + 1 }

Both cases are clumsy and require two iterations through the loop. I'd like to propose a combined method:

enum.map_select { |i| i + 1 if i.even? }

The only caveat is that it would be impossible to intentionally return nil here; suggestions welcome. The naming is also a strawman; feel free to propose something better.


-- 
http://redmine.ruby-lang.org

^ permalink raw reply	[flat|nested] 62+ messages in thread

* [ruby-core:41215] [ruby-trunk - Bug #5663] Combined map/select method
  2011-11-22 20:37 [ruby-core:41213] [ruby-trunk - Bug #5663][Open] Combined map/select method Yehuda Katz
@ 2011-11-22 20:43 ` Rodrigo Rosenfeld Rosas
  2011-11-22 20:45 ` [ruby-core:41217] " Rodrigo Rosenfeld Rosas
                   ` (44 subsequent siblings)
  45 siblings, 0 replies; 62+ messages in thread
From: Rodrigo Rosenfeld Rosas @ 2011-11-22 20:43 UTC (permalink / raw
  To: ruby-core


Issue #5663 has been updated by Rodrigo Rosenfeld Rosas.


I like the idea but not the name. Maybe something like select_non_nil would be more appropriate. English is not my mother tongue, is there any English way to say this in a shorter way?
----------------------------------------
Bug #5663: Combined map/select method
http://redmine.ruby-lang.org/issues/5663

Author: Yehuda Katz
Status: Open
Priority: Normal
Assignee: 
Category: 
Target version: 
ruby -v: ruby 1.9.3p0 (2011-11-08 revision 33661) [x86_64-darwin11.2.0]


It is pretty common to want to map over an Enumerable, but only include the elements that match a particular filter. A common idiom is:

enum.map { |i| i + 1 if i.even? }.compact

It is of course also possible to do this with two calls:

enum.select { |i| i.even? }.map { |i| i + 1 }

Both cases are clumsy and require two iterations through the loop. I'd like to propose a combined method:

enum.map_select { |i| i + 1 if i.even? }

The only caveat is that it would be impossible to intentionally return nil here; suggestions welcome. The naming is also a strawman; feel free to propose something better.


-- 
http://redmine.ruby-lang.org

^ permalink raw reply	[flat|nested] 62+ messages in thread

* [ruby-core:41217] [ruby-trunk - Bug #5663] Combined map/select method
  2011-11-22 20:37 [ruby-core:41213] [ruby-trunk - Bug #5663][Open] Combined map/select method Yehuda Katz
  2011-11-22 20:43 ` [ruby-core:41215] [ruby-trunk - Bug #5663] " Rodrigo Rosenfeld Rosas
@ 2011-11-22 20:45 ` Rodrigo Rosenfeld Rosas
  2011-11-22 21:15   ` [ruby-core:41218] " Adam Prescott
  2011-11-22 22:26 ` [ruby-core:41222] Re: [ruby-trunk - Bug #5663][Open] " Shugo Maeda
                   ` (43 subsequent siblings)
  45 siblings, 1 reply; 62+ messages in thread
From: Rodrigo Rosenfeld Rosas @ 2011-11-22 20:45 UTC (permalink / raw
  To: ruby-core


Issue #5663 has been updated by Rodrigo Rosenfeld Rosas.


Or maybe just enum.filter?
----------------------------------------
Bug #5663: Combined map/select method
http://redmine.ruby-lang.org/issues/5663

Author: Yehuda Katz
Status: Open
Priority: Normal
Assignee: 
Category: 
Target version: 
ruby -v: ruby 1.9.3p0 (2011-11-08 revision 33661) [x86_64-darwin11.2.0]


It is pretty common to want to map over an Enumerable, but only include the elements that match a particular filter. A common idiom is:

enum.map { |i| i + 1 if i.even? }.compact

It is of course also possible to do this with two calls:

enum.select { |i| i.even? }.map { |i| i + 1 }

Both cases are clumsy and require two iterations through the loop. I'd like to propose a combined method:

enum.map_select { |i| i + 1 if i.even? }

The only caveat is that it would be impossible to intentionally return nil here; suggestions welcome. The naming is also a strawman; feel free to propose something better.


-- 
http://redmine.ruby-lang.org

^ permalink raw reply	[flat|nested] 62+ messages in thread

* [ruby-core:41218] Re: [ruby-trunk - Bug #5663] Combined map/select method
  2011-11-22 20:45 ` [ruby-core:41217] " Rodrigo Rosenfeld Rosas
@ 2011-11-22 21:15   ` Adam Prescott
  2011-11-22 21:37     ` [ruby-core:41221] " Yehuda Katz
  0 siblings, 1 reply; 62+ messages in thread
From: Adam Prescott @ 2011-11-22 21:15 UTC (permalink / raw
  To: ruby-core

[-- Attachment #1: Type: text/plain, Size: 120 bytes --]

Instead of looking at it from the map + select approach for a name, what
about the map + compact version? compact_map ?

[-- Attachment #2: Type: text/html, Size: 120 bytes --]

^ permalink raw reply	[flat|nested] 62+ messages in thread

* [ruby-core:41221] Re: [ruby-trunk - Bug #5663] Combined map/select method
  2011-11-22 21:15   ` [ruby-core:41218] " Adam Prescott
@ 2011-11-22 21:37     ` Yehuda Katz
  0 siblings, 0 replies; 62+ messages in thread
From: Yehuda Katz @ 2011-11-22 21:37 UTC (permalink / raw
  To: ruby-core

[-- Attachment #1: Type: text/plain, Size: 265 bytes --]

Compact implies two passes, no?

Yehuda Katz
(ph) 718.877.1325


On Tue, Nov 22, 2011 at 1:15 PM, Adam Prescott <adam@aprescott.com> wrote:

> Instead of looking at it from the map + select approach for a name, what
> about the map + compact version? compact_map ?

[-- Attachment #2: Type: text/html, Size: 529 bytes --]

^ permalink raw reply	[flat|nested] 62+ messages in thread

* [ruby-core:41222] Re: [ruby-trunk - Bug #5663][Open] Combined map/select method
  2011-11-22 20:37 [ruby-core:41213] [ruby-trunk - Bug #5663][Open] Combined map/select method Yehuda Katz
  2011-11-22 20:43 ` [ruby-core:41215] [ruby-trunk - Bug #5663] " Rodrigo Rosenfeld Rosas
  2011-11-22 20:45 ` [ruby-core:41217] " Rodrigo Rosenfeld Rosas
@ 2011-11-22 22:26 ` Shugo Maeda
  2011-11-23  0:17   ` [ruby-core:41232] " Yehuda Katz
  2011-11-22 23:55 ` [ruby-core:41229] [ruby-trunk - Feature #5663] " Rodrigo Rosenfeld Rosas
                   ` (42 subsequent siblings)
  45 siblings, 1 reply; 62+ messages in thread
From: Shugo Maeda @ 2011-11-22 22:26 UTC (permalink / raw
  To: ruby-core

Hi,

2011/11/23 Yehuda Katz <wycats@gmail.com>:
> It is pretty common to want to map over an Enumerable, but only include the elements that match a particular filter. A common idiom is:
>
> enum.map { |i| i + 1 if i.even? }.compact
>
> It is of course also possible to do this with two calls:
>
> enum.select { |i| i.even? }.map { |i| i + 1 }
>
> Both cases are clumsy and require two iterations through the loop. I'd like to propose a combined method:
>
> enum.map_select { |i| i + 1 if i.even? }
>
> The only caveat is that it would be impossible to intentionally return nil here; suggestions welcome. The naming is also a strawman; feel free to propose something better.

How about to add list comprehensions or Scala's for expressions instead?
For example, enum.select { |i| i.even? }.map { |i| i + 1 } can be
written as follows:

  [ i + 1 for i in enum if i.even? ]

# The syntax of list comprehensions needs more considerations.

One benefit is that nested maps can be flattened by list comprehensions.
For example, the following code:

  pyths = [ [x, y, z] for z in [1..Float::INFINITY].defer
                          x in [1..z].defer
                          y in [x..z].defer
                          if x**2 + y**2 == z**2 ]
  p pyths.take(3)

is equivalent to the following code:

  pyths = (1..Float::INFINITY).defer.flat_map {|z|
    (1..z).defer.flat_map {|x|
      (x..z).defer.select {|y|
        x**2 + y**2 == z**2
      }.map {|y|
        [x, y, z]
      }
    }
  }
  p pyths.take(3)

# Enumerable#defer is proposed in Feature #4890.

BTW, now Ruby has map and reduce as aliases of collect and inject,
but not filter as an alias of select.  Why not?

-- 
Shugo Maeda

^ permalink raw reply	[flat|nested] 62+ messages in thread

* [ruby-core:41229] [ruby-trunk - Feature #5663] Combined map/select method
  2011-11-22 20:37 [ruby-core:41213] [ruby-trunk - Bug #5663][Open] Combined map/select method Yehuda Katz
                   ` (2 preceding siblings ...)
  2011-11-22 22:26 ` [ruby-core:41222] Re: [ruby-trunk - Bug #5663][Open] " Shugo Maeda
@ 2011-11-22 23:55 ` Rodrigo Rosenfeld Rosas
  2011-11-23 10:33 ` [ruby-core:41246] " Alexey Muranov
                   ` (41 subsequent siblings)
  45 siblings, 0 replies; 62+ messages in thread
From: Rodrigo Rosenfeld Rosas @ 2011-11-22 23:55 UTC (permalink / raw
  To: ruby-core


Issue #5663 has been updated by Rodrigo Rosenfeld Rosas.


Hi Shugo, I also like the idea of supporting list comprehensions like several other languages currently do.
----------------------------------------
Feature #5663: Combined map/select method
http://redmine.ruby-lang.org/issues/5663

Author: Yehuda Katz
Status: Open
Priority: Normal
Assignee: 
Category: 
Target version: 


It is pretty common to want to map over an Enumerable, but only include the elements that match a particular filter. A common idiom is:

enum.map { |i| i + 1 if i.even? }.compact

It is of course also possible to do this with two calls:

enum.select { |i| i.even? }.map { |i| i + 1 }

Both cases are clumsy and require two iterations through the loop. I'd like to propose a combined method:

enum.map_select { |i| i + 1 if i.even? }

The only caveat is that it would be impossible to intentionally return nil here; suggestions welcome. The naming is also a strawman; feel free to propose something better.


-- 
http://redmine.ruby-lang.org

^ permalink raw reply	[flat|nested] 62+ messages in thread

* [ruby-core:41232] Re: [ruby-trunk - Bug #5663][Open] Combined map/select method
  2011-11-22 22:26 ` [ruby-core:41222] Re: [ruby-trunk - Bug #5663][Open] " Shugo Maeda
@ 2011-11-23  0:17   ` Yehuda Katz
  0 siblings, 0 replies; 62+ messages in thread
From: Yehuda Katz @ 2011-11-23  0:17 UTC (permalink / raw
  To: ruby-core

[-- Attachment #1: Type: text/plain, Size: 3105 bytes --]

I am nervous about list comprehensions because in almost all cases, when
you do something in Ruby, you do it by invoking a named method on an
object. It is clear by looking at a piece of code which named method will
be invoked. In Ruby 1.9, it is even trivial to learn the exact source
location of such a named method.

In contrast, list comprehensions introduce new syntax that invokes some
invisible protocol; understanding which methods are involved requires
figuring out where to look in the documentation.

Python uses protocols like this for *everything*, so list comprehensions
fit in well there. The only Ruby case I can think of that works like this
is the much maligned for/in syntax, which invokes #each under the hood.
Most people I know find this strange, I suspect because of its
inconsistency with the very strong rule that if a method is directly
invoked by some syntax, you can see it.

If you want to see where this protocol-oriented path leads us, check out
http://docs.python.org/reference/datamodel.html#special-method-names. I
much prefer Ruby's "if you want to do something, invoke a named method"
principle of uniform access[1].

[1] http://en.wikipedia.org/wiki/Uniform_access_principle

Yehuda Katz
(ph) 718.877.1325


On Tue, Nov 22, 2011 at 2:26 PM, Shugo Maeda <shugo@ruby-lang.org> wrote:

> Hi,
>
> 2011/11/23 Yehuda Katz <wycats@gmail.com>:
> > It is pretty common to want to map over an Enumerable, but only include
> the elements that match a particular filter. A common idiom is:
> >
> > enum.map { |i| i + 1 if i.even? }.compact
> >
> > It is of course also possible to do this with two calls:
> >
> > enum.select { |i| i.even? }.map { |i| i + 1 }
> >
> > Both cases are clumsy and require two iterations through the loop. I'd
> like to propose a combined method:
> >
> > enum.map_select { |i| i + 1 if i.even? }
> >
> > The only caveat is that it would be impossible to intentionally return
> nil here; suggestions welcome. The naming is also a strawman; feel free to
> propose something better.
>
> How about to add list comprehensions or Scala's for expressions instead?
> For example, enum.select { |i| i.even? }.map { |i| i + 1 } can be
> written as follows:
>
>  [ i + 1 for i in enum if i.even? ]
>
> # The syntax of list comprehensions needs more considerations.
>
> One benefit is that nested maps can be flattened by list comprehensions.
> For example, the following code:
>
>  pyths = [ [x, y, z] for z in [1..Float::INFINITY].defer
>                          x in [1..z].defer
>                          y in [x..z].defer
>                          if x**2 + y**2 == z**2 ]
>  p pyths.take(3)
>
> is equivalent to the following code:
>
>  pyths = (1..Float::INFINITY).defer.flat_map {|z|
>    (1..z).defer.flat_map {|x|
>      (x..z).defer.select {|y|
>        x**2 + y**2 == z**2
>      }.map {|y|
>        [x, y, z]
>      }
>    }
>  }
>  p pyths.take(3)
>
> # Enumerable#defer is proposed in Feature #4890.
>
> BTW, now Ruby has map and reduce as aliases of collect and inject,
> but not filter as an alias of select.  Why not?
>
> --
> Shugo Maeda
>
>

[-- Attachment #2: Type: text/html, Size: 4003 bytes --]

^ permalink raw reply	[flat|nested] 62+ messages in thread

* [ruby-core:41246] [ruby-trunk - Feature #5663] Combined map/select method
  2011-11-22 20:37 [ruby-core:41213] [ruby-trunk - Bug #5663][Open] Combined map/select method Yehuda Katz
                   ` (3 preceding siblings ...)
  2011-11-22 23:55 ` [ruby-core:41229] [ruby-trunk - Feature #5663] " Rodrigo Rosenfeld Rosas
@ 2011-11-23 10:33 ` Alexey Muranov
  2011-11-23 15:21 ` [ruby-core:41251] " Rodrigo Rosenfeld Rosas
                   ` (40 subsequent siblings)
  45 siblings, 0 replies; 62+ messages in thread
From: Alexey Muranov @ 2011-11-23 10:33 UTC (permalink / raw
  To: ruby-core


Issue #5663 has been updated by Alexey Muranov.


It seems that in full generality this method needs to accept two blocks: one for selecting and one for mapping, but this would be an unusual syntax.
 
So how about a lazy `#selecting` first, which would store a block for selecting inside `enum`, and to make `#map` check if a block for selecting is defined, and to use it?  Maybe, instead of changing `#map`, a new variant of `#map` can be created that would take lazy operations into account. (For the name, i would propose `#partial_map` or `#map_partially`  ( http://en.wikipedia.org/wiki/Partial_function ), or `#map_selected`.)  Then the code would look like this:

enum.selecting { |i| i.even? }.map_selected { |i| i + 1 }

and only one loop will be needed.

I've read about gems defining lazy methods for Enumerable, but i do not remember if any of them is doing exactly this.

-Alexey.
----------------------------------------
Feature #5663: Combined map/select method
http://redmine.ruby-lang.org/issues/5663

Author: Yehuda Katz
Status: Open
Priority: Normal
Assignee: 
Category: 
Target version: 


It is pretty common to want to map over an Enumerable, but only include the elements that match a particular filter. A common idiom is:

enum.map { |i| i + 1 if i.even? }.compact

It is of course also possible to do this with two calls:

enum.select { |i| i.even? }.map { |i| i + 1 }

Both cases are clumsy and require two iterations through the loop. I'd like to propose a combined method:

enum.map_select { |i| i + 1 if i.even? }

The only caveat is that it would be impossible to intentionally return nil here; suggestions welcome. The naming is also a strawman; feel free to propose something better.


-- 
http://redmine.ruby-lang.org

^ permalink raw reply	[flat|nested] 62+ messages in thread

* [ruby-core:41251] [ruby-trunk - Feature #5663] Combined map/select method
  2011-11-22 20:37 [ruby-core:41213] [ruby-trunk - Bug #5663][Open] Combined map/select method Yehuda Katz
                   ` (4 preceding siblings ...)
  2011-11-23 10:33 ` [ruby-core:41246] " Alexey Muranov
@ 2011-11-23 15:21 ` Rodrigo Rosenfeld Rosas
  2011-11-23 16:53 ` [ruby-core:41254] " Alexey Muranov
                   ` (39 subsequent siblings)
  45 siblings, 0 replies; 62+ messages in thread
From: Rodrigo Rosenfeld Rosas @ 2011-11-23 15:21 UTC (permalink / raw
  To: ruby-core


Issue #5663 has been updated by Rodrigo Rosenfeld Rosas.


Alexey, what about thread safety in this case?
----------------------------------------
Feature #5663: Combined map/select method
http://redmine.ruby-lang.org/issues/5663

Author: Yehuda Katz
Status: Open
Priority: Normal
Assignee: 
Category: 
Target version: 


It is pretty common to want to map over an Enumerable, but only include the elements that match a particular filter. A common idiom is:

enum.map { |i| i + 1 if i.even? }.compact

It is of course also possible to do this with two calls:

enum.select { |i| i.even? }.map { |i| i + 1 }

Both cases are clumsy and require two iterations through the loop. I'd like to propose a combined method:

enum.map_select { |i| i + 1 if i.even? }

The only caveat is that it would be impossible to intentionally return nil here; suggestions welcome. The naming is also a strawman; feel free to propose something better.


-- 
http://redmine.ruby-lang.org

^ permalink raw reply	[flat|nested] 62+ messages in thread

* [ruby-core:41254] [ruby-trunk - Feature #5663] Combined map/select method
  2011-11-22 20:37 [ruby-core:41213] [ruby-trunk - Bug #5663][Open] Combined map/select method Yehuda Katz
                   ` (5 preceding siblings ...)
  2011-11-23 15:21 ` [ruby-core:41251] " Rodrigo Rosenfeld Rosas
@ 2011-11-23 16:53 ` Alexey Muranov
  2011-11-24  0:54 ` [ruby-core:41270] " Rodrigo Rosenfeld Rosas
                   ` (38 subsequent siblings)
  45 siblings, 0 replies; 62+ messages in thread
From: Alexey Muranov @ 2011-11-23 16:53 UTC (permalink / raw
  To: ruby-core


Issue #5663 has been updated by Alexey Muranov.


Rodrigo Rosenfeld Rosas wrote:
> Alexey, what about thread safety in this case? Would the selecting return a new object?

I do not know much about threads.  I think `#selecting` can return a new object, and `#selecting!` can add lazy selection to the object on which it is called.  Those more knowledgable please comment with something wiser.
----------------------------------------
Feature #5663: Combined map/select method
http://redmine.ruby-lang.org/issues/5663

Author: Yehuda Katz
Status: Open
Priority: Normal
Assignee: 
Category: 
Target version: 


It is pretty common to want to map over an Enumerable, but only include the elements that match a particular filter. A common idiom is:

enum.map { |i| i + 1 if i.even? }.compact

It is of course also possible to do this with two calls:

enum.select { |i| i.even? }.map { |i| i + 1 }

Both cases are clumsy and require two iterations through the loop. I'd like to propose a combined method:

enum.map_select { |i| i + 1 if i.even? }

The only caveat is that it would be impossible to intentionally return nil here; suggestions welcome. The naming is also a strawman; feel free to propose something better.


-- 
http://redmine.ruby-lang.org

^ permalink raw reply	[flat|nested] 62+ messages in thread

* [ruby-core:41270] [ruby-trunk - Feature #5663] Combined map/select method
  2011-11-22 20:37 [ruby-core:41213] [ruby-trunk - Bug #5663][Open] Combined map/select method Yehuda Katz
                   ` (6 preceding siblings ...)
  2011-11-23 16:53 ` [ruby-core:41254] " Alexey Muranov
@ 2011-11-24  0:54 ` Rodrigo Rosenfeld Rosas
  2011-11-24  7:12 ` [ruby-core:41279] " Nobuyoshi Nakada
                   ` (37 subsequent siblings)
  45 siblings, 0 replies; 62+ messages in thread
From: Rodrigo Rosenfeld Rosas @ 2011-11-24  0:54 UTC (permalink / raw
  To: ruby-core


Issue #5663 has been updated by Rodrigo Rosenfeld Rosas.


I was just suggesting that maybe avoiding laziness for this case would be less of a trouble since we wouldn't need to worry about thread safety...
----------------------------------------
Feature #5663: Combined map/select method
http://redmine.ruby-lang.org/issues/5663

Author: Yehuda Katz
Status: Open
Priority: Normal
Assignee: 
Category: 
Target version: 


It is pretty common to want to map over an Enumerable, but only include the elements that match a particular filter. A common idiom is:

enum.map { |i| i + 1 if i.even? }.compact

It is of course also possible to do this with two calls:

enum.select { |i| i.even? }.map { |i| i + 1 }

Both cases are clumsy and require two iterations through the loop. I'd like to propose a combined method:

enum.map_select { |i| i + 1 if i.even? }

The only caveat is that it would be impossible to intentionally return nil here; suggestions welcome. The naming is also a strawman; feel free to propose something better.


-- 
http://redmine.ruby-lang.org

^ permalink raw reply	[flat|nested] 62+ messages in thread

* [ruby-core:41279] [ruby-trunk - Feature #5663] Combined map/select method
  2011-11-22 20:37 [ruby-core:41213] [ruby-trunk - Bug #5663][Open] Combined map/select method Yehuda Katz
                   ` (7 preceding siblings ...)
  2011-11-24  0:54 ` [ruby-core:41270] " Rodrigo Rosenfeld Rosas
@ 2011-11-24  7:12 ` Nobuyoshi Nakada
  2011-11-24  8:49 ` [ruby-core:41280] " Thomas Sawyer
                   ` (36 subsequent siblings)
  45 siblings, 0 replies; 62+ messages in thread
From: Nobuyoshi Nakada @ 2011-11-24  7:12 UTC (permalink / raw
  To: ruby-core


Issue #5663 has been updated by Nobuyoshi Nakada.

Category set to lib
Target version set to 2.0.0

=begin
What about:
  (1..10).grep(->(i){i.even?}){|i|i+1}
or
  (1..10).grep(:even?.to_proc){|i|i+1}
=end

----------------------------------------
Feature #5663: Combined map/select method
http://redmine.ruby-lang.org/issues/5663

Author: Yehuda Katz
Status: Open
Priority: Normal
Assignee: 
Category: lib
Target version: 2.0.0


It is pretty common to want to map over an Enumerable, but only include the elements that match a particular filter. A common idiom is:

enum.map { |i| i + 1 if i.even? }.compact

It is of course also possible to do this with two calls:

enum.select { |i| i.even? }.map { |i| i + 1 }

Both cases are clumsy and require two iterations through the loop. I'd like to propose a combined method:

enum.map_select { |i| i + 1 if i.even? }

The only caveat is that it would be impossible to intentionally return nil here; suggestions welcome. The naming is also a strawman; feel free to propose something better.


-- 
http://redmine.ruby-lang.org

^ permalink raw reply	[flat|nested] 62+ messages in thread

* [ruby-core:41280] [ruby-trunk - Feature #5663] Combined map/select method
  2011-11-22 20:37 [ruby-core:41213] [ruby-trunk - Bug #5663][Open] Combined map/select method Yehuda Katz
                   ` (8 preceding siblings ...)
  2011-11-24  7:12 ` [ruby-core:41279] " Nobuyoshi Nakada
@ 2011-11-24  8:49 ` Thomas Sawyer
  2011-11-24 11:41 ` [ruby-core:41285] " Rodrigo Rosenfeld Rosas
                   ` (35 subsequent siblings)
  45 siblings, 0 replies; 62+ messages in thread
From: Thomas Sawyer @ 2011-11-24  8:49 UTC (permalink / raw
  To: ruby-core


Issue #5663 has been updated by Thomas Sawyer.


Related methods:

* filter (http://rubyworks.github.com/facets/doc/api/core/Enumerable.html#method-i-filter)
* purge (http://rubyworks.github.com/facets/doc/api/core/Enumerable.html#method-i-purge)

----------------------------------------
Feature #5663: Combined map/select method
http://redmine.ruby-lang.org/issues/5663

Author: Yehuda Katz
Status: Open
Priority: Normal
Assignee: 
Category: lib
Target version: 2.0.0


It is pretty common to want to map over an Enumerable, but only include the elements that match a particular filter. A common idiom is:

enum.map { |i| i + 1 if i.even? }.compact

It is of course also possible to do this with two calls:

enum.select { |i| i.even? }.map { |i| i + 1 }

Both cases are clumsy and require two iterations through the loop. I'd like to propose a combined method:

enum.map_select { |i| i + 1 if i.even? }

The only caveat is that it would be impossible to intentionally return nil here; suggestions welcome. The naming is also a strawman; feel free to propose something better.


-- 
http://redmine.ruby-lang.org

^ permalink raw reply	[flat|nested] 62+ messages in thread

* [ruby-core:41285] [ruby-trunk - Feature #5663] Combined map/select method
  2011-11-22 20:37 [ruby-core:41213] [ruby-trunk - Bug #5663][Open] Combined map/select method Yehuda Katz
                   ` (9 preceding siblings ...)
  2011-11-24  8:49 ` [ruby-core:41280] " Thomas Sawyer
@ 2011-11-24 11:41 ` Rodrigo Rosenfeld Rosas
  2011-11-24 11:43 ` [ruby-core:41286] " Rodrigo Rosenfeld Rosas
                   ` (34 subsequent siblings)
  45 siblings, 0 replies; 62+ messages in thread
From: Rodrigo Rosenfeld Rosas @ 2011-11-24 11:41 UTC (permalink / raw
  To: ruby-core


Issue #5663 has been updated by Rodrigo Rosenfeld Rosas.


Nobuyoshi, wouldn't &:even? be equivalent to :even?.to_proc? I just find that the example reads better this way ;)

<pre>
(1..10).grep(&:even?){|i|i+1}
</pre>

But anyway, I don't find that "grep" is self-explanatory, although I like the idea of passing two procs.
----------------------------------------
Feature #5663: Combined map/select method
http://redmine.ruby-lang.org/issues/5663

Author: Yehuda Katz
Status: Open
Priority: Normal
Assignee: 
Category: lib
Target version: 2.0.0


It is pretty common to want to map over an Enumerable, but only include the elements that match a particular filter. A common idiom is:

enum.map { |i| i + 1 if i.even? }.compact

It is of course also possible to do this with two calls:

enum.select { |i| i.even? }.map { |i| i + 1 }

Both cases are clumsy and require two iterations through the loop. I'd like to propose a combined method:

enum.map_select { |i| i + 1 if i.even? }

The only caveat is that it would be impossible to intentionally return nil here; suggestions welcome. The naming is also a strawman; feel free to propose something better.


-- 
http://redmine.ruby-lang.org

^ permalink raw reply	[flat|nested] 62+ messages in thread

* [ruby-core:41286] [ruby-trunk - Feature #5663] Combined map/select method
  2011-11-22 20:37 [ruby-core:41213] [ruby-trunk - Bug #5663][Open] Combined map/select method Yehuda Katz
                   ` (10 preceding siblings ...)
  2011-11-24 11:41 ` [ruby-core:41285] " Rodrigo Rosenfeld Rosas
@ 2011-11-24 11:43 ` Rodrigo Rosenfeld Rosas
  2011-11-25  3:00 ` [ruby-core:41294] " Nobuyoshi Nakada
                   ` (33 subsequent siblings)
  45 siblings, 0 replies; 62+ messages in thread
From: Rodrigo Rosenfeld Rosas @ 2011-11-24 11:43 UTC (permalink / raw
  To: ruby-core


Issue #5663 has been updated by Rodrigo Rosenfeld Rosas.


How can I find the syntax for highlighting the code in this Redmine instance?
----------------------------------------
Feature #5663: Combined map/select method
http://redmine.ruby-lang.org/issues/5663

Author: Yehuda Katz
Status: Open
Priority: Normal
Assignee: 
Category: lib
Target version: 2.0.0


It is pretty common to want to map over an Enumerable, but only include the elements that match a particular filter. A common idiom is:

enum.map { |i| i + 1 if i.even? }.compact

It is of course also possible to do this with two calls:

enum.select { |i| i.even? }.map { |i| i + 1 }

Both cases are clumsy and require two iterations through the loop. I'd like to propose a combined method:

enum.map_select { |i| i + 1 if i.even? }

The only caveat is that it would be impossible to intentionally return nil here; suggestions welcome. The naming is also a strawman; feel free to propose something better.


-- 
http://redmine.ruby-lang.org

^ permalink raw reply	[flat|nested] 62+ messages in thread

* [ruby-core:41294] [ruby-trunk - Feature #5663] Combined map/select method
  2011-11-22 20:37 [ruby-core:41213] [ruby-trunk - Bug #5663][Open] Combined map/select method Yehuda Katz
                   ` (11 preceding siblings ...)
  2011-11-24 11:43 ` [ruby-core:41286] " Rodrigo Rosenfeld Rosas
@ 2011-11-25  3:00 ` Nobuyoshi Nakada
  2011-11-28  1:05   ` [ruby-core:41341] " Rodrigo Rosenfeld Rosas
  2011-11-28 23:30 ` [ruby-core:41381] " Alexey Muranov
                   ` (32 subsequent siblings)
  45 siblings, 1 reply; 62+ messages in thread
From: Nobuyoshi Nakada @ 2011-11-25  3:00 UTC (permalink / raw
  To: ruby-core


Issue #5663 has been updated by Nobuyoshi Nakada.


Rodrigo Rosenfeld Rosas wrote:
> Nobuyoshi, wouldn't &:even? be equivalent to :even?.to_proc? I just find that the example reads better this way ;)

They are different.
&expr calls #to_proc method on the result of expr, to achieve a Proc object.

> (1..10).grep(&:even?){|i|i+1}

It's a syntax error.

----------------------------------------
Feature #5663: Combined map/select method
http://redmine.ruby-lang.org/issues/5663

Author: Yehuda Katz
Status: Open
Priority: Normal
Assignee: 
Category: lib
Target version: 2.0.0


It is pretty common to want to map over an Enumerable, but only include the elements that match a particular filter. A common idiom is:

enum.map { |i| i + 1 if i.even? }.compact

It is of course also possible to do this with two calls:

enum.select { |i| i.even? }.map { |i| i + 1 }

Both cases are clumsy and require two iterations through the loop. I'd like to propose a combined method:

enum.map_select { |i| i + 1 if i.even? }

The only caveat is that it would be impossible to intentionally return nil here; suggestions welcome. The naming is also a strawman; feel free to propose something better.


-- 
http://redmine.ruby-lang.org

^ permalink raw reply	[flat|nested] 62+ messages in thread

* [ruby-core:41341] Re: [ruby-trunk - Feature #5663] Combined map/select method
  2011-11-25  3:00 ` [ruby-core:41294] " Nobuyoshi Nakada
@ 2011-11-28  1:05   ` Rodrigo Rosenfeld Rosas
  2011-11-28  1:59     ` [ruby-core:41346] " Nobuyoshi Nakada
  0 siblings, 1 reply; 62+ messages in thread
From: Rodrigo Rosenfeld Rosas @ 2011-11-28  1:05 UTC (permalink / raw
  To: ruby-core

Em 25-11-2011 01:00, Nobuyoshi Nakada escreveu:
> Issue #5663 has been updated by Nobuyoshi Nakada.
>
>
> Rodrigo Rosenfeld Rosas wrote:
>> Nobuyoshi, wouldn't&:even? be equivalent to :even?.to_proc? I just find that the example reads better this way ;)
> They are different.
> &expr calls #to_proc method on the result of expr, to achieve a Proc object.
>
>> (1..10).grep(&:even?){|i|i+1}
> It's a syntax error.

Wow! Thanks! This is unexpected to me. I didn't know about the difference.

Anyway, I still didn't understand why (1..10).grep(&:even?) works, but 
(1..10).grep(&:even?){|i| i+1} not.

Actually, I didn't understand your explanation. You said that &expr 
calls #to_proc on the result of expr. What is the expr on each example? 
Is there any place I could further read about those differences?

Thank you, Rodrigo.

^ permalink raw reply	[flat|nested] 62+ messages in thread

* [ruby-core:41346] Re: [ruby-trunk - Feature #5663] Combined map/select method
  2011-11-28  1:05   ` [ruby-core:41341] " Rodrigo Rosenfeld Rosas
@ 2011-11-28  1:59     ` Nobuyoshi Nakada
  2011-11-28 12:31       ` [ruby-core:41361] " Rodrigo Rosenfeld Rosas
  0 siblings, 1 reply; 62+ messages in thread
From: Nobuyoshi Nakada @ 2011-11-28  1:59 UTC (permalink / raw
  To: ruby-core

Hi,

(11/11/28 10:05), Rodrigo Rosenfeld Rosas wrote:
>> &expr calls #to_proc method on the result of expr, to achieve a Proc object.

achieve a Proc object, and convert it into a block.

> Anyway, I still didn't understand why (1..10).grep(&:even?) works, but (1..10).grep(&:even?){|i| i+1} not.

The former is equivalent to

  (1..10).grep {|i| i.even?}

You can't pass two or more blocks to one method call.

> Actually, I didn't understand your explanation. You said that &expr calls #to_proc on the result of expr. What is the expr on each example? Is there any place I could further read about those differences?

expr is :even? symbol literal here.

-- 
Nobu Nakada

^ permalink raw reply	[flat|nested] 62+ messages in thread

* [ruby-core:41361] Re: [ruby-trunk - Feature #5663] Combined map/select method
  2011-11-28  1:59     ` [ruby-core:41346] " Nobuyoshi Nakada
@ 2011-11-28 12:31       ` Rodrigo Rosenfeld Rosas
  0 siblings, 0 replies; 62+ messages in thread
From: Rodrigo Rosenfeld Rosas @ 2011-11-28 12:31 UTC (permalink / raw
  To: ruby-core

Em 27-11-2011 23:59, Nobuyoshi Nakada escreveu:
> ...
>> Anyway, I still didn't understand why (1..10).grep(&:even?) works, but (1..10).grep(&:even?){|i| i+1} not.
> The former is equivalent to
>
>    (1..10).grep {|i| i.even?}
>
> You can't pass two or more blocks to one method call.

Ah, ok, thanks. So this is actually the explanation why the other 
example won't work.

Maybe if Ruby accepted blocks as parameters, like Groovy does and as 
José Valim has proposed in a talk at RubyConf Brazil, that could be 
achievable as

(1..10).grep&:even?, {|i| i+1}

Has this feature already been discussed?

^ permalink raw reply	[flat|nested] 62+ messages in thread

* [ruby-core:41381] [ruby-trunk - Feature #5663] Combined map/select method
  2011-11-22 20:37 [ruby-core:41213] [ruby-trunk - Bug #5663][Open] Combined map/select method Yehuda Katz
                   ` (12 preceding siblings ...)
  2011-11-25  3:00 ` [ruby-core:41294] " Nobuyoshi Nakada
@ 2011-11-28 23:30 ` Alexey Muranov
  2011-11-29 11:32 ` [ruby-core:41391] " Rodrigo Rosenfeld Rosas
                   ` (31 subsequent siblings)
  45 siblings, 0 replies; 62+ messages in thread
From: Alexey Muranov @ 2011-11-28 23:30 UTC (permalink / raw
  To: ruby-core


Issue #5663 has been updated by Alexey Muranov.


Rodrigo Rosenfeld Rosas wrote:
> Em 25-11-2011 01:00, Nobuyoshi Nakada escreveu:
>  > Issue #5663 has been updated by Nobuyoshi Nakada.
>  >
>  >
>  > Rodrigo Rosenfeld Rosas wrote:
>  >> Nobuyoshi, wouldn't&:even? be equivalent to :even?.to_proc? I just find that the example reads better this way ;)
>  > They are different.
>  > &expr calls #to_proc method on the result of expr, to achieve a Proc object.
>  >
>  >> (1..10).grep(&:even?){|i|i+1}
>  > It's a syntax error.
>  
>  Wow! Thanks! This is unexpected to me. I didn't know about the difference.
>  
>  Anyway, I still didn't understand why (1..10).grep(&:even?) works, but 
>  (1..10).grep(&:even?){|i| i+1} not.
>  
>  Actually, I didn't understand your explanation. You said that &expr 
>  calls #to_proc on the result of expr. What is the expr on each example? 
>  Is there any place I could further read about those differences?
>  
>  Thank you, Rodrigo.

I am not a specialist, but it seems that you can only use ampersand in a `def` with the *last* parameter, and in such case this last parameter becomes the name of a block passed to the method.  Similarly, when you call a method, you can either supply a block, or pass a proc as a block by adding it as the last argument prefixed with ampersand, but not both, because you cannot pass two blocks to a method (but you can pass multiple procs).  So basically only one ampersand is allowed, and only if you do not supply a block.

Here is a link about blocks a procs, but it does not explain this detail:
http://www.robertsosinski.com/2008/12/21/understanding-ruby-blocks-procs-and-lambdas/
----------------------------------------
Feature #5663: Combined map/select method
http://redmine.ruby-lang.org/issues/5663

Author: Yehuda Katz
Status: Open
Priority: Normal
Assignee: 
Category: lib
Target version: 2.0.0


It is pretty common to want to map over an Enumerable, but only include the elements that match a particular filter. A common idiom is:

enum.map { |i| i + 1 if i.even? }.compact

It is of course also possible to do this with two calls:

enum.select { |i| i.even? }.map { |i| i + 1 }

Both cases are clumsy and require two iterations through the loop. I'd like to propose a combined method:

enum.map_select { |i| i + 1 if i.even? }

The only caveat is that it would be impossible to intentionally return nil here; suggestions welcome. The naming is also a strawman; feel free to propose something better.


-- 
http://redmine.ruby-lang.org

^ permalink raw reply	[flat|nested] 62+ messages in thread

* [ruby-core:41391] [ruby-trunk - Feature #5663] Combined map/select method
  2011-11-22 20:37 [ruby-core:41213] [ruby-trunk - Bug #5663][Open] Combined map/select method Yehuda Katz
                   ` (13 preceding siblings ...)
  2011-11-28 23:30 ` [ruby-core:41381] " Alexey Muranov
@ 2011-11-29 11:32 ` Rodrigo Rosenfeld Rosas
  2011-11-30  7:41   ` [ruby-core:41407] " Ondřej Bílka
  2012-01-31 17:47 ` [ruby-core:42289] Re: [ruby-trunk - Bug #5663][Open] " Roger Pack
                   ` (30 subsequent siblings)
  45 siblings, 1 reply; 62+ messages in thread
From: Rodrigo Rosenfeld Rosas @ 2011-11-29 11:32 UTC (permalink / raw
  To: ruby-core


Issue #5663 has been updated by Rodrigo Rosenfeld Rosas.


Hi Alexey,

Yes, I know about this. What José Valim suggested (well, he actually wondered, since he doesn't believe this could be changed in Ruby due to the large existent code base) was the removal of the block concept. From what I've understood, the block syntax would actually create a proc (or a lambda) that would be passed as a parameter. And I also find this less confusing, with the similar callable approach taken by C, JavaScript, Python and most languages out there I guess.
----------------------------------------
Feature #5663: Combined map/select method
http://redmine.ruby-lang.org/issues/5663

Author: Yehuda Katz
Status: Open
Priority: Normal
Assignee: 
Category: lib
Target version: 2.0.0


It is pretty common to want to map over an Enumerable, but only include the elements that match a particular filter. A common idiom is:

enum.map { |i| i + 1 if i.even? }.compact

It is of course also possible to do this with two calls:

enum.select { |i| i.even? }.map { |i| i + 1 }

Both cases are clumsy and require two iterations through the loop. I'd like to propose a combined method:

enum.map_select { |i| i + 1 if i.even? }

The only caveat is that it would be impossible to intentionally return nil here; suggestions welcome. The naming is also a strawman; feel free to propose something better.


-- 
http://redmine.ruby-lang.org

^ permalink raw reply	[flat|nested] 62+ messages in thread

* [ruby-core:41407] Re: [ruby-trunk - Feature #5663] Combined map/select method
  2011-11-29 11:32 ` [ruby-core:41391] " Rodrigo Rosenfeld Rosas
@ 2011-11-30  7:41   ` Ondřej Bílka
  2011-11-30 20:28     ` [ruby-core:41415] " Rodrigo Rosenfeld Rosas
  0 siblings, 1 reply; 62+ messages in thread
From: Ondřej Bílka @ 2011-11-30  7:41 UTC (permalink / raw
  To: ruby-core

On Tue, Nov 29, 2011 at 08:32:01PM +0900, Rodrigo Rosenfeld Rosas wrote:
> 
> Issue #5663 has been updated by Rodrigo Rosenfeld Rosas.
> 
> 
> Hi Alexey,
> 
> Yes, I know about this. What José Valim suggested (well, he actually wondered, since he doesn't believe this could be changed in Ruby due to the large existent code base) was the removal of the block concept. From what I've understood, the block syntax would actually create a proc (or a lambda) that would be passed as a parameter. And I also find this less confusing, with the similar callable approach taken by C, JavaScript, Python and most languages out there I guess.

It already is. For example
def foo(&p)
p.call
end
> ----------------------------------------
> Feature #5663: Combined map/select method
> http://redmine.ruby-lang.org/issues/5663
> 
> Author: Yehuda Katz
> Status: Open
> Priority: Normal
> Assignee: 
> Category: lib
> Target version: 2.0.0
> 
> 
> It is pretty common to want to map over an Enumerable, but only include the elements that match a particular filter. A common idiom is:
> 
> enum.map { |i| i + 1 if i.even? }.compact
> 
> It is of course also possible to do this with two calls:
> 
> enum.select { |i| i.even? }.map { |i| i + 1 }
> 
> Both cases are clumsy and require two iterations through the loop. I'd like to propose a combined method:
> 
> enum.map_select { |i| i + 1 if i.even? }
> 
> The only caveat is that it would be impossible to intentionally return nil here; suggestions welcome. The naming is also a strawman; feel free to propose something better.
> 
> 
> -- 
> http://redmine.ruby-lang.org

-- 

I'm sorry a pentium won't do, you need an SGI to connect with us.

^ permalink raw reply	[flat|nested] 62+ messages in thread

* [ruby-core:41415] Re: [ruby-trunk - Feature #5663] Combined map/select method
  2011-11-30  7:41   ` [ruby-core:41407] " Ondřej Bílka
@ 2011-11-30 20:28     ` Rodrigo Rosenfeld Rosas
  0 siblings, 0 replies; 62+ messages in thread
From: Rodrigo Rosenfeld Rosas @ 2011-11-30 20:28 UTC (permalink / raw
  To: ruby-core

Em 30-11-2011 05:41, Ondřej Bílka escreveu:
> On Tue, Nov 29, 2011 at 08:32:01PM +0900, Rodrigo Rosenfeld Rosas wrote:
>> ... What José Valim suggested (well, he actually wondered, since he doesn't believe this could be changed in Ruby due to the large existent code base) was the removal of the block concept. From what I've understood, the block syntax would actually create a proc (or a lambda) that would be passed as a parameter. And I also find this less confusing, with the similar callable approach taken by C, JavaScript, Python and most languages out there I guess.
> It already is. For example
> def foo(&p)
> p.call
> end

This is not what I'm talking about. The other callable languages 
wouldn't have special treatments for blocks like block_given? or yield, 
for instance.

I'm talking about "method(some_param){some_block 'here'}" being exactly 
equal to "method some_param, lambda {some_block 'here'}" (or using a 
proc instead of a lambda, I'm not sure about which one would be a better 
fit).

^ permalink raw reply	[flat|nested] 62+ messages in thread

* [ruby-core:42289] Re: [ruby-trunk - Bug #5663][Open] Combined map/select method
  2011-11-22 20:37 [ruby-core:41213] [ruby-trunk - Bug #5663][Open] Combined map/select method Yehuda Katz
                   ` (14 preceding siblings ...)
  2011-11-29 11:32 ` [ruby-core:41391] " Rodrigo Rosenfeld Rosas
@ 2012-01-31 17:47 ` Roger Pack
  2012-02-01  2:17 ` [ruby-core:42296] " trans
                   ` (29 subsequent siblings)
  45 siblings, 0 replies; 62+ messages in thread
From: Roger Pack @ 2012-01-31 17:47 UTC (permalink / raw
  To: ruby-core

> It is pretty common to want to map over an Enumerable, but only include the elements that match a particular filter. A common idiom is:
>
> enum.map { |i| i + 1 if i.even? }.compact
>
> It is of course also possible to do this with two calls:
>
> enum.select { |i| i.even? }.map { |i| i + 1 }
>
> Both cases are clumsy and require two iterations through the loop. I'd like to propose a combined method:


+1 for a combined map and select.  I find myself reaching for it every
so often and wishing it were there.

^ permalink raw reply	[flat|nested] 62+ messages in thread

* [ruby-core:42296] Re: [ruby-trunk - Bug #5663][Open] Combined map/select method
  2011-11-22 20:37 [ruby-core:41213] [ruby-trunk - Bug #5663][Open] Combined map/select method Yehuda Katz
                   ` (15 preceding siblings ...)
  2012-01-31 17:47 ` [ruby-core:42289] Re: [ruby-trunk - Bug #5663][Open] " Roger Pack
@ 2012-02-01  2:17 ` trans
  2012-02-01  2:18 ` [ruby-core:42297] [ruby-trunk - Feature #5663] " Thomas Sawyer
                   ` (28 subsequent siblings)
  45 siblings, 0 replies; 62+ messages in thread
From: trans @ 2012-02-01  2:17 UTC (permalink / raw
  To: ruby-core-google; +Cc: ruby-core


[-- Attachment #1.1: Type: text/plain, Size: 179 bytes --]

In Facets it's called #compact_map, but that's only b/c I though better of 
monkey patching #compact itself.

I think it would be a slick addition for #compact to take a block.



[-- Attachment #1.2: Type: text/html, Size: 193 bytes --]

^ permalink raw reply	[flat|nested] 62+ messages in thread

* [ruby-core:42297] [ruby-trunk - Feature #5663] Combined map/select method
  2011-11-22 20:37 [ruby-core:41213] [ruby-trunk - Bug #5663][Open] Combined map/select method Yehuda Katz
                   ` (16 preceding siblings ...)
  2012-02-01  2:17 ` [ruby-core:42296] " trans
@ 2012-02-01  2:18 ` Thomas Sawyer
  2012-02-01  3:39   ` [ruby-core:42299] " Nobuyoshi Nakada
  2012-02-01  4:10 ` [ruby-core:42301] " Yura Sokolov
                   ` (27 subsequent siblings)
  45 siblings, 1 reply; 62+ messages in thread
From: Thomas Sawyer @ 2012-02-01  2:18 UTC (permalink / raw
  To: ruby-core


Issue #5663 has been updated by Thomas Sawyer.


In Facets it's called #compact_map, but that's only b/c I thought better of monkey patching #compact itself.

I think it would be a slick feature for #compact to take a block.

----------------------------------------
Feature #5663: Combined map/select method
https://bugs.ruby-lang.org/issues/5663

Author: Yehuda Katz
Status: Open
Priority: Normal
Assignee: 
Category: lib
Target version: 2.0.0


It is pretty common to want to map over an Enumerable, but only include the elements that match a particular filter. A common idiom is:

enum.map { |i| i + 1 if i.even? }.compact

It is of course also possible to do this with two calls:

enum.select { |i| i.even? }.map { |i| i + 1 }

Both cases are clumsy and require two iterations through the loop. I'd like to propose a combined method:

enum.map_select { |i| i + 1 if i.even? }

The only caveat is that it would be impossible to intentionally return nil here; suggestions welcome. The naming is also a strawman; feel free to propose something better.


-- 
http://bugs.ruby-lang.org/

^ permalink raw reply	[flat|nested] 62+ messages in thread

* [ruby-core:42299] Re: [ruby-trunk - Feature #5663] Combined map/select method
  2012-02-01  2:18 ` [ruby-core:42297] [ruby-trunk - Feature #5663] " Thomas Sawyer
@ 2012-02-01  3:39   ` Nobuyoshi Nakada
  0 siblings, 0 replies; 62+ messages in thread
From: Nobuyoshi Nakada @ 2012-02-01  3:39 UTC (permalink / raw
  To: ruby-core

Hi,

(12/02/01 11:18), Thomas Sawyer wrote:
> In Facets it's called #compact_map, but that's only b/c I thought better of monkey patching #compact itself.
> 
> I think it would be a slick feature for #compact to take a block.

Mere "compact" doesn't feel implying "map".

-- 
Nobu Nakada

^ permalink raw reply	[flat|nested] 62+ messages in thread

* [ruby-core:42301] [ruby-trunk - Feature #5663] Combined map/select method
  2011-11-22 20:37 [ruby-core:41213] [ruby-trunk - Bug #5663][Open] Combined map/select method Yehuda Katz
                   ` (17 preceding siblings ...)
  2012-02-01  2:18 ` [ruby-core:42297] [ruby-trunk - Feature #5663] " Thomas Sawyer
@ 2012-02-01  4:10 ` Yura Sokolov
  2012-02-01  5:11 ` [ruby-core:42302] " Nobuyoshi Nakada
                   ` (26 subsequent siblings)
  45 siblings, 0 replies; 62+ messages in thread
From: Yura Sokolov @ 2012-02-01  4:10 UTC (permalink / raw
  To: ruby-core


Issue #5663 has been updated by Yura Sokolov.


I often wish to have methods, which likes to `inject` but do use return value of block for next iteration:

    class Enumerable
      def accum(container)
        each{|args| yield container, args}
        container
      end
    end

Then I could use it in following ways:
instead of

    enum.inject({}){|h, k| h[k] = true; h}
    enum.map{|ar| ar.select{|i| i.usefull?}}.flatten(1)
    enum.map{|i| i + 1 if i.even?}.compact

I could

    enum.accum({}){|h,k| h[k] = true}
    enum.accum([]){|res, ar| ar.each{|i| res << i if i.usefull?}}
    enum.accum([]){|res, i| res << i + 1 if i.even?}

Well, it is shorter only in case of `inject`, but I still will prefer such method, cause I don't stress GC with many short living arrays.
And maybe two common `container`-s could have separate methods:

    class Enumerable
      def accum_hash(&block)
        accum({}, &block)
      end
      def accum_ar(&block)
        accum([], &block)
      end
    end

    enum.accum_hash{|h,k| h[k] = true}
    enum.accum_array{|res, ar| ar.each{|i| res << i if i.usefull?}}
    enum.accum_array{|res, i| res << i + 1 if i.even?}
----------------------------------------
Feature #5663: Combined map/select method
https://bugs.ruby-lang.org/issues/5663

Author: Yehuda Katz
Status: Open
Priority: Normal
Assignee: 
Category: lib
Target version: 2.0.0


It is pretty common to want to map over an Enumerable, but only include the elements that match a particular filter. A common idiom is:

enum.map { |i| i + 1 if i.even? }.compact

It is of course also possible to do this with two calls:

enum.select { |i| i.even? }.map { |i| i + 1 }

Both cases are clumsy and require two iterations through the loop. I'd like to propose a combined method:

enum.map_select { |i| i + 1 if i.even? }

The only caveat is that it would be impossible to intentionally return nil here; suggestions welcome. The naming is also a strawman; feel free to propose something better.


-- 
http://bugs.ruby-lang.org/

^ permalink raw reply	[flat|nested] 62+ messages in thread

* [ruby-core:42302] [ruby-trunk - Feature #5663] Combined map/select method
  2011-11-22 20:37 [ruby-core:41213] [ruby-trunk - Bug #5663][Open] Combined map/select method Yehuda Katz
                   ` (18 preceding siblings ...)
  2012-02-01  4:10 ` [ruby-core:42301] " Yura Sokolov
@ 2012-02-01  5:11 ` Nobuyoshi Nakada
  2012-02-01  9:14   ` [ruby-core:42306] " Юрий Соколов
  2012-02-01 11:41 ` [ruby-core:42308] " Thomas Sawyer
                   ` (25 subsequent siblings)
  45 siblings, 1 reply; 62+ messages in thread
From: Nobuyoshi Nakada @ 2012-02-01  5:11 UTC (permalink / raw
  To: ruby-core


Issue #5663 has been updated by Nobuyoshi Nakada.


Yura Sokolov wrote:
> I often wish to have methods, which likes to `inject` but do use return value of block for next iteration:

Try each_with_object.

----------------------------------------
Feature #5663: Combined map/select method
https://bugs.ruby-lang.org/issues/5663

Author: Yehuda Katz
Status: Open
Priority: Normal
Assignee: 
Category: lib
Target version: 2.0.0


It is pretty common to want to map over an Enumerable, but only include the elements that match a particular filter. A common idiom is:

enum.map { |i| i + 1 if i.even? }.compact

It is of course also possible to do this with two calls:

enum.select { |i| i.even? }.map { |i| i + 1 }

Both cases are clumsy and require two iterations through the loop. I'd like to propose a combined method:

enum.map_select { |i| i + 1 if i.even? }

The only caveat is that it would be impossible to intentionally return nil here; suggestions welcome. The naming is also a strawman; feel free to propose something better.


-- 
http://bugs.ruby-lang.org/

^ permalink raw reply	[flat|nested] 62+ messages in thread

* [ruby-core:42306] Re: [ruby-trunk - Feature #5663] Combined map/select method
  2012-02-01  5:11 ` [ruby-core:42302] " Nobuyoshi Nakada
@ 2012-02-01  9:14   ` Юрий Соколов
  2012-04-01  2:50     ` [ruby-core:44035] " Nobuyoshi Nakada
  0 siblings, 1 reply; 62+ messages in thread
From: Юрий Соколов @ 2012-02-01  9:14 UTC (permalink / raw
  To: ruby-core

[-- Attachment #1: Type: text/plain, Size: 354 bytes --]

2012/2/1 Nobuyoshi Nakada <nobu@ruby-lang.org>

>
> Issue #5663 has been updated by Nobuyoshi Nakada.
>
> Yura Sokolov wrote:
> > I often wish to have methods, which likes to `inject` but do use return
> value of block for next iteration:
>
> Try each_with_object.
>

Yeah, it is good :) though it have a long name. It's pity that 1.9.3 hadn't
it.

Yura

[-- Attachment #2: Type: text/html, Size: 639 bytes --]

^ permalink raw reply	[flat|nested] 62+ messages in thread

* [ruby-core:42308] [ruby-trunk - Feature #5663] Combined map/select method
  2011-11-22 20:37 [ruby-core:41213] [ruby-trunk - Bug #5663][Open] Combined map/select method Yehuda Katz
                   ` (19 preceding siblings ...)
  2012-02-01  5:11 ` [ruby-core:42302] " Nobuyoshi Nakada
@ 2012-02-01 11:41 ` Thomas Sawyer
  2012-02-13 11:12 ` [ruby-core:42528] [ruby-trunk - Feature #5663][Rejected] " Yusuke Endoh
                   ` (24 subsequent siblings)
  45 siblings, 0 replies; 62+ messages in thread
From: Thomas Sawyer @ 2012-02-01 11:41 UTC (permalink / raw
  To: ruby-core


Issue #5663 has been updated by Thomas Sawyer.


@Nakada Why not?

"Returns a copy of self with all nil elements removed. If block is given, returns the yield of each member sans those that yield nil." 

  [1,2,3,4].compact{ |x| x.even? ? x*2 : nil }  #=> [4,16]

Seems clear enough to me. Besides, I think we'd be quite hard pressed to find some other term that implies both "map" and "compact".


----------------------------------------
Feature #5663: Combined map/select method
https://bugs.ruby-lang.org/issues/5663

Author: Yehuda Katz
Status: Open
Priority: Normal
Assignee: 
Category: lib
Target version: 2.0.0


It is pretty common to want to map over an Enumerable, but only include the elements that match a particular filter. A common idiom is:

enum.map { |i| i + 1 if i.even? }.compact

It is of course also possible to do this with two calls:

enum.select { |i| i.even? }.map { |i| i + 1 }

Both cases are clumsy and require two iterations through the loop. I'd like to propose a combined method:

enum.map_select { |i| i + 1 if i.even? }

The only caveat is that it would be impossible to intentionally return nil here; suggestions welcome. The naming is also a strawman; feel free to propose something better.


-- 
http://bugs.ruby-lang.org/

^ permalink raw reply	[flat|nested] 62+ messages in thread

* [ruby-core:42528] [ruby-trunk - Feature #5663][Rejected] Combined map/select method
  2011-11-22 20:37 [ruby-core:41213] [ruby-trunk - Bug #5663][Open] Combined map/select method Yehuda Katz
                   ` (20 preceding siblings ...)
  2012-02-01 11:41 ` [ruby-core:42308] " Thomas Sawyer
@ 2012-02-13 11:12 ` Yusuke Endoh
  2012-02-13 11:43 ` [ruby-core:42531] [ruby-trunk - Feature #5663] " Rodrigo Rosenfeld Rosas
                   ` (23 subsequent siblings)
  45 siblings, 0 replies; 62+ messages in thread
From: Yusuke Endoh @ 2012-02-13 11:12 UTC (permalink / raw
  To: ruby-core


Issue #5663 has been updated by Yusuke Endoh.

Status changed from Open to Rejected

In #708, Matz approved a related ticket #4890.
Let's discuss there.

-- 
Yusuke Endoh <mame@tsg.ne.jp>
----------------------------------------
Feature #5663: Combined map/select method
https://bugs.ruby-lang.org/issues/5663

Author: Yehuda Katz
Status: Rejected
Priority: Normal
Assignee: 
Category: lib
Target version: 2.0.0


It is pretty common to want to map over an Enumerable, but only include the elements that match a particular filter. A common idiom is:

enum.map { |i| i + 1 if i.even? }.compact

It is of course also possible to do this with two calls:

enum.select { |i| i.even? }.map { |i| i + 1 }

Both cases are clumsy and require two iterations through the loop. I'd like to propose a combined method:

enum.map_select { |i| i + 1 if i.even? }

The only caveat is that it would be impossible to intentionally return nil here; suggestions welcome. The naming is also a strawman; feel free to propose something better.


-- 
http://bugs.ruby-lang.org/

^ permalink raw reply	[flat|nested] 62+ messages in thread

* [ruby-core:42531] [ruby-trunk - Feature #5663] Combined map/select method
  2011-11-22 20:37 [ruby-core:41213] [ruby-trunk - Bug #5663][Open] Combined map/select method Yehuda Katz
                   ` (21 preceding siblings ...)
  2012-02-13 11:12 ` [ruby-core:42528] [ruby-trunk - Feature #5663][Rejected] " Yusuke Endoh
@ 2012-02-13 11:43 ` Rodrigo Rosenfeld Rosas
  2012-02-13 11:51 ` [ruby-core:42533] [ruby-trunk - Feature #5663][Assigned] " Yusuke Endoh
                   ` (22 subsequent siblings)
  45 siblings, 0 replies; 62+ messages in thread
From: Rodrigo Rosenfeld Rosas @ 2012-02-13 11:43 UTC (permalink / raw
  To: ruby-core


Issue #5663 has been updated by Rodrigo Rosenfeld Rosas.


I don't think #4890 removes the need for this ticket. This is about API, not implementation. Even if we can use lazy maps/collects to implement this API, I still think it should exist.
----------------------------------------
Feature #5663: Combined map/select method
https://bugs.ruby-lang.org/issues/5663

Author: Yehuda Katz
Status: Rejected
Priority: Normal
Assignee: 
Category: lib
Target version: 2.0.0


It is pretty common to want to map over an Enumerable, but only include the elements that match a particular filter. A common idiom is:

enum.map { |i| i + 1 if i.even? }.compact

It is of course also possible to do this with two calls:

enum.select { |i| i.even? }.map { |i| i + 1 }

Both cases are clumsy and require two iterations through the loop. I'd like to propose a combined method:

enum.map_select { |i| i + 1 if i.even? }

The only caveat is that it would be impossible to intentionally return nil here; suggestions welcome. The naming is also a strawman; feel free to propose something better.


-- 
http://bugs.ruby-lang.org/

^ permalink raw reply	[flat|nested] 62+ messages in thread

* [ruby-core:42533] [ruby-trunk - Feature #5663][Assigned] Combined map/select method
  2011-11-22 20:37 [ruby-core:41213] [ruby-trunk - Bug #5663][Open] Combined map/select method Yehuda Katz
                   ` (22 preceding siblings ...)
  2012-02-13 11:43 ` [ruby-core:42531] [ruby-trunk - Feature #5663] " Rodrigo Rosenfeld Rosas
@ 2012-02-13 11:51 ` Yusuke Endoh
  2012-02-13 12:09 ` [ruby-core:42537] [ruby-trunk - Feature #5663] " Rodrigo Rosenfeld Rosas
                   ` (21 subsequent siblings)
  45 siblings, 0 replies; 62+ messages in thread
From: Yusuke Endoh @ 2012-02-13 11:51 UTC (permalink / raw
  To: ruby-core


Issue #5663 has been updated by Yusuke Endoh.

Status changed from Rejected to Assigned
Assignee set to Yukihiro Matsumoto

Okay reopened.

Do you mean we need map_select as a shorthand?

-- 
Yusuke Endoh <mame@tsg.ne.jp>
----------------------------------------
Feature #5663: Combined map/select method
https://bugs.ruby-lang.org/issues/5663

Author: Yehuda Katz
Status: Assigned
Priority: Normal
Assignee: Yukihiro Matsumoto
Category: lib
Target version: 2.0.0


It is pretty common to want to map over an Enumerable, but only include the elements that match a particular filter. A common idiom is:

enum.map { |i| i + 1 if i.even? }.compact

It is of course also possible to do this with two calls:

enum.select { |i| i.even? }.map { |i| i + 1 }

Both cases are clumsy and require two iterations through the loop. I'd like to propose a combined method:

enum.map_select { |i| i + 1 if i.even? }

The only caveat is that it would be impossible to intentionally return nil here; suggestions welcome. The naming is also a strawman; feel free to propose something better.


-- 
http://bugs.ruby-lang.org/

^ permalink raw reply	[flat|nested] 62+ messages in thread

* [ruby-core:42537] [ruby-trunk - Feature #5663] Combined map/select method
  2011-11-22 20:37 [ruby-core:41213] [ruby-trunk - Bug #5663][Open] Combined map/select method Yehuda Katz
                   ` (23 preceding siblings ...)
  2012-02-13 11:51 ` [ruby-core:42533] [ruby-trunk - Feature #5663][Assigned] " Yusuke Endoh
@ 2012-02-13 12:09 ` Rodrigo Rosenfeld Rosas
  2012-02-13 15:30 ` [ruby-core:42555] " Thomas Sawyer
                   ` (20 subsequent siblings)
  45 siblings, 0 replies; 62+ messages in thread
From: Rodrigo Rosenfeld Rosas @ 2012-02-13 12:09 UTC (permalink / raw
  To: ruby-core


Issue #5663 has been updated by Rodrigo Rosenfeld Rosas.


Yes, Yusuke, exactly. Thanks for reopening.
----------------------------------------
Feature #5663: Combined map/select method
https://bugs.ruby-lang.org/issues/5663

Author: Yehuda Katz
Status: Assigned
Priority: Normal
Assignee: Yukihiro Matsumoto
Category: lib
Target version: 2.0.0


It is pretty common to want to map over an Enumerable, but only include the elements that match a particular filter. A common idiom is:

enum.map { |i| i + 1 if i.even? }.compact

It is of course also possible to do this with two calls:

enum.select { |i| i.even? }.map { |i| i + 1 }

Both cases are clumsy and require two iterations through the loop. I'd like to propose a combined method:

enum.map_select { |i| i + 1 if i.even? }

The only caveat is that it would be impossible to intentionally return nil here; suggestions welcome. The naming is also a strawman; feel free to propose something better.


-- 
http://bugs.ruby-lang.org/

^ permalink raw reply	[flat|nested] 62+ messages in thread

* [ruby-core:42555] [ruby-trunk - Feature #5663] Combined map/select method
  2011-11-22 20:37 [ruby-core:41213] [ruby-trunk - Bug #5663][Open] Combined map/select method Yehuda Katz
                   ` (24 preceding siblings ...)
  2012-02-13 12:09 ` [ruby-core:42537] [ruby-trunk - Feature #5663] " Rodrigo Rosenfeld Rosas
@ 2012-02-13 15:30 ` Thomas Sawyer
  2012-02-13 19:45 ` [ruby-core:42566] " Joshua Ballanco
                   ` (19 subsequent siblings)
  45 siblings, 0 replies; 62+ messages in thread
From: Thomas Sawyer @ 2012-02-13 15:30 UTC (permalink / raw
  To: ruby-core


Issue #5663 has been updated by Thomas Sawyer.


One of the problems with this method is that in becomes impossible to get `nil` or `false` as a valid selection/non-compaction.

Couple thoughts on handling this. For starters maybe #compact should be able to take an argument, e.g.

  [1,2,3,1].compact(1) => [2,3]

(This in itself seems pretty useful, regardless.)

Then a #compact_map could do the same. If we need to be able to get nil/false results we could then use an alternative.

  foo = Object.new

  [0,1,-1].compact_map(foo){ |e| e.zero? ? foo : (e > 0 ? true : false) } => [true,false]

(Here's a case where some sort of global `null` instance might be useful, in place of `foo`.)

But then again, a delayed enumeration is about as concise, and maybe a bit easier to read.

  [0,1,-1].denum.select{ |e| !e.zero? }.map{ |e| e > 0 ? true : false }.to_a

Something to consider.

----------------------------------------
Feature #5663: Combined map/select method
https://bugs.ruby-lang.org/issues/5663

Author: Yehuda Katz
Status: Assigned
Priority: Normal
Assignee: Yukihiro Matsumoto
Category: lib
Target version: 2.0.0


It is pretty common to want to map over an Enumerable, but only include the elements that match a particular filter. A common idiom is:

enum.map { |i| i + 1 if i.even? }.compact

It is of course also possible to do this with two calls:

enum.select { |i| i.even? }.map { |i| i + 1 }

Both cases are clumsy and require two iterations through the loop. I'd like to propose a combined method:

enum.map_select { |i| i + 1 if i.even? }

The only caveat is that it would be impossible to intentionally return nil here; suggestions welcome. The naming is also a strawman; feel free to propose something better.


-- 
http://bugs.ruby-lang.org/

^ permalink raw reply	[flat|nested] 62+ messages in thread

* [ruby-core:42566] [ruby-trunk - Feature #5663] Combined map/select method
  2011-11-22 20:37 [ruby-core:41213] [ruby-trunk - Bug #5663][Open] Combined map/select method Yehuda Katz
                   ` (25 preceding siblings ...)
  2012-02-13 15:30 ` [ruby-core:42555] " Thomas Sawyer
@ 2012-02-13 19:45 ` Joshua Ballanco
  2012-02-13 20:17 ` [ruby-core:42568] " Rodrigo Rosenfeld Rosas
                   ` (18 subsequent siblings)
  45 siblings, 0 replies; 62+ messages in thread
From: Joshua Ballanco @ 2012-02-13 19:45 UTC (permalink / raw
  To: ruby-core


Issue #5663 has been updated by Joshua Ballanco.


What about using "next" for this purpose? Currently:

> (1..10).to_a.map { |i| i % 3 == 0 ? next : i**2 }
 => [1, 4, nil, 16, 25, nil, 49, 64, nil, 100]

Is it so common to use "next" with a return value inside of an Enumerable#map call? Even so, could we special case "next" so that instead of returning nil, it skips the element entirely?
----------------------------------------
Feature #5663: Combined map/select method
https://bugs.ruby-lang.org/issues/5663

Author: Yehuda Katz
Status: Assigned
Priority: Normal
Assignee: Yukihiro Matsumoto
Category: lib
Target version: 2.0.0


It is pretty common to want to map over an Enumerable, but only include the elements that match a particular filter. A common idiom is:

enum.map { |i| i + 1 if i.even? }.compact

It is of course also possible to do this with two calls:

enum.select { |i| i.even? }.map { |i| i + 1 }

Both cases are clumsy and require two iterations through the loop. I'd like to propose a combined method:

enum.map_select { |i| i + 1 if i.even? }

The only caveat is that it would be impossible to intentionally return nil here; suggestions welcome. The naming is also a strawman; feel free to propose something better.


-- 
http://bugs.ruby-lang.org/

^ permalink raw reply	[flat|nested] 62+ messages in thread

* [ruby-core:42568] [ruby-trunk - Feature #5663] Combined map/select method
  2011-11-22 20:37 [ruby-core:41213] [ruby-trunk - Bug #5663][Open] Combined map/select method Yehuda Katz
                   ` (26 preceding siblings ...)
  2012-02-13 19:45 ` [ruby-core:42566] " Joshua Ballanco
@ 2012-02-13 20:17 ` Rodrigo Rosenfeld Rosas
  2012-02-13 20:48 ` [ruby-core:42571] " Thomas Sawyer
                   ` (17 subsequent siblings)
  45 siblings, 0 replies; 62+ messages in thread
From: Rodrigo Rosenfeld Rosas @ 2012-02-13 20:17 UTC (permalink / raw
  To: ruby-core


Issue #5663 has been updated by Rodrigo Rosenfeld Rosas.


Thomas, I didn't find your example for justifying a "null" instance good enough. Why not just using "nil" instead of "foo"?

But I liked your suggestion on "compact" allowing an argument defaulting to nil.

Joshua, I like the idea of next inside a map doing the compact thing, but I guess this will be hard to get approval for from Ruby Core team.

It would be a surprising feature in Ruby. Ruby is usually a pretty concise language with very little surprises... I'm not sure if they'll want to introduce such different "next" behavior only for the map/collect method.
----------------------------------------
Feature #5663: Combined map/select method
https://bugs.ruby-lang.org/issues/5663

Author: Yehuda Katz
Status: Assigned
Priority: Normal
Assignee: Yukihiro Matsumoto
Category: lib
Target version: 2.0.0


It is pretty common to want to map over an Enumerable, but only include the elements that match a particular filter. A common idiom is:

enum.map { |i| i + 1 if i.even? }.compact

It is of course also possible to do this with two calls:

enum.select { |i| i.even? }.map { |i| i + 1 }

Both cases are clumsy and require two iterations through the loop. I'd like to propose a combined method:

enum.map_select { |i| i + 1 if i.even? }

The only caveat is that it would be impossible to intentionally return nil here; suggestions welcome. The naming is also a strawman; feel free to propose something better.


-- 
http://bugs.ruby-lang.org/

^ permalink raw reply	[flat|nested] 62+ messages in thread

* [ruby-core:42571] [ruby-trunk - Feature #5663] Combined map/select method
  2011-11-22 20:37 [ruby-core:41213] [ruby-trunk - Bug #5663][Open] Combined map/select method Yehuda Katz
                   ` (27 preceding siblings ...)
  2012-02-13 20:17 ` [ruby-core:42568] " Rodrigo Rosenfeld Rosas
@ 2012-02-13 20:48 ` Thomas Sawyer
  2012-02-13 20:52 ` [ruby-core:42572] " Rodrigo Rosenfeld Rosas
                   ` (16 subsequent siblings)
  45 siblings, 0 replies; 62+ messages in thread
From: Thomas Sawyer @ 2012-02-13 20:48 UTC (permalink / raw
  To: ruby-core


Issue #5663 has been updated by Thomas Sawyer.


@rodrigo

Your right, I could have used nil, so my example wasn't a particularly good one for what I was trying to demonstrate. Here's a better demonstration:

  [0,1,-1,2].compact_map(foo) do |e|
    case e
    when  0 then nil
    when  1 then true
    when -1 then false
    else         foo
    end
  end
  #=> [nil,true,false]


----------------------------------------
Feature #5663: Combined map/select method
https://bugs.ruby-lang.org/issues/5663

Author: Yehuda Katz
Status: Assigned
Priority: Normal
Assignee: Yukihiro Matsumoto
Category: lib
Target version: 2.0.0


It is pretty common to want to map over an Enumerable, but only include the elements that match a particular filter. A common idiom is:

enum.map { |i| i + 1 if i.even? }.compact

It is of course also possible to do this with two calls:

enum.select { |i| i.even? }.map { |i| i + 1 }

Both cases are clumsy and require two iterations through the loop. I'd like to propose a combined method:

enum.map_select { |i| i + 1 if i.even? }

The only caveat is that it would be impossible to intentionally return nil here; suggestions welcome. The naming is also a strawman; feel free to propose something better.


-- 
http://bugs.ruby-lang.org/

^ permalink raw reply	[flat|nested] 62+ messages in thread

* [ruby-core:42572] [ruby-trunk - Feature #5663] Combined map/select method
  2011-11-22 20:37 [ruby-core:41213] [ruby-trunk - Bug #5663][Open] Combined map/select method Yehuda Katz
                   ` (28 preceding siblings ...)
  2012-02-13 20:48 ` [ruby-core:42571] " Thomas Sawyer
@ 2012-02-13 20:52 ` Rodrigo Rosenfeld Rosas
  2012-03-31 17:39 ` [ruby-core:44017] [ruby-trunk - Feature #5663][Feedback] " matz (Yukihiro Matsumoto)
                   ` (15 subsequent siblings)
  45 siblings, 0 replies; 62+ messages in thread
From: Rodrigo Rosenfeld Rosas @ 2012-02-13 20:52 UTC (permalink / raw
  To: ruby-core


Issue #5663 has been updated by Rodrigo Rosenfeld Rosas.


I supposed that was your point, but I waited for your new example, before talking about this.

The point is that usually we want some examples from the real world for considering some feature.

So, I don't find this example likely to actually happen on real software. Could you please provide some real scenario where having nils in the result would be better than any other values?
----------------------------------------
Feature #5663: Combined map/select method
https://bugs.ruby-lang.org/issues/5663

Author: Yehuda Katz
Status: Assigned
Priority: Normal
Assignee: Yukihiro Matsumoto
Category: lib
Target version: 2.0.0


It is pretty common to want to map over an Enumerable, but only include the elements that match a particular filter. A common idiom is:

enum.map { |i| i + 1 if i.even? }.compact

It is of course also possible to do this with two calls:

enum.select { |i| i.even? }.map { |i| i + 1 }

Both cases are clumsy and require two iterations through the loop. I'd like to propose a combined method:

enum.map_select { |i| i + 1 if i.even? }

The only caveat is that it would be impossible to intentionally return nil here; suggestions welcome. The naming is also a strawman; feel free to propose something better.


-- 
http://bugs.ruby-lang.org/

^ permalink raw reply	[flat|nested] 62+ messages in thread

* [ruby-core:44017] [ruby-trunk - Feature #5663][Feedback] Combined map/select method
  2011-11-22 20:37 [ruby-core:41213] [ruby-trunk - Bug #5663][Open] Combined map/select method Yehuda Katz
                   ` (29 preceding siblings ...)
  2012-02-13 20:52 ` [ruby-core:42572] " Rodrigo Rosenfeld Rosas
@ 2012-03-31 17:39 ` matz (Yukihiro Matsumoto)
  2012-04-01  2:18 ` [ruby-core:44034] [ruby-trunk - Feature #5663] " rosenfeld (Rodrigo Rosenfeld Rosas)
                   ` (14 subsequent siblings)
  45 siblings, 0 replies; 62+ messages in thread
From: matz (Yukihiro Matsumoto) @ 2012-03-31 17:39 UTC (permalink / raw
  To: ruby-core


Issue #5663 has been updated by matz (Yukihiro Matsumoto).

Status changed from Assigned to Feedback

I am OK with the original map_select behavior, but I don't like the name #map_select.
It is combination of -ect family name with map.

I prefer the name #filter, but it might be confused by simple alias of select.
Any idea?

Matz.


----------------------------------------
Feature #5663: Combined map/select method
https://bugs.ruby-lang.org/issues/5663#change-25545

Author: wycats (Yehuda Katz)
Status: Feedback
Priority: Normal
Assignee: matz (Yukihiro Matsumoto)
Category: lib
Target version: 2.0.0


It is pretty common to want to map over an Enumerable, but only include the elements that match a particular filter. A common idiom is:

enum.map { |i| i + 1 if i.even? }.compact

It is of course also possible to do this with two calls:

enum.select { |i| i.even? }.map { |i| i + 1 }

Both cases are clumsy and require two iterations through the loop. I'd like to propose a combined method:

enum.map_select { |i| i + 1 if i.even? }

The only caveat is that it would be impossible to intentionally return nil here; suggestions welcome. The naming is also a strawman; feel free to propose something better.


-- 
http://bugs.ruby-lang.org/

^ permalink raw reply	[flat|nested] 62+ messages in thread

* [ruby-core:44034] [ruby-trunk - Feature #5663] Combined map/select method
  2011-11-22 20:37 [ruby-core:41213] [ruby-trunk - Bug #5663][Open] Combined map/select method Yehuda Katz
                   ` (30 preceding siblings ...)
  2012-03-31 17:39 ` [ruby-core:44017] [ruby-trunk - Feature #5663][Feedback] " matz (Yukihiro Matsumoto)
@ 2012-04-01  2:18 ` rosenfeld (Rodrigo Rosenfeld Rosas)
  2012-04-01 17:40 ` [ruby-core:44043] " trans (Thomas Sawyer)
                   ` (13 subsequent siblings)
  45 siblings, 0 replies; 62+ messages in thread
From: rosenfeld (Rodrigo Rosenfeld Rosas) @ 2012-04-01  2:18 UTC (permalink / raw
  To: ruby-core


Issue #5663 has been updated by rosenfeld (Rodrigo Rosenfeld Rosas).


I actually prefer map_select as it is self-explanatory. There isn't a single word that is able to clearly provide the description for what it does.
----------------------------------------
Feature #5663: Combined map/select method
https://bugs.ruby-lang.org/issues/5663#change-25563

Author: wycats (Yehuda Katz)
Status: Feedback
Priority: Normal
Assignee: matz (Yukihiro Matsumoto)
Category: lib
Target version: 2.0.0


It is pretty common to want to map over an Enumerable, but only include the elements that match a particular filter. A common idiom is:

enum.map { |i| i + 1 if i.even? }.compact

It is of course also possible to do this with two calls:

enum.select { |i| i.even? }.map { |i| i + 1 }

Both cases are clumsy and require two iterations through the loop. I'd like to propose a combined method:

enum.map_select { |i| i + 1 if i.even? }

The only caveat is that it would be impossible to intentionally return nil here; suggestions welcome. The naming is also a strawman; feel free to propose something better.


-- 
http://bugs.ruby-lang.org/

^ permalink raw reply	[flat|nested] 62+ messages in thread

* [ruby-core:44035] Re: [ruby-trunk - Feature #5663] Combined map/select method
  2012-02-01  9:14   ` [ruby-core:42306] " Юрий Соколов
@ 2012-04-01  2:50     ` Nobuyoshi Nakada
  0 siblings, 0 replies; 62+ messages in thread
From: Nobuyoshi Nakada @ 2012-04-01  2:50 UTC (permalink / raw
  To: ruby-core

Hi,

(12/02/01 18:14), Юрий Соколов wrote:
>> Try each_with_object.
> 
> Yeah, it is good :) though it have a long name. It's pity that 1.9.3 hadn't
> it.

It's long indeed, but 1.9.3 had it.

  $ ./ruby -v -e 'p((1..3).each_with_object({}){|x,a|a[x]=x+1})'
  ruby 1.9.3p0 (2011-10-30 revision 33569) [x86_64-darwin11.3.0]
  {1=>2, 2=>3, 3=>4}

-- 
Nobu Nakada

^ permalink raw reply	[flat|nested] 62+ messages in thread

* [ruby-core:44043] [ruby-trunk - Feature #5663] Combined map/select method
  2011-11-22 20:37 [ruby-core:41213] [ruby-trunk - Bug #5663][Open] Combined map/select method Yehuda Katz
                   ` (31 preceding siblings ...)
  2012-04-01  2:18 ` [ruby-core:44034] [ruby-trunk - Feature #5663] " rosenfeld (Rodrigo Rosenfeld Rosas)
@ 2012-04-01 17:40 ` trans (Thomas Sawyer)
  2012-04-13  2:21 ` [ruby-core:44325] " shugo (Shugo Maeda)
                   ` (12 subsequent siblings)
  45 siblings, 0 replies; 62+ messages in thread
From: trans (Thomas Sawyer) @ 2012-04-01 17:40 UTC (permalink / raw
  To: ruby-core


Issue #5663 has been updated by trans (Thomas Sawyer).


Maybe `#select_yield`, since that what it is doing.

Which reminds me, is there an equivalent `#find` method to this (e.g. `#find_yield`), that returns the yield result instead of the element?


----------------------------------------
Feature #5663: Combined map/select method
https://bugs.ruby-lang.org/issues/5663#change-25572

Author: wycats (Yehuda Katz)
Status: Feedback
Priority: Normal
Assignee: matz (Yukihiro Matsumoto)
Category: lib
Target version: 2.0.0


It is pretty common to want to map over an Enumerable, but only include the elements that match a particular filter. A common idiom is:

enum.map { |i| i + 1 if i.even? }.compact

It is of course also possible to do this with two calls:

enum.select { |i| i.even? }.map { |i| i + 1 }

Both cases are clumsy and require two iterations through the loop. I'd like to propose a combined method:

enum.map_select { |i| i + 1 if i.even? }

The only caveat is that it would be impossible to intentionally return nil here; suggestions welcome. The naming is also a strawman; feel free to propose something better.


-- 
http://bugs.ruby-lang.org/

^ permalink raw reply	[flat|nested] 62+ messages in thread

* [ruby-core:44325] [ruby-trunk - Feature #5663] Combined map/select method
  2011-11-22 20:37 [ruby-core:41213] [ruby-trunk - Bug #5663][Open] Combined map/select method Yehuda Katz
                   ` (32 preceding siblings ...)
  2012-04-01 17:40 ` [ruby-core:44043] " trans (Thomas Sawyer)
@ 2012-04-13  2:21 ` shugo (Shugo Maeda)
  2012-04-13 11:51 ` [ruby-core:44337] " rosenfeld (Rodrigo Rosenfeld Rosas)
                   ` (11 subsequent siblings)
  45 siblings, 0 replies; 62+ messages in thread
From: shugo (Shugo Maeda) @ 2012-04-13  2:21 UTC (permalink / raw
  To: ruby-core


Issue #5663 has been updated by shugo (Shugo Maeda).


matz (Yukihiro Matsumoto) wrote:
> I am OK with the original map_select behavior, but I don't like the name #map_select.
> It is combination of -ect family name with map.
> 
> I prefer the name #filter, but it might be confused by simple alias of select.
> Any idea?

I think filter should be a simple alias of select.
# Otherwise, we can't complain about Scala's collect:p
How about filter_map?

I've found that Scheme has filter-map.
From SRFI-1:

  filter-map f clist1 clist2 ... -> list
  Like map, but only true values are saved.
  (filter-map (lambda (x) (and (number? x) (* x x))) '(a 1 b 3 c 7))
      => (1 9 49)
  The dynamic order in which the various applications of f are made is not specified.
  At least one of the list arguments must be finite.

----------------------------------------
Feature #5663: Combined map/select method
https://bugs.ruby-lang.org/issues/5663#change-25872

Author: wycats (Yehuda Katz)
Status: Feedback
Priority: Normal
Assignee: matz (Yukihiro Matsumoto)
Category: lib
Target version: 2.0.0


It is pretty common to want to map over an Enumerable, but only include the elements that match a particular filter. A common idiom is:

enum.map { |i| i + 1 if i.even? }.compact

It is of course also possible to do this with two calls:

enum.select { |i| i.even? }.map { |i| i + 1 }

Both cases are clumsy and require two iterations through the loop. I'd like to propose a combined method:

enum.map_select { |i| i + 1 if i.even? }

The only caveat is that it would be impossible to intentionally return nil here; suggestions welcome. The naming is also a strawman; feel free to propose something better.


-- 
http://bugs.ruby-lang.org/

^ permalink raw reply	[flat|nested] 62+ messages in thread

* [ruby-core:44337] [ruby-trunk - Feature #5663] Combined map/select method
  2011-11-22 20:37 [ruby-core:41213] [ruby-trunk - Bug #5663][Open] Combined map/select method Yehuda Katz
                   ` (33 preceding siblings ...)
  2012-04-13  2:21 ` [ruby-core:44325] " shugo (Shugo Maeda)
@ 2012-04-13 11:51 ` rosenfeld (Rodrigo Rosenfeld Rosas)
  2012-05-30 22:48 ` [ruby-core:45327] " alexeymuranov (Alexey Muranov)
                   ` (10 subsequent siblings)
  45 siblings, 0 replies; 62+ messages in thread
From: rosenfeld (Rodrigo Rosenfeld Rosas) @ 2012-04-13 11:51 UTC (permalink / raw
  To: ruby-core


Issue #5663 has been updated by rosenfeld (Rodrigo Rosenfeld Rosas).


+1
----------------------------------------
Feature #5663: Combined map/select method
https://bugs.ruby-lang.org/issues/5663#change-25882

Author: wycats (Yehuda Katz)
Status: Feedback
Priority: Normal
Assignee: matz (Yukihiro Matsumoto)
Category: lib
Target version: 2.0.0


It is pretty common to want to map over an Enumerable, but only include the elements that match a particular filter. A common idiom is:

enum.map { |i| i + 1 if i.even? }.compact

It is of course also possible to do this with two calls:

enum.select { |i| i.even? }.map { |i| i + 1 }

Both cases are clumsy and require two iterations through the loop. I'd like to propose a combined method:

enum.map_select { |i| i + 1 if i.even? }

The only caveat is that it would be impossible to intentionally return nil here; suggestions welcome. The naming is also a strawman; feel free to propose something better.


-- 
http://bugs.ruby-lang.org/

^ permalink raw reply	[flat|nested] 62+ messages in thread

* [ruby-core:45327] [ruby-trunk - Feature #5663] Combined map/select method
  2011-11-22 20:37 [ruby-core:41213] [ruby-trunk - Bug #5663][Open] Combined map/select method Yehuda Katz
                   ` (34 preceding siblings ...)
  2012-04-13 11:51 ` [ruby-core:44337] " rosenfeld (Rodrigo Rosenfeld Rosas)
@ 2012-05-30 22:48 ` alexeymuranov (Alexey Muranov)
  2012-05-31 11:32 ` [ruby-core:45334] " alexeymuranov (Alexey Muranov)
                   ` (9 subsequent siblings)
  45 siblings, 0 replies; 62+ messages in thread
From: alexeymuranov (Alexey Muranov) @ 2012-05-30 22:48 UTC (permalink / raw
  To: ruby-core


Issue #5663 has been updated by alexeymuranov (Alexey Muranov).


=begin
By the way, is anybody using the (({nil})) returned by (({#compact!})) ?

  enum.map { |i| i + 1 if i.even? }.compact

makes un unnecessary copy, but i cannot use

  enum.map { |i| i + 1 if i.even? }.compact!

because it will return (({nil})) if no changes were made.

Wouldn't it be better if (({#compact})) and (({#compact!})) returned the same thing?
=end

----------------------------------------
Feature #5663: Combined map/select method
https://bugs.ruby-lang.org/issues/5663#change-26908

Author: wycats (Yehuda Katz)
Status: Feedback
Priority: Normal
Assignee: matz (Yukihiro Matsumoto)
Category: lib
Target version: 2.0.0


It is pretty common to want to map over an Enumerable, but only include the elements that match a particular filter. A common idiom is:

enum.map { |i| i + 1 if i.even? }.compact

It is of course also possible to do this with two calls:

enum.select { |i| i.even? }.map { |i| i + 1 }

Both cases are clumsy and require two iterations through the loop. I'd like to propose a combined method:

enum.map_select { |i| i + 1 if i.even? }

The only caveat is that it would be impossible to intentionally return nil here; suggestions welcome. The naming is also a strawman; feel free to propose something better.


-- 
http://bugs.ruby-lang.org/

^ permalink raw reply	[flat|nested] 62+ messages in thread

* [ruby-core:45334] [ruby-trunk - Feature #5663] Combined map/select method
  2011-11-22 20:37 [ruby-core:41213] [ruby-trunk - Bug #5663][Open] Combined map/select method Yehuda Katz
                   ` (35 preceding siblings ...)
  2012-05-30 22:48 ` [ruby-core:45327] " alexeymuranov (Alexey Muranov)
@ 2012-05-31 11:32 ` alexeymuranov (Alexey Muranov)
  2012-06-19 20:32   ` [ruby-core:45720] " Roger Pack
  2012-08-14  9:24 ` [ruby-core:47181] " drKreso (Kresimir Bojcic)
                   ` (8 subsequent siblings)
  45 siblings, 1 reply; 62+ messages in thread
From: alexeymuranov (Alexey Muranov) @ 2012-05-31 11:32 UTC (permalink / raw
  To: ruby-core


Issue #5663 has been updated by alexeymuranov (Alexey Muranov).


How about `#map_some` as the name?
----------------------------------------
Feature #5663: Combined map/select method
https://bugs.ruby-lang.org/issues/5663#change-26915

Author: wycats (Yehuda Katz)
Status: Feedback
Priority: Normal
Assignee: matz (Yukihiro Matsumoto)
Category: lib
Target version: 2.0.0


It is pretty common to want to map over an Enumerable, but only include the elements that match a particular filter. A common idiom is:

enum.map { |i| i + 1 if i.even? }.compact

It is of course also possible to do this with two calls:

enum.select { |i| i.even? }.map { |i| i + 1 }

Both cases are clumsy and require two iterations through the loop. I'd like to propose a combined method:

enum.map_select { |i| i + 1 if i.even? }

The only caveat is that it would be impossible to intentionally return nil here; suggestions welcome. The naming is also a strawman; feel free to propose something better.


-- 
http://bugs.ruby-lang.org/

^ permalink raw reply	[flat|nested] 62+ messages in thread

* [ruby-core:45720] Re: [ruby-trunk - Feature #5663] Combined map/select method
  2012-05-31 11:32 ` [ruby-core:45334] " alexeymuranov (Alexey Muranov)
@ 2012-06-19 20:32   ` Roger Pack
  2012-06-19 22:11     ` [ruby-core:45723] " Rodrigo Rosenfeld Rosas
  0 siblings, 1 reply; 62+ messages in thread
From: Roger Pack @ 2012-06-19 20:32 UTC (permalink / raw
  To: ruby-core

> How about `#map_some` as the name?

#map_if ?
-r

^ permalink raw reply	[flat|nested] 62+ messages in thread

* [ruby-core:45723] Re: [ruby-trunk - Feature #5663] Combined map/select method
  2012-06-19 20:32   ` [ruby-core:45720] " Roger Pack
@ 2012-06-19 22:11     ` Rodrigo Rosenfeld Rosas
  0 siblings, 0 replies; 62+ messages in thread
From: Rodrigo Rosenfeld Rosas @ 2012-06-19 22:11 UTC (permalink / raw
  To: ruby-core

Em 19-06-2012 17:32, Roger Pack escreveu:
>> How about `#map_some` as the name?
> #map_if ?

I loved this one :)

^ permalink raw reply	[flat|nested] 62+ messages in thread

* [ruby-core:47181] [ruby-trunk - Feature #5663] Combined map/select method
  2011-11-22 20:37 [ruby-core:41213] [ruby-trunk - Bug #5663][Open] Combined map/select method Yehuda Katz
                   ` (36 preceding siblings ...)
  2012-05-31 11:32 ` [ruby-core:45334] " alexeymuranov (Alexey Muranov)
@ 2012-08-14  9:24 ` drKreso (Kresimir Bojcic)
  2012-08-14 11:25 ` [ruby-core:47184] " trans (Thomas Sawyer)
                   ` (7 subsequent siblings)
  45 siblings, 0 replies; 62+ messages in thread
From: drKreso (Kresimir Bojcic) @ 2012-08-14  9:24 UTC (permalink / raw
  To: ruby-core


Issue #5663 has been updated by drKreso (Kresimir Bojcic).


+1 I also like filter_map

(My other favourite would be map_selected which I think is more expressive for non-lisp-brainwashed)
----------------------------------------
Feature #5663: Combined map/select method
https://bugs.ruby-lang.org/issues/5663#change-28862

Author: wycats (Yehuda Katz)
Status: Feedback
Priority: Normal
Assignee: matz (Yukihiro Matsumoto)
Category: lib
Target version: 2.0.0


It is pretty common to want to map over an Enumerable, but only include the elements that match a particular filter. A common idiom is:

enum.map { |i| i + 1 if i.even? }.compact

It is of course also possible to do this with two calls:

enum.select { |i| i.even? }.map { |i| i + 1 }

Both cases are clumsy and require two iterations through the loop. I'd like to propose a combined method:

enum.map_select { |i| i + 1 if i.even? }

The only caveat is that it would be impossible to intentionally return nil here; suggestions welcome. The naming is also a strawman; feel free to propose something better.


-- 
http://bugs.ruby-lang.org/

^ permalink raw reply	[flat|nested] 62+ messages in thread

* [ruby-core:47184] [ruby-trunk - Feature #5663] Combined map/select method
  2011-11-22 20:37 [ruby-core:41213] [ruby-trunk - Bug #5663][Open] Combined map/select method Yehuda Katz
                   ` (37 preceding siblings ...)
  2012-08-14  9:24 ` [ruby-core:47181] " drKreso (Kresimir Bojcic)
@ 2012-08-14 11:25 ` trans (Thomas Sawyer)
  2012-08-14 12:50   ` [ruby-core:47188] " Sheldon Hearn
  2012-10-25 11:29 ` [ruby-core:48266] " yhara (Yutaka HARA)
                   ` (6 subsequent siblings)
  45 siblings, 1 reply; 62+ messages in thread
From: trans (Thomas Sawyer) @ 2012-08-14 11:25 UTC (permalink / raw
  To: ruby-core


Issue #5663 has been updated by trans (Thomas Sawyer).


Instead of thinking of it as a special type of #map, I suggest thinking about it as a special type of #select. The reason is that we could also use the same type of behavior for #find. Which is why I suggest #select_yield and #find_yield (or #yield_select and #yield_find). The names of both of these need to be considered together.



----------------------------------------
Feature #5663: Combined map/select method
https://bugs.ruby-lang.org/issues/5663#change-28865

Author: wycats (Yehuda Katz)
Status: Feedback
Priority: Normal
Assignee: matz (Yukihiro Matsumoto)
Category: lib
Target version: 2.0.0


It is pretty common to want to map over an Enumerable, but only include the elements that match a particular filter. A common idiom is:

enum.map { |i| i + 1 if i.even? }.compact

It is of course also possible to do this with two calls:

enum.select { |i| i.even? }.map { |i| i + 1 }

Both cases are clumsy and require two iterations through the loop. I'd like to propose a combined method:

enum.map_select { |i| i + 1 if i.even? }

The only caveat is that it would be impossible to intentionally return nil here; suggestions welcome. The naming is also a strawman; feel free to propose something better.


-- 
http://bugs.ruby-lang.org/

^ permalink raw reply	[flat|nested] 62+ messages in thread

* [ruby-core:47188] Re: [ruby-trunk - Feature #5663] Combined map/select method
  2012-08-14 11:25 ` [ruby-core:47184] " trans (Thomas Sawyer)
@ 2012-08-14 12:50   ` Sheldon Hearn
  0 siblings, 0 replies; 62+ messages in thread
From: Sheldon Hearn @ 2012-08-14 12:50 UTC (permalink / raw
  To: ruby-core

On Tue, Aug 14, 2012 at 1:25 PM, trans (Thomas Sawyer)
<transfire@gmail.com> wrote:
> Instead of thinking of it as a special type of #map, I suggest thinking about it as a special type of #select. The reason is that we could also use the same type of behavior for #find. Which is why I suggest #select_yield and #find_yield (or #yield_select and #yield_find). The names of both of these need to be considered together.

To me it looks like a not-so-special type of inject.

How would map_select differ from inject, please?

Ciao,
Sheldon.

^ permalink raw reply	[flat|nested] 62+ messages in thread

* [ruby-core:48266] [ruby-trunk - Feature #5663] Combined map/select method
  2011-11-22 20:37 [ruby-core:41213] [ruby-trunk - Bug #5663][Open] Combined map/select method Yehuda Katz
                   ` (38 preceding siblings ...)
  2012-08-14 11:25 ` [ruby-core:47184] " trans (Thomas Sawyer)
@ 2012-10-25 11:29 ` yhara (Yutaka HARA)
  2014-03-03 12:04 ` [ruby-core:61255] [ruby-trunk - Feature #5663] [Assigned] " shugo
                   ` (5 subsequent siblings)
  45 siblings, 0 replies; 62+ messages in thread
From: yhara (Yutaka HARA) @ 2012-10-25 11:29 UTC (permalink / raw
  To: ruby-core


Issue #5663 has been updated by yhara (Yutaka HARA).

Target version changed from 2.0.0 to next minor


----------------------------------------
Feature #5663: Combined map/select method
https://bugs.ruby-lang.org/issues/5663#change-31552

Author: wycats (Yehuda Katz)
Status: Feedback
Priority: Normal
Assignee: matz (Yukihiro Matsumoto)
Category: lib
Target version: next minor


It is pretty common to want to map over an Enumerable, but only include the elements that match a particular filter. A common idiom is:

enum.map { |i| i + 1 if i.even? }.compact

It is of course also possible to do this with two calls:

enum.select { |i| i.even? }.map { |i| i + 1 }

Both cases are clumsy and require two iterations through the loop. I'd like to propose a combined method:

enum.map_select { |i| i + 1 if i.even? }

The only caveat is that it would be impossible to intentionally return nil here; suggestions welcome. The naming is also a strawman; feel free to propose something better.


-- 
http://bugs.ruby-lang.org/

^ permalink raw reply	[flat|nested] 62+ messages in thread

* [ruby-core:61255] [ruby-trunk - Feature #5663] [Assigned] Combined map/select method
  2011-11-22 20:37 [ruby-core:41213] [ruby-trunk - Bug #5663][Open] Combined map/select method Yehuda Katz
                   ` (39 preceding siblings ...)
  2012-10-25 11:29 ` [ruby-core:48266] " yhara (Yutaka HARA)
@ 2014-03-03 12:04 ` shugo
  2014-03-03 13:55 ` [ruby-core:61257] [ruby-trunk - Feature #5663] " sawadatsuyoshi
                   ` (4 subsequent siblings)
  45 siblings, 0 replies; 62+ messages in thread
From: shugo @ 2014-03-03 12:04 UTC (permalink / raw
  To: ruby-core

Issue #5663 has been updated by Shugo Maeda.

Status changed from Feedback to Assigned

Yukihiro Matsumoto wrote:
> I am OK with the original map_select behavior, but I don't like the name #map_select.
> It is combination of -ect family name with map.
> 
> I prefer the name #filter, but it might be confused by simple alias of select.
> Any idea?

What do you think of the following counter proposals?

* select_yield
* filter_map
* map_if

----------------------------------------
Feature #5663: Combined map/select method
https://bugs.ruby-lang.org/issues/5663#change-45595

* Author: Yehuda Katz
* Status: Assigned
* Priority: Normal
* Assignee: Yukihiro Matsumoto
* Category: lib
* Target version: next minor
----------------------------------------
It is pretty common to want to map over an Enumerable, but only include the elements that match a particular filter. A common idiom is:

enum.map { |i| i + 1 if i.even? }.compact

It is of course also possible to do this with two calls:

enum.select { |i| i.even? }.map { |i| i + 1 }

Both cases are clumsy and require two iterations through the loop. I'd like to propose a combined method:

enum.map_select { |i| i + 1 if i.even? }

The only caveat is that it would be impossible to intentionally return nil here; suggestions welcome. The naming is also a strawman; feel free to propose something better.



-- 
http://bugs.ruby-lang.org/

^ permalink raw reply	[flat|nested] 62+ messages in thread

* [ruby-core:61257] [ruby-trunk - Feature #5663] Combined map/select method
  2011-11-22 20:37 [ruby-core:41213] [ruby-trunk - Bug #5663][Open] Combined map/select method Yehuda Katz
                   ` (40 preceding siblings ...)
  2014-03-03 12:04 ` [ruby-core:61255] [ruby-trunk - Feature #5663] [Assigned] " shugo
@ 2014-03-03 13:55 ` sawadatsuyoshi
  2014-03-03 20:27   ` [ruby-core:61264] " Joel VanderWerf
  2014-03-04 13:52 ` [ruby-core:61292] " sawadatsuyoshi
                   ` (3 subsequent siblings)
  45 siblings, 1 reply; 62+ messages in thread
From: sawadatsuyoshi @ 2014-03-03 13:55 UTC (permalink / raw
  To: ruby-core

Issue #5663 has been updated by Tsuyoshi Sawada.


I would like to propose:

    map_any
    map_while


----------------------------------------
Feature #5663: Combined map/select method
https://bugs.ruby-lang.org/issues/5663#change-45597

* Author: Yehuda Katz
* Status: Assigned
* Priority: Normal
* Assignee: Yukihiro Matsumoto
* Category: lib
* Target version: next minor
----------------------------------------
It is pretty common to want to map over an Enumerable, but only include the elements that match a particular filter. A common idiom is:

enum.map { |i| i + 1 if i.even? }.compact

It is of course also possible to do this with two calls:

enum.select { |i| i.even? }.map { |i| i + 1 }

Both cases are clumsy and require two iterations through the loop. I'd like to propose a combined method:

enum.map_select { |i| i + 1 if i.even? }

The only caveat is that it would be impossible to intentionally return nil here; suggestions welcome. The naming is also a strawman; feel free to propose something better.



-- 
http://bugs.ruby-lang.org/

^ permalink raw reply	[flat|nested] 62+ messages in thread

* [ruby-core:61264] Re: [ruby-trunk - Feature #5663] Combined map/select method
  2014-03-03 13:55 ` [ruby-core:61257] [ruby-trunk - Feature #5663] " sawadatsuyoshi
@ 2014-03-03 20:27   ` Joel VanderWerf
  0 siblings, 0 replies; 62+ messages in thread
From: Joel VanderWerf @ 2014-03-03 20:27 UTC (permalink / raw
  To: Ruby developers

On 03/03/2014 05:55 AM, sawadatsuyoshi@gmail.com wrote:
> Issue #5663 has been updated by Tsuyoshi Sawada.
>
>      map_any

Too close to #any? for me.

>      map_while

That one suggests that the iteration stops when the predicate is false.

What about:

       map_where

^ permalink raw reply	[flat|nested] 62+ messages in thread

* [ruby-core:61292] [ruby-trunk - Feature #5663] Combined map/select method
  2011-11-22 20:37 [ruby-core:41213] [ruby-trunk - Bug #5663][Open] Combined map/select method Yehuda Katz
                   ` (41 preceding siblings ...)
  2014-03-03 13:55 ` [ruby-core:61257] [ruby-trunk - Feature #5663] " sawadatsuyoshi
@ 2014-03-04 13:52 ` sawadatsuyoshi
  2014-03-18 18:27 ` [ruby-core:61578] " sawadatsuyoshi
                   ` (2 subsequent siblings)
  45 siblings, 0 replies; 62+ messages in thread
From: sawadatsuyoshi @ 2014-03-04 13:52 UTC (permalink / raw
  To: ruby-core

Issue #5663 has been updated by Tsuyoshi Sawada.


Also, regarding Yehuda Katz's concern:

> The only caveat is that it would be impossible to intentionally return nil here; suggestions welcome.

I would like to propose that the method takes an optional argument that determines what element is to be removed. By default, this is `nil`.

    [1, 2, 3, 4].partial_map{|i| i + 4 if i.even?} # => [6, 8]

    s = "abc"
    [0, 1, 2, 3, 4].partial_map(:ignore){|i| i.even? s[i] : :ignore} # => ["a", "c", nil]


----------------------------------------
Feature #5663: Combined map/select method
https://bugs.ruby-lang.org/issues/5663#change-45623

* Author: Yehuda Katz
* Status: Assigned
* Priority: Normal
* Assignee: Yukihiro Matsumoto
* Category: lib
* Target version: next minor
----------------------------------------
It is pretty common to want to map over an Enumerable, but only include the elements that match a particular filter. A common idiom is:

enum.map { |i| i + 1 if i.even? }.compact

It is of course also possible to do this with two calls:

enum.select { |i| i.even? }.map { |i| i + 1 }

Both cases are clumsy and require two iterations through the loop. I'd like to propose a combined method:

enum.map_select { |i| i + 1 if i.even? }

The only caveat is that it would be impossible to intentionally return nil here; suggestions welcome. The naming is also a strawman; feel free to propose something better.



-- 
http://bugs.ruby-lang.org/

^ permalink raw reply	[flat|nested] 62+ messages in thread

* [ruby-core:61578] [ruby-trunk - Feature #5663] Combined map/select method
  2011-11-22 20:37 [ruby-core:41213] [ruby-trunk - Bug #5663][Open] Combined map/select method Yehuda Katz
                   ` (42 preceding siblings ...)
  2014-03-04 13:52 ` [ruby-core:61292] " sawadatsuyoshi
@ 2014-03-18 18:27 ` sawadatsuyoshi
  2014-04-09 14:41 ` [ruby-core:61923] " epidemian
  2015-02-10 22:30 ` [ruby-core:68083] [Ruby trunk " wvvwwvw
  45 siblings, 0 replies; 62+ messages in thread
From: sawadatsuyoshi @ 2014-03-18 18:27 UTC (permalink / raw
  To: ruby-core

Issue #5663 has been updated by Tsuyoshi Sawada.


I came to think that, if this feature is to be added, then are other methods to be considered: `flat_map` and `to_h`. I think it should be either the case that the corresponding feature added to all of these methods, or none.

----------------------------------------
Feature #5663: Combined map/select method
https://bugs.ruby-lang.org/issues/5663#change-45861

* Author: Yehuda Katz
* Status: Assigned
* Priority: Normal
* Assignee: Yukihiro Matsumoto
* Category: lib
* Target version: next minor
----------------------------------------
It is pretty common to want to map over an Enumerable, but only include the elements that match a particular filter. A common idiom is:

enum.map { |i| i + 1 if i.even? }.compact

It is of course also possible to do this with two calls:

enum.select { |i| i.even? }.map { |i| i + 1 }

Both cases are clumsy and require two iterations through the loop. I'd like to propose a combined method:

enum.map_select { |i| i + 1 if i.even? }

The only caveat is that it would be impossible to intentionally return nil here; suggestions welcome. The naming is also a strawman; feel free to propose something better.



-- 
https://bugs.ruby-lang.org/

^ permalink raw reply	[flat|nested] 62+ messages in thread

* [ruby-core:61923] [ruby-trunk - Feature #5663] Combined map/select method
  2011-11-22 20:37 [ruby-core:41213] [ruby-trunk - Bug #5663][Open] Combined map/select method Yehuda Katz
                   ` (43 preceding siblings ...)
  2014-03-18 18:27 ` [ruby-core:61578] " sawadatsuyoshi
@ 2014-04-09 14:41 ` epidemian
  2015-02-10 22:30 ` [ruby-core:68083] [Ruby trunk " wvvwwvw
  45 siblings, 0 replies; 62+ messages in thread
From: epidemian @ 2014-04-09 14:41 UTC (permalink / raw
  To: ruby-core

Issue #5663 has been updated by Demian Ferreiro.


I found this issue looking for a single-pass alternative to `.map{...}.compact`.

The former example uses `{ |i| i + 1 if i.even? }`, which reads almost like a comprehension and has a clear separation between the condition and the transformation. But sometimes it's not so easy to achieve such separation:

~~~ruby
# Generate an array of integers from untrusted input.
['', '42', 'nope', :not_even_int_convertible].compact_map { |x| Integer(x) rescue nil } # => [42]
~~~

BTW, i think that `compact_map` sounds quite natural for what this method does, but it could also be an extension to `compact` as others have mentioned:

~~~ruby
['', '42', 'nope', :not_even_int_convertible].compact { |x| Integer(x) rescue nil } # => [42]
~~~


As long as this is considered an alternative to map + concat, i think it makes sense not to worry about the edge case of wanting to preserve the nils, as the purpose of compact is to wipe them out. For those cases a combination of `select` and `map` can be used, or `grep` with a proc as its "pattern" argument to avoid having two iterations.

----------------------------------------
Feature #5663: Combined map/select method
https://bugs.ruby-lang.org/issues/5663#change-46128

* Author: Yehuda Katz
* Status: Assigned
* Priority: Normal
* Assignee: Yukihiro Matsumoto
* Category: lib
* Target version: next minor
----------------------------------------
It is pretty common to want to map over an Enumerable, but only include the elements that match a particular filter. A common idiom is:

enum.map { |i| i + 1 if i.even? }.compact

It is of course also possible to do this with two calls:

enum.select { |i| i.even? }.map { |i| i + 1 }

Both cases are clumsy and require two iterations through the loop. I'd like to propose a combined method:

enum.map_select { |i| i + 1 if i.even? }

The only caveat is that it would be impossible to intentionally return nil here; suggestions welcome. The naming is also a strawman; feel free to propose something better.



-- 
https://bugs.ruby-lang.org/

^ permalink raw reply	[flat|nested] 62+ messages in thread

* [ruby-core:68083] [Ruby trunk - Feature #5663] Combined map/select method
  2011-11-22 20:37 [ruby-core:41213] [ruby-trunk - Bug #5663][Open] Combined map/select method Yehuda Katz
                   ` (44 preceding siblings ...)
  2014-04-09 14:41 ` [ruby-core:61923] " epidemian
@ 2015-02-10 22:30 ` wvvwwvw
  45 siblings, 0 replies; 62+ messages in thread
From: wvvwwvw @ 2015-02-10 22:30 UTC (permalink / raw
  To: ruby-core

Issue #5663 has been updated by Andrew Ledvina.


~~~
The only caveat is that it would be impossible to intentionally return nil here
~~~

I don't see why you need that, just have the block return a pair `(keep_if_true, mapped_value)`. I also would second the name `filter_map`. Ignoring all edge-cases you could just do something like:

```
module Array
  def filter_map
    result = []
    self.each do |elem|
      keep, value = yield elem
      result << value if keep
    end
    result
  end
end

> [1,32,9,33,2,13].filter_map{|v| [v < 20, v%2==1 ? v*2 : nil]]}
 => [2, 18, nil, 26]
```

Although to be fair, `filter_map` is just `reduce` with a more complicated block

```
> [1,32,9,33,2,13].reduce([]){|acc, v| v<20 ? v%2==1 ? acc << v*2 : acc << nil : nil; acc}
 => [2, 18, nil, 26]
```

----------------------------------------
Feature #5663: Combined map/select method
https://bugs.ruby-lang.org/issues/5663#change-51466

* Author: Yehuda Katz
* Status: Assigned
* Priority: Normal
* Assignee: Yukihiro Matsumoto
----------------------------------------
It is pretty common to want to map over an Enumerable, but only include the elements that match a particular filter. A common idiom is:

enum.map { |i| i + 1 if i.even? }.compact

It is of course also possible to do this with two calls:

enum.select { |i| i.even? }.map { |i| i + 1 }

Both cases are clumsy and require two iterations through the loop. I'd like to propose a combined method:

enum.map_select { |i| i + 1 if i.even? }

The only caveat is that it would be impossible to intentionally return nil here; suggestions welcome. The naming is also a strawman; feel free to propose something better.



-- 
https://bugs.ruby-lang.org/

^ permalink raw reply	[flat|nested] 62+ messages in thread

end of thread, other threads:[~2015-02-10 22:28 UTC | newest]

Thread overview: 62+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2011-11-22 20:37 [ruby-core:41213] [ruby-trunk - Bug #5663][Open] Combined map/select method Yehuda Katz
2011-11-22 20:43 ` [ruby-core:41215] [ruby-trunk - Bug #5663] " Rodrigo Rosenfeld Rosas
2011-11-22 20:45 ` [ruby-core:41217] " Rodrigo Rosenfeld Rosas
2011-11-22 21:15   ` [ruby-core:41218] " Adam Prescott
2011-11-22 21:37     ` [ruby-core:41221] " Yehuda Katz
2011-11-22 22:26 ` [ruby-core:41222] Re: [ruby-trunk - Bug #5663][Open] " Shugo Maeda
2011-11-23  0:17   ` [ruby-core:41232] " Yehuda Katz
2011-11-22 23:55 ` [ruby-core:41229] [ruby-trunk - Feature #5663] " Rodrigo Rosenfeld Rosas
2011-11-23 10:33 ` [ruby-core:41246] " Alexey Muranov
2011-11-23 15:21 ` [ruby-core:41251] " Rodrigo Rosenfeld Rosas
2011-11-23 16:53 ` [ruby-core:41254] " Alexey Muranov
2011-11-24  0:54 ` [ruby-core:41270] " Rodrigo Rosenfeld Rosas
2011-11-24  7:12 ` [ruby-core:41279] " Nobuyoshi Nakada
2011-11-24  8:49 ` [ruby-core:41280] " Thomas Sawyer
2011-11-24 11:41 ` [ruby-core:41285] " Rodrigo Rosenfeld Rosas
2011-11-24 11:43 ` [ruby-core:41286] " Rodrigo Rosenfeld Rosas
2011-11-25  3:00 ` [ruby-core:41294] " Nobuyoshi Nakada
2011-11-28  1:05   ` [ruby-core:41341] " Rodrigo Rosenfeld Rosas
2011-11-28  1:59     ` [ruby-core:41346] " Nobuyoshi Nakada
2011-11-28 12:31       ` [ruby-core:41361] " Rodrigo Rosenfeld Rosas
2011-11-28 23:30 ` [ruby-core:41381] " Alexey Muranov
2011-11-29 11:32 ` [ruby-core:41391] " Rodrigo Rosenfeld Rosas
2011-11-30  7:41   ` [ruby-core:41407] " Ondřej Bílka
2011-11-30 20:28     ` [ruby-core:41415] " Rodrigo Rosenfeld Rosas
2012-01-31 17:47 ` [ruby-core:42289] Re: [ruby-trunk - Bug #5663][Open] " Roger Pack
2012-02-01  2:17 ` [ruby-core:42296] " trans
2012-02-01  2:18 ` [ruby-core:42297] [ruby-trunk - Feature #5663] " Thomas Sawyer
2012-02-01  3:39   ` [ruby-core:42299] " Nobuyoshi Nakada
2012-02-01  4:10 ` [ruby-core:42301] " Yura Sokolov
2012-02-01  5:11 ` [ruby-core:42302] " Nobuyoshi Nakada
2012-02-01  9:14   ` [ruby-core:42306] " Юрий Соколов
2012-04-01  2:50     ` [ruby-core:44035] " Nobuyoshi Nakada
2012-02-01 11:41 ` [ruby-core:42308] " Thomas Sawyer
2012-02-13 11:12 ` [ruby-core:42528] [ruby-trunk - Feature #5663][Rejected] " Yusuke Endoh
2012-02-13 11:43 ` [ruby-core:42531] [ruby-trunk - Feature #5663] " Rodrigo Rosenfeld Rosas
2012-02-13 11:51 ` [ruby-core:42533] [ruby-trunk - Feature #5663][Assigned] " Yusuke Endoh
2012-02-13 12:09 ` [ruby-core:42537] [ruby-trunk - Feature #5663] " Rodrigo Rosenfeld Rosas
2012-02-13 15:30 ` [ruby-core:42555] " Thomas Sawyer
2012-02-13 19:45 ` [ruby-core:42566] " Joshua Ballanco
2012-02-13 20:17 ` [ruby-core:42568] " Rodrigo Rosenfeld Rosas
2012-02-13 20:48 ` [ruby-core:42571] " Thomas Sawyer
2012-02-13 20:52 ` [ruby-core:42572] " Rodrigo Rosenfeld Rosas
2012-03-31 17:39 ` [ruby-core:44017] [ruby-trunk - Feature #5663][Feedback] " matz (Yukihiro Matsumoto)
2012-04-01  2:18 ` [ruby-core:44034] [ruby-trunk - Feature #5663] " rosenfeld (Rodrigo Rosenfeld Rosas)
2012-04-01 17:40 ` [ruby-core:44043] " trans (Thomas Sawyer)
2012-04-13  2:21 ` [ruby-core:44325] " shugo (Shugo Maeda)
2012-04-13 11:51 ` [ruby-core:44337] " rosenfeld (Rodrigo Rosenfeld Rosas)
2012-05-30 22:48 ` [ruby-core:45327] " alexeymuranov (Alexey Muranov)
2012-05-31 11:32 ` [ruby-core:45334] " alexeymuranov (Alexey Muranov)
2012-06-19 20:32   ` [ruby-core:45720] " Roger Pack
2012-06-19 22:11     ` [ruby-core:45723] " Rodrigo Rosenfeld Rosas
2012-08-14  9:24 ` [ruby-core:47181] " drKreso (Kresimir Bojcic)
2012-08-14 11:25 ` [ruby-core:47184] " trans (Thomas Sawyer)
2012-08-14 12:50   ` [ruby-core:47188] " Sheldon Hearn
2012-10-25 11:29 ` [ruby-core:48266] " yhara (Yutaka HARA)
2014-03-03 12:04 ` [ruby-core:61255] [ruby-trunk - Feature #5663] [Assigned] " shugo
2014-03-03 13:55 ` [ruby-core:61257] [ruby-trunk - Feature #5663] " sawadatsuyoshi
2014-03-03 20:27   ` [ruby-core:61264] " Joel VanderWerf
2014-03-04 13:52 ` [ruby-core:61292] " sawadatsuyoshi
2014-03-18 18:27 ` [ruby-core:61578] " sawadatsuyoshi
2014-04-09 14:41 ` [ruby-core:61923] " epidemian
2015-02-10 22:30 ` [ruby-core:68083] [Ruby trunk " wvvwwvw

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).