Chaining & to_proc on symbol
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.
Chaining methods using Symbol#to_proc shorthand in Ruby?
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 nil
s 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.
Chaining block passing in ruby
Because :any?(&:zero?)
is not an appropriate symbol literal. You can make it a symbol by doing :"any?(&:zero?)"
, but still, there is no such method.
Is it possible to use &: (ampersand colon) notation with a parameter or with chaining in Ruby?
:to_s
is a symbol,not a method. So you can't pass any argument to it like :to_s(2)
. If you do so,you will get error.That's how your code wouldn't work.So [1, 2, 3].map(&:to_s(2))
is not possible,where as [1, 2, 3].map(&:to_s)
possible.&:to_s
means you are calling #to_proc
method on the symbol. Now in your case &:to_s(2)
means :to_s(2).to_proc
. Error will be happened before the call to the method #to_proc
.
:to_s.to_proc # => #<Proc:0x20e4178>
:to_s(2).to_proc # if you try and the error as below
syntax error, unexpected '(', expecting $end
p :to_s(2).to_proc
^
Now try your one and compare the error with above explanation :
[1, 2, 3].map(&:to_s(2))
syntax error, unexpected '(', expecting ')'
[1, 2, 3].map(&:to_s(2))
^
calling slice! with map / symbol_to_proc syntax
As far as I know that is the simplest way to do it without monkey patching as indicated in the link you gave. You really aren't saving much time by using a more compact format. If you want to compact it more, you can move the map into it's own method. then do something like
def map_slice!(arr, *fields)
arr.map {|i| i.slice!(*fields) }
end
map_slice!(arr, :sort, :suppress)
# Not much shorter than just using below
# Which is why it probably wasn't implemented.
arr.map {|i| i.slice!(:sort, :suppress) }
Explicitly yielding n values to Symbol#to_proc
Here's how you can do it:
class Enumerator
def explicitly
each { |e| yield(*e) }
end
end
I executed your tests against this and the proper results are returned.
UPDATE: Changed to not capture the block explicitly.
How do i invoke a method chain using map method, in ruby?
You can pass a block to map and put your expression within the block. Each member of the enumerable will be yielded in succession to the block.
category_ids = categories.map {|c| c._id.to_s }
doing ampersand for multiple fields does not work in ruby
Symbol#to_proc is useful as shorthand for the basic case of calling one method. If you want something more complicated just move to the longhand
['Hi', 'Yo'].map { |word| [word.upcase, word.downcase] }
which would return [['HI', 'hi'], ['YO', 'yo']]
- which you could then call flatten
on if what you want is ['HI', 'hi', 'YO', 'yo']
instead.
UPDATE: Since you actually want [['HI','YO'], ['hi', 'yo']]
you can call transpose on the results
['Hi', 'Yo'].map { |w| [w.upcase, w.downcase] }.transpose
Note: The following is a terrible idea and no one should implement it in real code because the meaning of Array#to_proc would be completely non-obvious (does it call all and return an array, does it chain, does it pass parameters to a method, etc), but since you've asked for it you can do something like
class Array
def to_proc
lambda { |o| map { |m| o.send(m) } }
end
end
which would allow
['Hi', 'Yo'].map(&[:upcase, :downcase]).transpose
to produce the answer you're asking for. It does save a couple of characters but it's not worth the ambiguity it adds to the code.
Related Topics
How to Express Infinity in Ruby
Failing Installing Pg Gem, "Mkmf.Rb Can't Find Header Files for Ruby" (MAC Osx 10.6.5)
Why Is Enumerable#Each_With_Object Deprecated
How to Find Each Instance of a Class in Ruby
How to Fire Raw Mongodb Queries Directly in Ruby
Converting a Hexadecimal Digest to Base64 in Ruby
How to Identify Aliased Methods in Ruby
How to Use Params with Slashes with Sinatra
Ruby: What Is the Easiest Way to Remove the First Element from an Array
Ruby on Rails: Delete Multiple Hash Keys
How to Test Exception Raising in Rails/Rspec
Why Doesn't "Rails S" Work from the App Directory
How to Read a File from Bottom to Top in Ruby
Is There a Cucumber Hook to Run Before and After Each Feature
Unix Commands Work on Server But Not in Ruby Ssh Session
Ruby | Find a Way to Find an Exception on the Same Word to Capitalize