Symbol-to-Proc: The &: Shortcut That Ruins Other Languages for You
&:method_name converts a symbol into a block that calls that method on each element. It's one of Ruby's most commonly used shortcuts and has no direct Perl equivalent. Once you start writing lines.map(&:strip) instead of lines.map { |l| l.strip }, every other language feels verbose.
Part 1: How It Works
The& operator calls to_proc on whatever follows it. Symbol#to_proc creates a proc that calls the named method on its argument.
# These are equivalent: words.map(&:upcase) words.map { |w| w.upcase } # The & converts :upcase into this proc: # Proc.new { |obj| obj.upcase }
Part 2: Common Usage
# Transform words.map(&:upcase) # uppercase all words words.map(&:strip) # strip whitespace from all words.map(&:chomp) # chomp all strings nums.map(&:to_s) # convert all to strings strings.map(&:to_i) # convert all to integers # Filter lines.reject(&:empty?) # remove empty lines nums.select(&:positive?) # keep positive numbers nums.select(&:even?) # keep even numbers # Check lines.any?(&:empty?) # any empty lines? lines.all?(&:frozen?) # all frozen? lines.none?(&:nil?) # no nils?
Part 3: Chaining
Chain multiple symbol-to-proc calls for clean pipelines:# Strip, filter empties, downcase lines.map(&:strip).reject(&:empty?).map(&:downcase) # Chomp and sort lines.map(&:chomp).sort
Part 4: With inject/reduce
# Sum (1..10).inject(:+) # => 55 # Note: no & needed with inject - it accepts bare symbol # Product (1..10).inject(:*) # => 3628800 # Concatenate words.inject(:+) # join all words (no separator)
Part 5: The Limitation
Symbol-to-proc only works for methods that take NO arguments. If you need to pass arguments, use a full block:# This WON'T work: lines.map(&:split(",")) # ERROR! # Use a full block instead: lines.map { |l| l.split(",") } # Or with numbered parameters (Ruby 2.7+): lines.map { _1.split(",") }
Part 6: Perl Comparison
# Perl: my @upper = map { uc($_) } @words; my @non_empty = grep { $_ ne '' } @lines;
The Ruby version is more concise when the operation is a simple no-argument method call. For anything more complex, you're back to full blocks, same as Perl.# Ruby: upper = words.map(&:upcase) non_empty = lines.reject(&:empty?)
Part 7: Advanced, Creating Your Own
Any object with ato_proc method works with &:
This is niche, but it means the# Method objects work too method(:puts).to_proc lines.each(&method(:puts)) # prints each line
& operator is extensible. It's not magic, it's just to_proc all the way down.
Created By: Wildcard Wizard. Copyright 2026