Какое правило для круглых скобок при вызове метода Scala?

Разве не ToList метод, который преобразует что-то в список?

Если да, то почему я не могу использовать скобки с ним? Я должен упустить что-то более фундаментальное здесь.

Вот пример:

val l = Array(1,2,3).toList // works fine

val l = Array(1,2,3).toList() // gives the error below

Применяется недостаточно аргументов для метода: (n: Int)Int в признаке LinearSeqOptimized. Не указано значение параметра n.

4 ответа

Решение

Если метод определен как

def toList = { /* something */ }

тогда оно должно называться

object.toList

без лишних скобок. Мы говорим, что этот метод имеет нулевые списки параметров.

Мы могли бы также определить список параметров, но ничего не помещать в него:

def toList() = { /* something */ }

Теперь мы можем позвонить любому из

object.toList()
object.toList

так как Scala позволяет ярлык опускать скобки при вызове метода.

Что касается JVM, то нет разницы между первым определением ("списки нулевых параметров") и вторым ("один пустой список параметров"). Но Скала проводит различие. Является ли это хорошая идея или нет, это вопрос спорный, но мотивация может быть яснее, когда вы понимаете, что мы можем также

def toList()() = { /* something */ }

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

object.toList()()
object.toList()
object.toList

и теперь, если бы мы преобразовали это в функцию, мы бы напечатали это как

() => () => T   /* T is the return value of the something */

в то время как второе определение будет

() => T

который явно отличается концептуально, даже если практически вы используете его таким же образом (ничего не вкладывать и рано или поздно вытащить T).

Тем не мение, toList не требует каких-либо параметров, и стандарт Scala состоит в том, чтобы исключать паренсы, если только метод не изменяет сам объект (а не просто возвращает что-то), поэтому def toList без всяких парней потом. И, таким образом, вы можете назвать это только как object.toList,

Ваша вторая строка фактически интерпретируется как

val l = Array(1,2,3).toList.apply()

поскольку foo(x) такое "волшебный" синтаксис для foo.apply(x),

Вот почему компилятор жалуется на "недостаточно аргументов", поскольку метод apply для списков принимает один аргумент.

Таким образом, вы можете написать, например:

scala> val i = Array(1, 2, 3).toList(1)
i: Int = 2

Позвольте мне ответить с точки зрения стиля Scala.

Руководство по стилю Scala говорит...

Опускайте пустые скобки, используйте только тогда, когда у рассматриваемого метода нет побочных эффектов (чисто функциональный). Другими словами, было бы приемлемо опустить круглые скобки при вызове queue.size, но не при вызове println().

Религиозное соблюдение этого соглашения значительно улучшит читабельность кода и значительно упростит понимание самой основной операции любого данного метода. Не поддавайтесь искушению опустить скобки, просто чтобы сохранить два символа!

11 лет спустя... ИсключениеNot enough arguments for method apply: (n: Int)Int in trait LinearSeqOptimizedсообщение дает вам подсказку. Проверка документов для LinearSeqOps.html#apply(n:Int):A:

def apply(n: Int): AПолучить элемент по указанному индексу.

The toListвArray не принимает никаких аргументов [см. Array:toList docs] и преобразует его вl: List[Int], который являетсяLinearSeqOpsчерта:

      val l = Array(1,2,3).toList        // l: List[Int] = List(1, 2, 3)

Есть много способов позвонитьapply(0)в спискеlчтобы получить элемент по индексу0. Все они делают одно и то же :

      var el1 = l.apply(0)               // el1: Int = 1
el1 = l(0)                         // el1: Int = 1
el1 = Array(1,2,3).toList.apply(0) // el1: Int = 1
el1 = Array(1,2,3).toList(0)       // el1: Int = 1

Но если мы не обеспечимIntаргументapply(n: Int), код завершится ошибкой. Одни и те же варианты будут давать одну и ту же ошибку :

      el1 = Array(1,2,3).toList()        // not enough arguments for method apply: (n: Int)
el1 = Array(1,2,3).toList.apply()  // not enough arguments for method apply: (n: Int)
el1 = l.apply()                    // not enough arguments for method apply: (n: Int)
el1 = l()                          // not enough arguments for method apply: (n: Int)
Другие вопросы по тегам