Better name for #zip_with

Any ideas for a better name for:

    [1,2,3].zip_with([6,5,4]) { |a, b| 3 * a + b } #=> [9, 11, 13]

#zip_with comes from Haskell, but I think it's confusing because of
Ruby's #zip.

Doesn't zip basically do that already?

ruby-1.9.2-p180 :001 > l = [1,2,3]; r = [6,5,4]
=> [6, 5, 4]
ruby-1.9.2-p180 :002 > arr = []; l.zip(r) { |first, second| arr << 3 *
first + second }; arr
=> [9, 11, 13]

(Are you just trying to save the last step?)

~ jf

···

--
John Feminella
Principal Consultant, BitsBuilder
LI: http://www.linkedin.com/in/johnxf
SO: http://stackoverflow.com/users/75170/

IT seems closer to map than zip (IMHO) so maybe map_with ?
OR would cross_product cover it? Maybe too specific...

···

On Sun, Jul 17, 2011 at 9:44 PM, Intransition <transfire@gmail.com> wrote:

Any ideas for a better name for:

[1,2,3].zip_with([6,5,4]) { |a, b| 3 * a + b } #=> [9, 11, 13]

#zip_with comes from Haskell, but I think it's confusing because of
Ruby's #zip.

How about #zip_and_map? Notice that:

a.zip_with(b) { |c, d| ... }

is the same as the result of

a.zip(b).map { |c, d| ... }

~ jf

···

--
John Feminella
Principal Consultant, BitsBuilder
LI: http://www.linkedin.com/in/johnxf
SO: User John Feminella - Stack Overflow

On Sun, Jul 17, 2011 at 21:44, Intransition <transfire@gmail.com> wrote:

Any ideas for a better name for:

[1,2,3].zip_with([6,5,4]) { |a, b| 3 * a + b } #=> [9, 11, 13]

#zip_with comes from Haskell, but I think it's confusing because of
Ruby's #zip.

Actually, I didn't know zip took a block. Good to know. So yea, that
makes it much closer than I realized. But why doesn't it map the
results? That's unfortunate. I think I will submit a feature request
for Ruby.

Thanks.

···

On Jul 17, 10:13 pm, John Feminella <jo...@bitsbuilder.com> wrote:

Doesn't zip basically do that already?

ruby-1.9.2-p180 :001 > l = [1,2,3]; r = [6,5,4]
=> [6, 5, 4]
ruby-1.9.2-p180 :002 > arr = ; l.zip(r) { |first, second| arr << 3 *
first + second }; arr
=> [9, 11, 13]

(Are you just trying to save the last step?)

Ah, right. `#zip_map` would makes sense then. But per your last post,
I think I may override #zip itself.

···

On Jul 17, 10:36 pm, John Feminella <jo...@bitsbuilder.com> wrote:

How about #zip_and_map? Notice that:

> a.zip_with(b) { |c, d| ... }

is the same as the result of

> a.zip(b).map { |c, d| ... }

#map_with does read right, doesn't it. hmm...

···

On Jul 17, 10:16 pm, Chris Hulan <chris.hu...@gmail.com> wrote:

IT seems closer to map than zip (IMHO) so maybe map_with ?
OR would cross_product cover it? Maybe too specific...

Thomas Sawyer wrote in post #1011313:

How about #zip_and_map? Notice that:

> a.zip_with(b) { |c, d| ... }

is the same as the result of

> a.zip(b).map { |c, d| ... }

Ah, right. `#zip_map` would makes sense then. But per your last post,
I think I may override #zip itself.

Not sure whether I find this a good idea. Reason: #map has overhead of
creating a new Array with the same length as the input. That should not
be the default behavior IMHO. A clean separation would be

.zip() => Enumerator
.zip() {|a,b| ...} => nil (as today) or self (i.e. leftmost Array)

Then we can efficiently have .zip().map {|a,b| ...}

But it would break old code. :frowning:

So, today for efficient zip + map we would have to do

.enum_for(:zip, ).map {|a,b| ...}

Kind regards

robert

···

On Jul 17, 10:36pm, John Feminella <jo...@bitsbuilder.com> wrote:

--
Posted via http://www.ruby-forum.com/\.

So, don't do that; just return an Enumerator that returns the
successive results of applying the given block to the elements that
would be returned by the Enumerator that would be returned by the
non-block form of #zip.

···

On Mon, Jul 18, 2011 at 10:25 AM, Robert Klemme <shortcutter@googlemail.com> wrote:

Thomas Sawyer wrote in post #1011313:

On Jul 17, 10:36pm, John Feminella <jo...@bitsbuilder.com> wrote:

How about #zip_and_map? Notice that:

> a.zip_with(b) { |c, d| ... }

is the same as the result of

> a.zip(b).map { |c, d| ... }

