Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Scala toString: parenthesize or not?

Tags:

I'd like this thread to be some kind of summary of pros/cons for overriding and calling toString with or without empty parentheses, because this thing still confuses me sometimes, even though I've been into Scala for quite a while.

So which one is preferable over another? Comments from Scala geeks, officials and OCD paranoids are highly appreciated.

Pros to toString:

  • seems to be an obvious and natural choice at the first glance;
  • most cases are trivial and just construct Strings on the fly without ever modifying internal state;
  • another common case is to delegate method call to the wrapped abstraction:

    override def toString = underlying.toString 

Pros to toString():

  • definitely not "accessor-like" name (that's how IntelliJ IDEA inspector complains every once in a while);
  • might imply some CPU or I/O work (in cases where counting every System.arrayCopy call is crucial to performance);
  • even might imply some mutable state changing (consider an example when first toString call is expensive, so it is cached internally to yield quicker calls in future).

So what's the best practice? Am I still missing something?

Update: this question is related specifically to toString which is defined on every JVM object, so I was hoping to find the best practice, if it ever exists.

like image 854
BorisOkunskiy Avatar asked Nov 14 '11 15:11

BorisOkunskiy


2 Answers

Here's what Programming In Scala (section 10.3) has to say:

The recommended convention is to use a parameterless method whenever there are no parameters and the method accesses mutable state only by reading fields of the containing object (in particular, it does not change mutable state). This convention supports the uniform access principle,1 which says that client code should not be affected by a decision to implement an attribute as a field or method.

Here's what the (unofficial) Scala Style Guide (page 18) has to say:

Scala allows the omission of parentheses on methods of arity-0 (no arguments):

reply()  // is the same as  reply  

However, this syntax should only be used when the method in question has no side-effects (purely-functional). In other words, it would be acceptable to omit parentheses when calling queue.size, but not when calling println(). This convention mirrors the method declaration convention given above.

The latter does not mention the Uniform Access Principle.

If your toString method can be implemented as a val, it implies the field is immutable. If, however, your class is mutable, toString might not always yield the same result (e.g. for StringBuffer). So Programming In Scala implies that we should use toString() in two different situations:

1) When its value is mutable

2) When there are side-effects

Personally I think it's more common and more consistent to ignore the first of these. In practice toString will almost never have side-effects. So (unless it does), always use toString and ignore the Uniform Access Principle (following the Style Guide): keep parentheses to denote side-effects, rather than mutability.

like image 196
Luigi Plinge Avatar answered Sep 23 '22 05:09

Luigi Plinge


Yes, you are missing something: Semantics.

If you have a method that simply gives back a value, you shouldn't use parens. The reason is that this blurs the line between vals and defs, satisfying the Uniform Access Principle. E.g. consider the size method for collections. For fixed-sized vectors or arrays this can be just a val, other collections may need to calculate it.

The usage of empty parens should be limited to methods which perform some kind of side effect, e.g. println(), or a method that increases an internal counter, or a method that resets a connection etc.

like image 36
Landei Avatar answered Sep 19 '22 05:09

Landei