Chaining methods using Symbol#to_proc shorthand in Ruby?
Asked Answered
I

4

10

I'm wondering is there a way we can chain a method using (&:method)

For example:

array.reject { |x| x.strip.empty? }

To turn it into:

array.reject(&:strip.empty?)

I prefer the shorthand notation, due to its readability.

Immunogenetics answered 27/2, 2012 at 4:50 Comment(0)
F
7

No, there's no shorthand for that. You could define a method:

def really_empty?(x)
  x.strip.empty?
end

and use method:

array.reject(&method(:really_empty?))

or use a lambda:

really_empty = ->(x) { x.strip.empty? }
array.reject(&really_empty)

but I wouldn't call either of those better unless you have a use for really_empty? in enough places that splitting up the logic makes sense.

However, since you're using Rails, you could just use blank? instead of .strip.empty?:

array.reject(&:blank?)

Note that nil.blank? is true whereas nil.strip.empty? just hands you an exception so they're not quite equivalent; however, you probably want to reject nils as well so using blank? might be better anyway. blank? also returns true for false, {}, and [] but you probably don't have those in your array of strings.

Foppish answered 27/2, 2012 at 5:5 Comment(1)
You could also define the really_empty? method on the "array content class" (e.g. String) and then use it like the blank method. I am not advising this, just saying you could..Margie
P
2

It would be quite nice to write the above like that but it's not a supported syntax, the way that you would want to chain methods using the to_proc syntax (&:) is like so:

.map(&:strip).reject(&:empty?)

Philibeg answered 27/2, 2012 at 5:2 Comment(2)
Though in all reality rather than trying to chain them together like that, I would opt to use your original example as it is.Philibeg
I just ran a quick test out of interest and found that doing it your original way is over twice as fast (on my system) than doing it the double shorthand way (this makes sense as another temp array would have to be allocated as part of the map).Philibeg
L
2

A bit late to the party, but starting Ruby 2.6 you can do a Proc composition, which allows you to do, for example, this:

>> [:" aaa ", :"  ", :"ccc  "].map(&:to_s.to_proc >> :strip.to_proc >> :upcase.to_proc)
=> ["AAA", "", "CCC"]

This, of course, works with reject, too, so the original example in question would look like this:

[" aa ", "   ", "ccc   "].reject(&:strip.to_proc >> :empty?.to_proc)
# => [" aaa ", "ccc      "]
Latoshalatouche answered 21/7, 2022 at 10:36 Comment(0)
M
1

You can do it with the ampex gem:

require 'ampex'
array.reject &X.strip.empty?
Mauchi answered 26/8, 2016 at 15:24 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.