Scala Named and Default Arguments: A Sticky Situation

I love named and default arguments. I’ve been using them for years in ColdFusion and find them quite useful. It is a wonder more languages don’t support them. Scala 2.8 has both as new features. Here is an example of the usage.

class Person(
  var firstName: String = "Dustin",
  var lastName: String = "Martin"
)

// Use named arguments
val person = new Person(
  firstName = "John",
  lastName = "Doe"
)

// Or use the default arguments
val person = new Person

// Or mix and match the two - lastName uses the default of "Martin"
val person = new Person(
  firstName = "John"
)

As you can see this is a very simple class with two properties. I’m very fond of these new features and both can serve to simplify your code.

But not all is well when using named arguments. Lets say you have a class and start off using names arguments for the constructor.

// Use named arguments
val person = new Person(
  firstName = "John",
  lastName = "Doe"
)

No problems yet. But lets say you need to add a custom method for firstName to return “foo” instead of the actual firstName

class Person(
  var firstName: String = "Dustin",
  var lastName: String = "Martin" ){

  def firstName = "foo"
}

val person = new Person(
  firstName ="John",
  lastName = "Doe"
)

As soon as you run this you find the compiler throwing an error. The problem is that variables and methods share the same namespace. In other words, methods and variables can’t share the same name. Consequently, if a custom method is needed, the variable – in this case firstName – must be renamed. This poses a problem if you have already started using named arguments.

// The above would need to be...
class Person(
  var _firstName: String = "Dustin",
  var lastName: String = "Martin"){

  def firstName = "foo"

}

val person = new Person(
  firstName = "John",
  lastName = "Doe"
)

But this still will not work either. The problem is that when the person object is instantiated, the argument firstName is referenced. It no longer exists though. Only _firstName exists. So to fix this we are stuck renaming firstName to _firstName every time a new person object is created. But that seems like a poor solution. We don’t want to have to change all of our code every time we need to update a class.

So what is the solution to the problem? I’m not sure. Always prefixing variables with underscores or some other character? Not using named arguments? Something else? Right now I’m inclined to simply not use named arguments – at least not for constructor arguments. That way I can change firstName to _firstName and create my custom method without having to update my code. But it would certainly be nice if named arguments could be used in constructors without having to worry about this. Perhaps there is another solution that I’m not aware of. Seeing as how Scala is still a fairly new language, and version 2.8 hasn’t even been officially released, a lot of best practices have yet to be established. It will be interesting to see how the Scala community decides to handle this sticky situation.