Ah, right. `#zip_map` would makes sense then. But per your last post,
I think I may override #zip itself.

Not sure whether I find this a good idea. Reason: #map has overhead of
creating a new Array with the same length as the input. That should not
be the default behavior IMHO.

Thanks. If I add to Facets I'll utilize this.

I'm starting to think, however, that it makes more sense to add
optional arguments to #map itself. Consider that #zip returns an assoc
array, that's it's expected behavior. So it's probably best not to
alter that. Whereas map can return any form of array based on the
block.

    [1,2,3].map([2,3,4], [5,6,7]) { |a,b,c| ... }

Map has free arguments, so why not?

···

On Jul 18, 1:25 pm, Robert Klemme <shortcut...@googlemail.com> wrote:

Thomas Sawyer wrote in post #1011313:

> On Jul 17, 10:36pm, John Feminella <jo...@bitsbuilder.com> wrote:
>> How about #zip_and_map? Notice that:

>> > a.zip_with(b) { |c, d| ... }

>> is the same as the result of

>> > a.zip(b).map { |c, d| ... }

> Ah, right. `#zip_map` would makes sense then. But per your last post,
> I think I may override #zip itself.

Not sure whether I find this a good idea. Reason: #map has overhead of
creating a new Array with the same length as the input. That should not
be the default behavior IMHO. A clean separation would be

.zip() => Enumerator
.zip() {|a,b| ...} => nil (as today) or self (i.e. leftmost Array)

Then we can efficiently have .zip().map {|a,b| ...}

But it would break old code. :frowning:

So, today for efficient zip + map we would have to do

.enum_for(:zip, ).map {|a,b| ...}

What exactly do you mean? #to_enum does not honor a block:

irb(main):001:0> a=5.times.to_a
=> [0, 1, 2, 3, 4]
irb(main):002:0> b=a.to_enum(:map) {|x|x*2}
=> #<Enumerator: [0, 1, 2, 3, 4]:map>
irb(main):003:0> b.to_a
=> [0, 1, 2, 3, 4]

Did you mean Generator?

irb(main):012:0> b=Enumerator.new {|y| a.each {|x| y << x*2}}
=> #<Enumerator: #<Enumerator::Generator:0x106afc60>:each>
irb(main):013:0> b.to_a
=> [0, 2, 4, 6, 8]

With #zip

irb(main):014:0> b=a.dup
=> [0, 1, 2, 3, 4]
irb(main):015:0> i=Enumerator.new {|y| a.zip(b){|m,n| y << m - n} }
=> #<Enumerator: #<Enumerator::Generator:0x1066d248>:each>
irb(main):016:0> i.to_a
=> [0, 0, 0, 0, 0]

Kind regards

robert

···

On Sun, Jul 24, 2011 at 8:24 AM, Christopher Dicely <cmdicely@gmail.com> wrote:

On Mon, Jul 18, 2011 at 10:25 AM, Robert Klemme > <shortcutter@googlemail.com> wrote:

Thomas Sawyer wrote in post #1011313:

On Jul 17, 10:36pm, John Feminella <jo...@bitsbuilder.com> wrote:

How about #zip_and_map? Notice that:

> a.zip_with(b) { |c, d| ... }

is the same as the result of

> a.zip(b).map { |c, d| ... }

Ah, right. `#zip_map` would makes sense then. But per your last post,
I think I may override #zip itself.

Not sure whether I find this a good idea. Reason: #map has overhead of
creating a new Array with the same length as the input. That should not
be the default behavior IMHO.

So, don't do that; just return an Enumerator that returns the
successive results of applying the given block to the elements that
would be returned by the Enumerator that would be returned by the
non-block form of #zip.

--
remember.guy do |as, often| as.you_can - without end
http://blog.rubybestpractices.com/

I'm starting to think, however, that it makes more sense to add
optional arguments to #map itself. Consider that #zip returns an assoc
array, that's it's expected behavior. So it's probably best not to
alter that. Whereas map can return any form of array based on the
block.

[1,2,3].map([2,3,4], [5,6,7]) { |a,b,c| ... }

Wouldn't that be

[1,2,3].map([2,3,4], [5,6,7]) { |a,b| ... }

?

Map has free arguments, so why not?

Orthogonality probably. And it is not entirely clear whether map +
zip is the most common or most useful use. Others may want to use
arguments to #map for #grep like selection or even other uses. Who
decides which use wins and becomes standard?

Kind regards

robert

···

On Mon, Jul 25, 2011 at 1:16 AM, Intransition <transfire@gmail.com> wrote:

--
remember.guy do |as, often| as.you_can - without end
http://blog.rubybestpractices.com/

What about cutting to the point of the method and calling it #zip_map (first
zip, then map)? It isn't as readable but it avoids the misleading parts of
#zip_with and the introduction of zipping functionality to #map.