1

Is there a nice way to create a Ruby array chainable on the fly that combines map and inject?

Here's what I mean. Let a be an array of integers, then to get all sums of 2 adjacent elements we can do:

a.each_cons(2).map(&:sum)

We can also get the product of all the elements of an array a by:

a.inject(1,&:*)

But we can't do:

a.each_cons(2).map(&:inject(1,&:*))

We can, however, define an array chainable:

class Array

  def prod
    return self.inject(1,&:*)
  end

end

Then a.each_cons(2).map(&:prod) works fine.

2 Answers2

3

If you use this wierd Symbol patch shown here:

https://stackoverflow.com/a/23711606/2981429

class Symbol
  def call(*args, &block)
    ->(caller, *rest) { caller.send(self, *rest, *args, &block) }
  end
end

This allows you to pass arguments to the proc shorthand by means of Currying:

[[1,2],[3,4]].map(&:inject.(1, &:*))
# => [2, 12]

I'm sure this has been requested in Ruby core many times, unfortunately I don't have a link to the Ruby forums right now but I promise you it's on there.

max pleaner
  • 26,189
  • 9
  • 66
  • 118
1

I doubt that this is what you're looking for, but don't forget that you can still call map with a normal block.

a.each_cons(2).map { |n1, n2| n1 * n2 }

Since you didn't mention it in the question I thought you might have overlooked the easiest option.

3limin4t0r
  • 19,353
  • 2
  • 31
  • 52