Many ways to express one thing in Ruby (_n syntax, _ prefix, & ampersand)

Today, coding in Ruby reminds me of the days when I was learning French. I wasn’t bad at expressing myself, but I struggled with vocabulary. One day, I needed to draft a professional email in French. After spending hours checking my grammar and searching for the right words, I hoped my language teacher would give me the green light to send it out. While she acknowledged that I had conveyed the meaning correctly, she also pointed out that I was repeating myself. She then introduced me to different ways to say the same thing, just to avoid using the same word. Below is an example of expressing the same thing in many ways in Ruby. This is an array of arrays, where each inner array contains a date and a volume value. Our goal is to calculate the total volume. [["2025-05", 1400], ["2025-04", 4200], ["2025-03", 3100]] Here are a few ways to do that in Ruby: Desctructure manually by assigning variables to each element total_volume = data.sum { |date, volume| volume } Desctructure manually and only assign variable that you are going to use. '_' in this context is considered as a thrown-away or not-used element total_volume = data.sum { | _, volume | volume } You can use chain map and sum. total_volume = data.map { | _, volume | volume }.sum Desctructure and make use of numbered parameter. Ruby reads the patter of each inner array (e.g ["2025-05", 1400]), first element("2025-05") as _1, second element (1400) as _2. total_volume = data.sum { _2 } reference: https://ruby-doc.org/core-2.7.0/Proc.html#class-Proc-label-Numbered+parameters It felt odd, but saving time and space to name your variable in an iteration. Why not? Here is the part when things get "Frenchy"(aka inconsistent and full of exceptions). Let's say now the data I need to deal with changes to new_data = [[1400, "2025-05"], [4200, "2025-04"], [3100, "2025-03"]]. Now the volume is the first element of each inner array, and we want to sum all those volumes. From what we learned earlier, it might feel natural to write: total_volume = new_data.sum { _1 } But nope! ❌ Since there is only 1 parameter, the destructuring magic disappears and _1 just gives you the whole pair, not the first item in the pair([1400, "2025-05"]). Hence if you are only passing _1 in the block, you have to index into the array explicitly. Like this: total_volume = data.sum { _1[0]} To go back to the example at the beginning of the article, you can write below to achieve the same result total_volume = data.sum { _1.last} Confusing! Isn't it? Use & ampersand operator to represent the iterating element. Note: This approach calls a method on the element, so use : instead of . total_volume = data.sum(&:last) total_volume = data.map(&:last).sum Ruby often feels like a language built on the motto: “There should be many -- and sometimes too many ways to do it, implicit or explicitly.” (Yes I am trying to contradict the Zen of Python: "there should be one-- and preferably only one --obvious way to do it") I like shortcuts. I like flexibility. But I’m not always convinced a language needs so many different ways to say the same thing. Ideally, I’d rather use a language to express many different ideas. So, what about you? What’s your favourite (or least favourite) Ruby shorthand? And if you code in another language, does it offer similar shortcuts? Let’s chat

Apr 8, 2025 - 23:10
 0
Many ways to express one thing in Ruby (_n syntax, _ prefix, & ampersand)

Today, coding in Ruby reminds me of the days when I was learning French. I wasn’t bad at expressing myself, but I struggled with vocabulary. One day, I needed to draft a professional email in French. After spending hours checking my grammar and searching for the right words, I hoped my language teacher would give me the green light to send it out.

While she acknowledged that I had conveyed the meaning correctly, she also pointed out that I was repeating myself. She then introduced me to different ways to say the same thing, just to avoid using the same word.

Below is an example of expressing the same thing in many ways in Ruby. This is an array of arrays, where each inner array contains a date and a volume value. Our goal is to calculate the total volume.
[["2025-05", 1400], ["2025-04", 4200], ["2025-03", 3100]]

Here are a few ways to do that in Ruby:

  1. Desctructure manually by assigning variables to each element
    total_volume = data.sum { |date, volume| volume }

  2. Desctructure manually and only assign variable that you are going to use. '_' in this context is considered as a thrown-away or not-used element
    total_volume = data.sum { | _, volume | volume }
    You can use chain map and sum.
    total_volume = data.map { | _, volume | volume }.sum

  3. Desctructure and make use of numbered parameter. Ruby reads the patter of each inner array (e.g ["2025-05", 1400]), first element("2025-05") as _1, second element (1400) as _2.
    total_volume = data.sum { _2 }
    reference: https://ruby-doc.org/core-2.7.0/Proc.html#class-Proc-label-Numbered+parameters
    It felt odd, but saving time and space to name your variable in an iteration. Why not?

  4. Here is the part when things get "Frenchy"(aka inconsistent and full of exceptions). Let's say now the data I need to deal with changes to
    new_data = [[1400, "2025-05"], [4200, "2025-04"], [3100, "2025-03"]].
    Now the volume is the first element of each inner array, and we want to sum all those volumes.
    From what we learned earlier, it might feel natural to write:
    total_volume = new_data.sum { _1 }
    But nope! ❌ Since there is only 1 parameter, the destructuring magic disappears and _1 just gives you the whole pair, not the first item in the pair([1400, "2025-05"]).
    Hence if you are only passing _1 in the block, you have to index into the array explicitly. Like this:
    total_volume = data.sum { _1[0]}
    To go back to the example at the beginning of the article, you can write below to achieve the same result
    total_volume = data.sum { _1.last}
    Confusing! Isn't it?

  5. Use & ampersand operator to represent the iterating element. Note: This approach calls a method on the element, so use : instead of .
    total_volume = data.sum(&:last)
    total_volume = data.map(&:last).sum

Ruby often feels like a language built on the motto:
“There should be many -- and sometimes too many ways to do it, implicit or explicitly.”

(Yes I am trying to contradict the Zen of Python: "there should be one-- and preferably only one --obvious way to do it")

I like shortcuts. I like flexibility. But I’m not always convinced a language needs so many different ways to say the same thing. Ideally, I’d rather use a language to express many different ideas.

So, what about you?

What’s your favourite (or least favourite) Ruby shorthand? And if you code in another language, does it offer similar shortcuts?

Let’s chat