2

Interpolation and Statements

I imagine most of you know that you can rewrite the above to use String interpolation:

"1 + 2 = #{1+2}"# => "1 + 2 = 3"

Let's think about that simple code a little bit more than we usually do though. What's really going on here? Obviously #{ … } inserts the result of the embedded code in the String, but it's important to realize that it also calls to_s() on that result to make it fit in the String.

We can really make use of that knowledge if we try. Here's an example:

I've built a trivial data class for managing names here. In that, I've tried to make use of interpolation to the fullest.

First, I needed to be able to build a reasonable representation of a full name no matter what data I have. My first example shows how this might play out when I only have a first name. That means first() will return "James" and last() will return nil. There are several ways to deal with this, but I chose what I consider to be one of the easiest.

I want something like a String for first and last name. Interpolation pretty much enforces this for me, since it automatically calls to_s() on the interpolated values. It just so happens that nil.to_s is "" and following that up with a simple strip() will remove any excess space due to missing names.

You can also see from the second example that I don't have to be strictly using String objects for the names. Anything with a reasonable to_s() will do.

Taking that one step further, the third example shows that even Name itself can benefit from a reasonable to_s(). This allows me to drop the full object right into any old String. You can take this really far by just adding sensible to_s() definitions to all kinds of objects. You could have objects representing data changes dropping themselves right into audit logs, have game move classes automatically serialize themselves for transport over a network protocol, or anything else you can think of.

Hopefully I've made that point now. The implicit to_s() of String interpolation is nice. Now let's look at another aspect of Ruby.

Many languages go to great lengths to distinguish between concepts like a statement and an expression, what each of those does, and where they can appear. Thankfully, Ruby doesn't much care.

What does that mean for us? Well, just about everything evaluates to something. You can kind of think of it as everything having a return value. (It's not really a return value in the case of something like a conditional, but I think that description makes for a good visual of what we are talking about here.) Let me show some examples:

Hopefully something in there surprises you. Take special note of the last two which pretty much show that Ruby tends to just go with nil when there's nothing else for a construct to evaluate to. We can use that.

Now, let's throw those two concepts together. Interpolation calls to_s() on the results of any code and we now know that most any code will have a result. That means we can write code like this:

Obviously, this is a pretty dumb method compared to the similar functionality in ActiveSupport and other libraries, but check out that last interpolation. I dumped a full unless right in the String. If it triggers, it will evaluate to a simple 's', which may be an unusual use of a conditional but is exactly what we need here. When it doesn't trigger, we know Ruby will punt with nil and nil.to_s is nothing, so it won't affect our output at all.

Like anything, you can take this technique too far. If you find yourself embedding entire programs in a String it's time to turn in your keyboard. However, if you find yourself slinging to_s() calls like they are going out of style, there's probably some cleanup you could try.

When my mother makes these great dishes that nobody else can do quite like her, I have taken to peering over her shoulder in the hopes I can learn to do it like her. Most of the time I'm busy guessing at ingredients and quantities, because she never weighs anything out. She does that by 'feel'. And most importantly: I watch her at work.

I'm guessing your posts and screencasts are made of:

at least 5 cups of playful enthusiasm for Ruby

heaps of programming skills

2 handfuls of intuition about pedagogy/teaching

You have a certain tone that says to me: 'I am having fun doing this'.
That makes it a joy to read, watch and learn.

I am definitely missing the "heaps of programming skills" you credit me with, but you're right on that I love what I do. Can you believe people pay me to play with Ruby (my favorite toy)? It still surprises me.

I'm nothing if not an amateur, so I might not be the best judge of what 'heaps of programming skills' contain :-)

They're no replacement for loving one's work, though.

For my part, I couldn't tell you precisely what keeps me going. It's a wide variety of factors. One such is definitely the kick I get when the core of a work in progress works for the first time. In those moments I always feel like laughing loudly and exclaiming 'It's alive! muhahahahaaaa!' :)

It's really insane the number of hours it can take me to get from no code to that moment.

Sometimes I wish I was a street sweeper. At least they have shorter work cycles.

About

James Edward Gray II was a part the Ruby community before Rails
ever shipped. He wrote code and documentation that now come with
the language. He ran two Red Dirt Ruby Conferences and is now
a regular on the Ruby Rogues podcast. He does all of this just
because he loves to program. This site is where he writes about
that.