Scala - синтаксис вызова метода

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

1 to 10

но некоторые действительно меня озадачат. например:

breakable { ... }

Это просто вызов метода? Могу ли я также сделать это для нескольких параметров или параметра, который не является параметром без параметров?

Спасибо

Ответ 1

Существует два стандартных способа вызова методов:

obj.method(params)   // dot notation
obj method (params)  // operator notation

Вышеуказанное может быть изменено следующими способами:

  • Если params - единственный параметр, вы можете заменить () на {}.
  • Если params - это единственный параметр, и вы используете обозначение оператора, вы можете отбросить скобки.
  • Если method не принимает параметры, вы можете отказаться от (params) (т.е. удалить пустой ()).
  • Если method заканчивается на :, то он фактически привязывается к правой части в обозначении оператора. То есть (params) method_: obj эквивалентно obj.method_:(params).
  • В любом случае, пробелы являются необязательными, если идентификаторы можно разделить друг с другом. Таким образом, можно добавить пробелы в точечную нотацию, например, obj . method ( params ) или написать .method(params) на следующей строке - как это часто бывает с цепочкой вызовов, - а также удалить пробелы из операторной нотации, как в a+b.

Там также есть материал с кортежем, но я стараюсь избегать его, поэтому я не уверен в правильности правил.

Ничего из этого не объяснит, например, ваш пример. Однако, прежде чем я объясню это, я хотел бы показать некоторые синтаксические сахара, которые также могут быть использованы для вызова методов:

obj(params) // equivalent to obj.apply(params)
obj.x = y   // equivalent to obj.x_=(y), if obj.x also exists
obj(x) = y  // equivalent to obj.update(x, y)
obj op= y   // equivalent to obj = obj op y, if op is symbolic
~obj        // equivalent to obj.unary_~; also for !, + and -, but no other symbol

Хорошо, теперь к примеру, который вы дали. Можно импортировать элементы стабильных значений. Java может сделать это для статических методов со статическим импортом, но Scala имеет более общий механизм: импорт из пакетов, объектов или общих экземпляров ничем не отличается: он включает как членов типа, так и членов значения. Методы относятся к последней категории.

Итак, представьте, что у вас есть val a = 2, и вы делаете import a._. Это позволит охватить все методы Int, поэтому вы можете их напрямую вызвать. Вы не можете сделать +(2), потому что это будет интерпретироваться как вызов unary_+, но вы можете вызвать *(4), например:

scala> val a = 2
a: Int = 2

scala> import a._
import a._

scala> *(4)
res16: Int = 8

Теперь, вот правило. Вы можете позвонить

method(params)

Если:

  • method был импортирован в область видимости.
  • Вы сохраняете скобки (даже если есть только один параметр)

Обратите внимание, что есть проблема с приоритетом. Если вы пишете obj method(params), Scala предположим, что method принадлежит obj, даже если он был импортирован в область видимости.

Ответ 2

Если мы отбросим это, мы получим:

breakable({ ... }) 

это соответствует сигнатуре

breakable: (op: ⇒ Unit): Unit 

и использует так называемые аргументы call-by-name (вы можете подумать об этом как передать блок кода в качестве аргумента)

Более scala позволяет вам написать следующее:

scala> def foo (op1: => Unit)(op2: => Unit) = {op1;op2;}
foo: (op1: => Unit)(op2: => Unit)Unit

scala> foo { println(1) } { println(2) }
1
2

Выше приведен пример работы с картой