I’ve read about and practiced working with Ruby procs – all with contrived examples. That’s all well and good, but for me, the best learning comes with a heaping helping of context, which has been sorely missing from most of the contrived examples. I finally got some good context today when the need for a proc sprung up organically in a code challenge I was working on. So now I get it. I have a much stronger foothold on procs and when to use them. Hopefully seeing my process here will help build context for when you may be able to use a proc to solve a similar problem.
The Challenge: Building a Message Cipher
Here’s the challenge: I’m building a message cipher – a small program that will encode and decode messages. The cipher is very basic. When it encodes, it takes a letter and simply moves down the alphabet the number of letters provided by the given offset. For example:
Here’s my original
encode method. For the sake of simplicity in explaining procs, this encoder does not handle wrapping the alphabet for letters exceeding “z”.
After writing the encoder, I realized that the only difference between the process of encoding and decoding was the use of
-. Instead of creating a nearly identical
decode method, I decided to extract the encode/decode logic out into their own methods and leave the rest of the process in a method called
Then I realized that in order for the encode/decode methods to work, they’ll have to access the value of the
letter iterator happening in the
message.chars.each do |letter|... block inside the
processor method. Yikes. So how do you do that?
Procs! Tada! I found my own completely non-contrived use for a proc. At last. Here’s how it plays out:
Incorporating the proc logic
I created a new proc for both the
And then passed the proc into the
processor method as an argument.
I needed the proc inside the
each loop to:
- take the value of the current message input letter
- get the index of where it is stored in the
- add the offset value (3) to that index
- return the new index number for the encoded letter
decodemethods with their procs look like this:
processor method takes the proc and
.call()s it along with a
letter argument for each letter of the input message inside the
each loop. That new index is then used to get the value of the new letter from the
ALPHABET array and then the new letter is pushed into the
Lastly, the output array is joined back into a string and we get our encoded/decoded message.
Outputting the Results
Putting it all Together
Though this is not the most streamlined or elegant cipher code base, it has been useful to me in building my understanding of procs. I hope it’s been useful to you too!