Skip to content

Instantly share code, notes, and snippets.

@elight
Created December 8, 2011 20:59
Show Gist options
  • Save elight/1448559 to your computer and use it in GitHub Desktop.
Save elight/1448559 to your computer and use it in GitHub Desktop.
<!DOCTYPE html
PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<link rel="stylesheet"
href="/Users/light/.vim/plugin/vim-markdown-preview/stylesheets/github.css">
</link>
<title> Untitled </title>
</head>
<body>
<div id="container">
<div id="centered">
<div id="article">
<div class="page">
<p>Let&rsquo;s Talk About Conditional Expressions</p>
<p>You know what bugs me? People who don&rsquo;t write idiomatic conditionals in Ruby.</p>
<p>Many folks, especially those who came out of Java, .NET, or C/C++, use and abuse the ternary. The ternary is a humble little production rule that works like so:</p>
<pre><code>&lt;boolean expression&gt; ? &lt;eval this expression if truthy&gt; : &lt;eval if falsey&gt;
</code></pre>
<p>The ternary can be useful if the truthy and falsey cases are terse and well-named. However, it&rsquo;s not uncommon to see multi-line ternaries or, even worse, nested ternaries. For example:</p>
<script src="https://gist.github.com/1448377.js?file=delegation_1.rb"></script>
<p>By the way, the above example comes out of Rails.</p>
<p>Accepting that the above is just painful, how could we make it hurt less? Specifically, let&rsquo;s focus on the nested ternary on Line 14 (accepting that there are other ways that the code can be made clearer).</p>
<p>For starters, let&rsquo;s DRY up these Hash lookups:</p>
<script src="https://gist.github.com/1448397.js?file=delegation_2.rb"></script>
<p>Now let&rsquo;s unravel this into more idiomatic Ruby. We&rsquo;ll extract the outer ternary into a functional style if-else. Remember that every expression in Ruby returns the value of its last executed expression. The if-else returns either the value of the computed String in the <strong><em>if</em></strong> or the empty String <strong><em>else</em></strong>. It has the advantage of containing more English words and fewer characters that resemble modem line noise or PERL.</p>
<script src="https://gist.github.com/1448450.js?file=delegation_3.rb"></script>
<p>We can get rid of this <strong><em>else</em></strong>. After all, it doesn&rsquo;t contain any logic. Let&rsquo;s just make it the default value for <strong><em>method_prefix</em></strong> and then assign a new value only when <strong><em>prefix</em></strong> is truthy.</p>
<script src="https://gist.github.com/1448492.js?file=delegation_4.rb"></script>
<p>Ah so what this code really cares about, first and foremost, is whether <strong><em>prefix</em></strong> is falsey. When it&rsquo;s falsey, it just returns an empty String! Otherwise, if it&rsquo;s not, it generates a String possibly using the value of <strong><em>prefix</em></strong> if and only if <strong><em>prefix</em></strong> is not true &ndash; not a boolean.</p>
<p>So why should we try to avoid ternaries? Because, when used within a complex expression, they tend to lack the clarity of intent of an if-else. The lack of clarity likely resulted in the less DRY previous implementation. Once we introduced more clarity, it became obvious how this code could be DRY&rsquo;d up, resulting in better readability.</p>
</div>
</div>
</div>
</div>
</body>
</html>

Let's Talk About Conditional Expressions

You know what bugs me? People who don't write idiomatic conditionals in Ruby.

Many folks, especially those who came out of Java, .NET, or C/C++, use and abuse the ternary. The ternary is a humble little production rule that works like so:

<boolean expression> ? <eval this expression if truthy> : <eval if falsey>

The ternary can be useful if the truthy and falsey cases are terse and well-named. However, it's not uncommon to see multi-line ternaries or, even worse, nested ternaries. For example:

<script src="https://gist.github.com/1448377.js?file=delegation_1.rb"></script>

By the way, the above example comes out of Rails.

Accepting that the above is just painful, how could we make it hurt less? Specifically, let's focus on the nested ternary on Line 14 (accepting that there are other ways that the code can be made clearer).

For starters, let's DRY up these Hash lookups:

<script src="https://gist.github.com/1448397.js?file=delegation_2.rb"></script>

Now let's unravel this into more idiomatic Ruby. We'll extract the outer ternary into a functional style if-else. Remember that every expression in Ruby returns the value of its last executed expression. The if-else returns either the value of the computed String in the if or the empty String else. It has the advantage of containing more English words and fewer characters that resemble modem line noise or PERL.

<script src="https://gist.github.com/1448450.js?file=delegation_3.rb"></script>

We can get rid of this else. After all, it doesn't contain any logic. Let's just make it the default value for method_prefix and then assign a new value only when prefix is truthy.

<script src="https://gist.github.com/1448492.js?file=delegation_4.rb"></script>

Ah so what this code really cares about, first and foremost, is whether prefix is falsey. When it's falsey, it just returns an empty String! Otherwise, if it's not, it generates a String possibly using the value of prefix if and only if prefix is not true -- not a boolean.

So why should we try to avoid ternaries? Because, when used within a complex expression, they tend to lack the clarity of intent of an if-else. The lack of clarity likely resulted in the less DRY previous implementation. Once we introduced more clarity, it became obvious how this code could be DRY'd up, resulting in better readability.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment