First look: Procs in Ruby

Malorie Casimir
3 min readJun 7, 2018

--

If you read my last post, I used Ruby enumerators to create the basic structure of an opera aria and an art song using the #map and #each methods. I feel pretty comfortable with iteration and figured it was about time that I built upon what I already knew about it. My solution literally fell from the sky in the form of my instructor.

While sitting in a lecture today, my instructor used a shorthand that I was not familiar with. Names, in this case, is an array of strings.

names.map(&:upcase)

He very briefly explained that it was a shorthand for iteration.

But wait. I learned it this way:

names.map do |name|
name.upcase
end

More lines, more fun, right?

#stopcodesmells2018

I was pretty excited to look into this and found out that I can do things like iterate through databases, arrays, etc with just one line.

The ampersand is calling the #to_proc method and is essentially creating a new proc out of the object you pass it. Here’s the longhand of its functionality:

scream_things = Proc.new {|word| word.upcase}

This works the same way:

names = ["Pete", "Patricia", "Patty"]
names.map(&scream_things)
=> ["PETE", "PATRICIA", "PATTY"]

What exactly is a proc?

A proc, (short for procedure), is one of the three types of closures in Ruby along with blocks and lambdas. It’s a block of code that can use the local variables around it. If the variables are reassigned, they keep the value from their very first assignment.

Like most things in Ruby, a proc is an object and in this case, it’s an object of the Proc class and creating one will generate an instance.

=> #<Proc:0x007f8c1e0c2b30@(irb):51>

This shorthand really comes in handy and I highly encourage using it to make your code more concise and readable. If you’re building something that uses a certain method multiple times, you can save it to a proc. This comes especially handy when we need to extract data from a database. For example, if you need to sort some book titles from the “title” column in your “books” table, you can use a proc in addition to ActiveRecord’s #pluck method.

Book.pluck(:title).map(&:sort!) 

Brevity has never been more welcome!

Taking a look back at the code I wrote for my art song hash, I refactored it by using a proc to output the song. The results speak directly to the usefulness of procs.

We went from this:

8 lines of code

To this:

2 lines of code!

This outputs:

3 bars of a nostaligic introduction with a certain je ne sais quoi
Im wunderschönen Monat Mai,
Als alle Knospen sprangen,
Da ist in meinem Herzen
Die Liebe aufgegangen
2 bars seamlessly carrying us to verse 2
Im wunderschönen Monat Mai,
Als alle Vögel sangen,
Da hab ich ihr gestanden
Mein Sehnen und Verlangen.
3 bars of depth and longing that leads us tactfully into the next song in the cycle...
=> {:intro=>"3 bars of a nostaligic introduction with a certain je ne sais quoi", :verse_1=>"Im wundersch\u00F6nen Monat Mai,\nAls alle Knospen sprangen,\nDa ist in meinem Herzen\nDie Liebe aufgegangen", :interlude=>"2 bars seamlessly carrying us to verse 2", :verse_2=>"Im wundersch\u00F6nen Monat Mai,\nAls alle V\u00F6gel sangen,\nDa hab ich ihr gestanden\nMein Sehnen und Verlangen.", :postlude=>"3 bars of depth and longing that leads us tactfully into the next song in the cycle..."}

Unfortunately, I can’t use this for nested hashes and/or sub-arrays but I’m super excited to implement this into my code and learn more about closures in general.

In the future, I will edit this to be more wholesome and go into lambdas as well! Until then:

2.3.3 :061 > Time.now.friday?=> false

--

--