В чем разница между def foo = {} и def foo() = {} в Scala?

Учитывая следующие конструкции для определения функции в Scala, можете ли вы объяснить, в чем состоит разница, и каковы будут последствия?

def foo = {}

против.

def foo() = {}

Update

Спасибо за быстрые ответы. Это здорово. Единственный вопрос, который остается для меня:

Если я опускаю скобку, есть ли способ передать функцию вокруг? Это то, что я получаю в repl:

scala> def foo = {}
foo: Unit

scala> def baz() = {}
baz: ()Unit

scala> def test(arg: () => Unit) = { arg }
test: (arg: () => Unit)() => Unit

scala> test(foo)
<console>:10: error: type mismatch;
 found   : Unit
 required: () => Unit
              test(foo)
                   ^

scala> test(baz)
res1: () => Unit = <function0>

Обновление 2012-09-14

Вот некоторые похожие вопросы, которые я заметил:

Ответ 1

Если вы включаете круглые скобки в определение, вы можете опционально опустить их при вызове метода. Если вы опустите их в определении, вы не сможете использовать их при вызове метода.

scala> def foo() {}
foo: ()Unit

scala> def bar {}
bar: Unit

scala> foo

scala> bar()
<console>:12: error: Unit does not take parameters
       bar()
          ^

Кроме того, вы можете сделать что-то подобное с функциями более высокого порядка:

scala> def baz(f: () => Unit) {}
baz: (f: () => Unit)Unit

scala> def bat(f: => Unit) {}
bat: (f: => Unit)Unit

scala> baz(foo)    

scala> baz(bar)
<console>:13: error: type mismatch;
 found   : Unit
 required: () => Unit
       baz(bar)
           ^
scala> bat(foo)

scala> bat(bar)  // both ok

Здесь baz будет принимать только foo(), а не bar. Какая польза от этого, я не знаю. Но это показывает, что типы различны.

Ответ 2

Позвольте мне скопировать мой ответ, который я разместил на дублированном вопросе:

A Scala метод 0-арности может быть определен с круглыми скобками или без них (). Это используется, чтобы сигнализировать пользователю о том, что метод имеет какой-то побочный эффект (например, распечатывать или удалять данные), в отличие от того, который отсутствует, который впоследствии может быть реализован как val.

См. Программирование в Scala:

Такие безпараметрические методы довольно распространены в Scala. Напротив, методы, определяемые пустым скобками, например def height(): Int, называются пустыми методами. Рекомендуемое соглашение заключается в использовании безпараметрического метода, когда нет параметров, и метод обращается к изменяемому состоянию только путем чтения полей содержащего объекта (в частности, он не изменяет изменяемое состояние).

Это соглашение поддерживает принцип единого доступа [...]

Подводя итог, рекомендуется, чтобы стиль в Scala определял методы, которые не принимают никаких параметров и не имеют побочных эффектов в качестве безпараметрических методов, т.е. оставляют пустые круглые скобки. С другой стороны, вы никогда не должны определять метод, который имеет побочные эффекты без круглых скобок, потому что тогда вызовы этого метода будут выглядеть как выбор поля.

Ответ 3

Чтобы ответить на второй вопрос, просто добавьте _:

scala> def foo = println("foo!")
foo: Unit

scala> def test(arg: () => Unit) = { arg }
test: (arg: () => Unit)() => Unit

scala> test(foo _)
res10: () => Unit = <function0>

scala> test(foo _)()
foo!

scala>