How to perform conditional logic effectively with Ruby

Our first Ruby versus Java tutorial offered some refactoring opportunities. Here we look at using Ruby's if, elsif and case statement more efficiently.

In the first implementation of the rock-paper-scissors (or roshambo) game using Ruby, we employed a very simple approach to conditional processing. However, Ruby has a rich set of keywords that allow for conditional logic, including elsif, case, when and unless -- and by using these constructs properly, we can make our code more readable and more efficient.

With the use of elsif, conditional processing will stop as soon as a first true condition is encountered.

A more effective approach to programming our roshambo application would be to use elsif statements, because the processing would short-circuit out of subsequent if blocks as soon as a matching condition is found. As our code currently stands (see below), each if condition is executed, even if the first one is true. With the use of elsif, conditional processing will stop as soon as a first true condition is encountered.

Improving our conditional logic

Currently, our application, with its basic conditional logic, looks like this:

# The Ruby version of rock-paper-scissors

# Saved in a file named Roshambo.rb

# Variable declarations

outcome = "error"

server_gesture = "rock"

client_gesture = ""

# Prompt the user and obtain input

print "\nWill it be rock, paper or scissors?\n\n"

client_gesture = gets.chomp

# Perform conditional logic

if client_gesture == "rock"

    outcome = "tie"

end

if client_gesture == "paper"

    outcome = "win"

end

if client_gesture == "scissors"

    outcome = "loss"

end

# Render output to the console

print "\nYou chose #{client_gesture}. "

print "\nThe server chose #{server_gesture}. "

print "\nThe outcome is a #{outcome}.\n"

# End of the roshambo application

If we use the elsif and else keywords, our code becomes much more efficient:

if client_gesture == "rock"

    outcome = "tie"

elsif client_gesture == "paper"

    outcome = "win"

elsif client_gesture == "scissors"

    outcome = "loss"

else

     outcome = "error"

end

Figure 1 shows how a run of the code looks when the new changes are incorporated. As you can see, the rendering is the same as before, only the logic within the actual application has changed.

Running the Ruby app after updating the conditional logic.
Figure 1. Running the Ruby app after updating the conditional logic.

Conditional case blocks in Ruby

The Ruby language also provides a case statement for when there is a large number of conditions that might switch on a single value. Similar in many ways to Java's switch statement, Ruby's case, when and else block statements are analogous to Java's switch, case and default semantics. Here's how we would implement the conditional logic of the roshambo application using Ruby's case statement:

case

when client_gesture == "rock"

    outcome = "tie"

when client_gesture == "paper"

    outcome = "win"

when client_gesture == "scissors"

    outcome = "lose"

else

    outcome = "error"

end

An example of Ruby's unless semantics

Ruby also provides a neat compliment to the if statement, called unless. The unless condition will run as long as the condition being tested is not true. Anything accomplished with an unless statement also could be achieved through the use of an if block, but the use of the unless statement can in many instances make the source code much more readable.

Unfortunately, when we shoehorn the unless statement into the roshambo application, the code becomes more confusing, rather than more readable, but it is instructive to see the unless block in action:

outcome = "win"

unless client_gesture != "rock"

    outcome = "tie"

     unless client_gesture != "scissors"

           outcome = "lose"

           unless client_gesture != "paper"

                outcome = "error"

           end

     end

end

The code would read something like this: Let's assume the user won. That's true unless the user chose rock, which means the result would be a tie. And that is true unless the user chose scissors, in which case the user would have lost. The last unless that checks for the String paper basically says, if the user didn't enter paper -- and at this point we've already determined that he didn't enter rock or scissors -- then he must have entered some gibberish, so the outcome is set to the text error.

Whereas Java only provides if, else and switch blocks for performing conditional logic, Ruby provides a slightly richer set of tools with which blocks of code can be conditionally executed, including the if, else, elsif, unless and case statement -- all of which are demonstrated above.

What do you think of Ruby's unless condition? Is it helpful or is it more confusing? Let us know.

Modern programming languages made easy for Java developers

For those interested in learning Java, or for those who know Java and are interested in leveraging those skills in order to learn a complimentary language like JavaScript or Ruby, TheServerSide is providing a number of problem-driven tutorials that will help you master the fundamentals of these languages.

The catalog of tutorials currently includes the following:

Dig Deeper on Core Java APIs and programming techniques

App Architecture
Software Quality
Cloud Computing
Security
SearchAWS
Close