Sunday, January 23, 2011

Predicate Method for Yes/No: The David Version

After I posted my predicate method for categorizing yes/no questions as true or false, David challenged me to rewrite the solution with a single call to readLine(prompt) and a single test for reply.equals("yes").

Here's my shot at it (tested and it works, oorah):

/*

    private boolean askYesOrNoQ(String prompt){   
        while (true) {
            String reply = readLine(prompt);
         
            if (reply.equals("yes")) {
                return true;
            }
            if (reply.equals("no")) {
                return false;
            }
            else
            println("Please enter a yes or no answer.");
        }
        
    }


The old approach said, "As long as the user enters a non-yes/no answer, keep prompting him to enter yes or no; once he does, return true or false, respectively." This version says, "Keep looping. If he enters yes, break from the loop and return true. If he enters no, break from the loop and return false. Else, keep re-prompting and looping."

I don't know if this was the strategy David was thinking of, but I'm glad I figured out how to solve a problem two ways. Comparing this method with the old version, I'm trying to figure out which one is better and why.

For reference, here is the old version:

/*

private boolean askYesOrNoQ(String prompt){ 
        String reply = readLine(prompt);
      
        while ((!reply.equals("yes"))&&(!reply.equals("no"))) {
            println("Please enter a yes or no answer.");
            reply = readLine(prompt);
        }
        return (reply.equals("yes"));
    }
}



Merits of the new version:

1) Clearer to read; you don't really need to know the syntax of Java or how booleans work to know what's going on.

2) Doesn't repeat the line "reply = readLine(prompt)". In general it's a good practice to avoid repeating code so you don't introduce bugs if you decide to change the name of the variable "reply", etc.

Merits of the old version:

1) Fewer lines of code.

2) I like the clean and elegant "return" statement. Instead of breaking down the true or false possibilities into two "if" statements, we say return(boolean); it lets the program figure out true vs false for itself. I guess you could write, "If reply equals yes or no, return(boolean)", though that would violate the challenge of only inspecting reply.equals("yes") only once.

What do you guys think? Also are there other ways of solving this problem?

4 comments:

  1. Renee is the best! Yay yay yay Renee!

    ReplyDelete
  2. A sketch of an alternative:

    switch(readLine(prompt)) {
    case "yes": return true;
    case "no": return false;
    default: printLn("Please enter a yes or no answer.");
    }

    ReplyDelete
  3. You could also change the second if statement to an else so that you don't have to always check for "no" in the first example. As it stood, you were checking for "no" every time, even when you may have already realized the answer was yes in the first if statement. It is one of the reasons why the second one is a bit cleaner (this is how the && operator works).

    I wouldn't recommend doing too many "while(true)" statements, as it can open you up to problems if there is a condition that never breaks the loop. I tend to leave control for these things in another method to avoid having too many of these issues. For example, if you wanted to change this so that after the 5th attempt you make the person do something else, it would be good to have that logic outside of the method that asks a yes or no Q.

    Just my view. Its awesome that you put code out there. Are you on Forrst? Thats basically what that community is for.

    ReplyDelete
  4. Here is my solution;

    private boolean askYesNoQuestion(String answer){
    while (true){
    if (answer.equals("yes") || answer.equals("no")) break;
    answer = readLine("Please answer \"yes\" or \"no\": ");
    }
    return answer.equals("yes");
    }

    ReplyDelete