Thursday, May 1, 2008

Enum parameters

This is something that I've wanted for many, many years. (Warning: coding post.) It's considered good coding practice to not use boolean flags as parameters to functions, but rather to use enumerated types, so that things are extensible in the future by adding new items to the enumeration rather than yet another flag parameter, and so that the calling code is more explicitly readable. In concept it's usually good advice (though there are times that what you want really is a set of boolean flags), but generally I avoid using it in practice because I dislike the way that it makes the code look.

person = FindPerson(name, false)
person = FindPerson(name, PersonFindOptions.CaseInsensitive)

The latter is clearer since it's explicitly case-insensitive rather than having to wonder whether that second parameter means "is case sensitive" or "is case insensitive," but it puts too much visual emphasis on the unimportant part of the function call—the case-insensitive flag. It's important to me that as much as possible of the textual content of a line of code be meaningful. What I'd like to see is this:

person = FindPerson(name, Insensitive)

That's so clear and nice-looking! In version 2, when you want to specify a second option, it's still simple and clear:

person = FindPerson(name, Insensitive RefreshCache)

(It's not as essential that whitespace become synonymous with the logical or operator in this context, but it seems like a nice bonus, since what you want is both option 1 AND option 2, but what you have to type to get that is "option 1 Or option 2", which looks especially dumb if your language uses the word "or" and not a symbol, like Basic.)

Specifically what I want from my language is that if the compiler knows that what I'm about to type is a value from an enumeration (parameters, variable assignments, et cetera), the name of the enumeration becomes optional. This doesn't work in C++ without some language extensions, but it could easily be made to work in VB or C# or most any other modern language (except ones that don't have enums, like older versions of Java). The chances of conflicts between existing names and enumeration values seem like they would be low in practice (especially in a case-sensitive language), but local variable names should win out if they do. That way, if you add a new item to your enumeration that matches a variable name used in a function anywhere, you don't change the meaning of the existing code.

No comments: