Skip to content

rewrite style guide entry on foo vs foo() #3053

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 2 commits into from
Aug 14, 2024
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
58 changes: 25 additions & 33 deletions _style/naming-conventions.md
Original file line number Diff line number Diff line change
Expand Up @@ -195,44 +195,36 @@ getter and setter. For example:

### Parentheses

Unlike Ruby, Scala attaches significance to whether or not a method is
*declared* with parentheses (only applicable to methods of
[arity](https://en.wikipedia.org/wiki/Arity)-0). For example:
Scala allows a parameterless, zero-[arity](https://en.wikipedia.org/wiki/Arity)
method to be declared with an empty parameter list:

def foo1() = ...

or with no parameter lists at all:

def foo2 = ...

These are different methods at compile-time. While `foo1` can be called
with or without the parentheses, `foo2` *may not* be called *with*
parentheses.

Thus, it is actually quite important that proper guidelines be observed
regarding when it is appropriate to declare a method without parentheses
and when it is not.

Methods which act as accessors of any sort (either encapsulating a field
or a logical property) should be declared *without* parentheses except
if they have side effects. While Ruby and Lift use a `!` to indicate
this, the usage of parens is preferred (please note that fluid APIs and
internal domain-specific languages have a tendency to break the
guidelines given below for the sake of syntax. Such exceptions should
not be considered a violation so much as a time when these rules do not
apply. In a DSL, syntax should be paramount over convention).

Further, the callsite should follow the declaration; if declared with
parentheses, call with parentheses. While there is temptation to save a
few characters, if you follow this guideline, your code will be *much*
more readable and maintainable.

// doesn't change state, call as birthdate
def birthdate = firstName

// updates our internal state, call as age()
def age() = {
_age = updateAge(birthdate)
_age
}
By convention, parentheses are used to indicate that a method has
side effects, such as altering the receiver.

On the other hand, the absence of parentheses indicates that a
method is like an accessor: it returns a value without altering the
receiver, and on the same receiver in the same state, it always
returns the same answer.

The callsite should follow the declaration; if declared with
parentheses, call with parentheses.

These conventions are followed in the Scala standard library and
you should follow them in your own code as well.

Additional notes:

* Scala 3 errors if you leave out the parentheses at the call site. Scala 2 merely warns.
* Scala 3 and 2 both error if the call site has parentheses where the definition doesn't.
* Java-defined methods are exempt from this distinction and may be called either way.
* If a method _does_ take parameters, there isn't any convention for indicating whether it also has side effects.
* Creating an object isn't considered a side effect. So for example, Scala collections have an `iterator` method with no parens. Yes, you get a new iterator each time. And yes, iterators are mutable. But every fresh iterator is the same until it has been altered by calling a side-effecting method such as `Iterator#next()`, which _is_ declared with parentheses. See this [2018 design discussion](https://github.com/scala/collection-strawman/issues/520).

### Symbolic Method Names

Expand Down