Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Chaining & to_proc on symbol

Tags:

symbols

ruby

proc

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!

like image 340
sbs Avatar asked Jan 03 '16 17:01

sbs


People also ask

What is an example of chaining?

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.

What are the 3 types of chaining?

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.

What is chaining and its types?

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.

What is a chained behavior?

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.


2 Answers

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.

like image 173
mu is too short Avatar answered Sep 17 '22 22:09

mu is too short


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
like image 45
sawa Avatar answered Sep 19 '22 22:09

sawa