It's well known to Rubyist &
will call to_proc
on a symbol, so
[:a, :b, :c].map(&:to_s)
is equivalent to
[:a, :b, :c].map { |e| e.to_s } # => ["a", "b", "c"]
Say I want to call another method right after to_s
, these two implementations will work:
[:a, :b, :c].map { |e| e.to_s.upcase }
[:a, :b, :c].map(&:to_s).map(&:upcase)
My question is, is there a way to chain the &
Symbol#to_proc
call in one parameter? Something like:
[:a, :b, :c].map(&:to_s:upcase)
Thanks!
Chaining breaks a task down into small steps and then teaches each step within the sequence by itself. For example, a child learning to wash his/her hands independently may start with learning to turn on the faucet. Once this initial skill is learned, the next step may be getting his/her hands, etc.
The 3 types of chaining are: Backward chaining, Forward chaining, and Total Task chaining. Backward Chaining- Backward chaining refers to teaching a behavioral chain beginning with the last step: you would completely prompt the entire chain of behaviors except the last step.
There are two types of chaining: forward chaining and backward chaining. In forward chaining, the behavior is taught in the steps as they naturally occur. In the example of tooth-brushing, the first step might be to take the toothbrush from its holder. The next step would be to take the toothpaste from the cabinet.
A behavior chain (chaining) is a type of teaching procedure used to connect individual behaviors to form more complex responses. Any action that requires more than one response or behavior to emit, can be taught via a chaining procedure.
If you're only doing:
%i[a b c].map { |e| e.to_s.upcase }
then just use the block and get on with more important things. If you're really doing a chain of Enumerable calls and find the blocks too visually noisy:
%i[a b c].map { |e| e.to_s.upcase }.some_chain_of_enumerable_calls...
then you could toss your logic into a lambda to help clean up the appearance:
to_s_upcase = lambda { |e| e.to_s.upcase }
%i[a b c].map(&to_s_upcase).some_chain_of_enumerable_calls...
or throw it in a method and say:
%i[a b c].map(&method(:to_s_upcase)).some_chain_of_enumerable_calls...
Either way, you're giving your little bit of logic a name (which is pretty much all &:symbol
is doing for you) to make the code more readable and easier to understand. In the specific case of to_s.upcase
, this is all a bit pointless but these approaches are quite useful when the block gets bigger.
You will need to define some method in advance, but this will have generality. You can do like this:
class Symbol
def * other
->x{x.send(self).send(other)}
end
end
[:a, :b, :c].map(&:to_s * :upcase)
[:a, :b, :c].map(&:to_s * :capitalize)
...
I chose *
as a method for functional composition.
And if you think you might use a third symbol, you can define like:
class Proc
def * other
->x{call(x).send(other)}
end
end
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With