Tuesday, 18 September 2012

Puzzle 19: Classy Fire


The following program uses a method to classify characters. What does the program print? In case you are not familiar with the String.indexOf(char) method, it returns the index of the first occurrence of the specified character in the string, or –1 if the string doesn't contain the character:
public class Classifier {

    public static void main(String[] args) {

        System.out.println(

            classify('n') + classify('+') + classify('2'));

    }

    static String classify(char ch) {

        if ("0123456789".indexOf(ch) >= 0)

            return "NUMERAL ";

        if ("abcdefghijklmnopqrstuvwxyz".indexOf(ch) >= 0)

            return "LETTER ";

/* (Operators not supported yet)

        if ("+-*/&|!=".indexOf(ch) >= 0)

            return "OPERATOR ";

 */

        return "UNKNOWN ";

    }

}


Solution 19: Classy Fire

If you guessed that this program prints LETTER UNKNOWN NUMBER, you fell for the trap. The program doesn't even compile. Let's take another look at the relevant section, this time highlighting the block comment in boldface:
        if ("abcdefghijklmnopqrstuvwxyz".indexOf(ch) >= 0)

            return "LETTER ";

/* (Operators not supported yet)

        if ("+-*/&|!=".indexOf(ch) >= 0)

            return "OPERATOR ";

 */

        return "UNKNOWN ";

    }

}


As you can see, the comment ends inside the string, which quite naturally contains the characters */. The resulting program is syntactically invalid. Our attempt to comment out a section of the program failed because string literals are not treated specially within comments.
More generally, the text inside of comments is not treated specially in any way [JLS 3.7]. Therefore, block comments do not nest. Consider the following code snippet:
/* Add the numbers from 1 to n */

int sum = 0;

for (int i = 1; i <= n; i++)

    sum += i;


Now suppose that we try to comment out the snippet with a block comment. Again, we highlight the entire comment in boldface:
/*

    /* Add the numbers from to 1 to n */

    int sum = 0;

    for (int i = 1; i <= n; i++)

        sum += i;

 */


As you can see, we failed to comment out the original snippet. On the bright side, the resulting code contains a syntax error, so the compiler will tell us that we have a problem.
You may occasionally see a section of code that is disabled with an if statement whose boolean expression is the constant false:
// Code commented out with an if statement - doesn't always work!

if (false) {

    /* Add the numbers from 1 to n */

    int sum = 0;

    for (int i = 1; i <= n; i++)

        sum += i;

}


The language specification recommends this as a technique for conditional compilation [JLS 14.21], but it is not well suited to commenting out code. It can't be used unless the code to be disabled is a sequence of valid statements.
The best way to comment out a section of code is to use a sequence of single-line comments. Most IDEs automate this process:
// Code commented out with a sequence of single-line comments

//    /* Add the numbers from 1 to n */

//    int sum = 0;

//    for (int i = 1; i <= n; i++)

//        sum += i;


In summary, a block comment does not reliably comment out a section of code. Use a sequence of single-line comments instead. For language designers, note that nestable block comments are not a good idea. They force the compiler to parse the text inside block comments, which causes more problems than it solves.

No comments:

Post a Comment

Your comments are welcome!