Подтвердить что ты не робот

Scala "postfix ops"

Я искал полчаса и все еще не могу понять.

В SIP: Модульные функции языка существует ряд функций, которые требуют явного "включения" в Scala 2.10 (import language.feature). Среди них есть postfixOps, к которому я просто не могу найти ссылку нигде. Что именно эта функция позволяет?

4b9b3361

Ответ 1

Он позволяет использовать синтаксис оператора в постфиксной позиции. Например

List(1,2,3) tail

а не

List(1,2,3).tail

В этом безобидном примере это не проблема, но это может привести к двусмысленности. Это не скомпилируется:

val appender:List[Int] => List[Int] = List(1,2,3) ::: //add ; here
List(3,4,5).foreach {println}

И сообщение об ошибке не очень полезно:

    value ::: is not a member of Unit

Он пытается вызвать метод ::: для результата вызова foreach, который имеет тип Unit. Вероятно, это не то, что планировал программист. Чтобы получить правильный результат, вам нужно вставить точку с запятой после первой строки.

Ответ 2

Самый простой ответ:

Удаление точки из методов без параметров DEPRECATED!

List(1,2,3) reverse //is bad style and will lead to unpredicted behaviour
List(1,2,3) map(_*2) reverse //bad too, because reverse can take first method call from the next line (details below)

ОК, чтобы удалить точку в методах, которые принимают один параметр функцию более высокого порядка, такую ​​как карта, фильтр, счетчик и быть в безопасности! Кроме того, чисто функциональные методы, такие как zip.

List(1,2,3) map(_*2) filter(_>2)
(List(1,2,3) map(_*2)).reverse //safe and good
List(1,3,5) zip List(2,4,6)

Длинный ответ ПОЧЕМУ

case class MyBool(x: Boolean) {
  def !!! = MyBool(!x) //postfix
  def or(other: MyBool): MyBool = if(x) other else this //infix
  def justMethod0() = this //method with empty parameters
  def justMethod2(a: MyBool, b: MyBool) = this //method with two or more
  override def toString = if(x) "true" else "false"
}

1) Оператор Postfix - это фактически вызов метода без параметров (a! == a.!) и без скобок. (считается небезопасным и устаревшим)

val b1 = MyBool(false) !!!
List(1,2,3) head

2) Оператор Postfix - это метод, который должен заканчивать строку, иначе он будет обрабатываться как infix.

val b1 = MyBool(true) no! no! //ERROR
//is actually parsed like
val b2 = MyBool(true).no!(no!) //(no!) is unknown identifier
//as bad as
Vector(1,2,3) toList map(_*2) //ERROR

3) Оператор Infix - это метод с одним параметром, который можно вызвать без точек и круглых скобок. Только для чисто функциональных методов

val c1 = MyBool(true) or b1 or MyBool(true)
val c2 = MyBool(true).or(b1).or(MyBool(true))
c1 == c2

4) Метод с одним или несколькими параметрами будет цепляться без точки, если вы вызываете его с параметрами. def a(), def a (x), def a (x, y) Но вы должны сделать это только для методов, которые используют функцию более высокого порядка в качестве параметра!

val d1 = MyBool(true) justMethod2(b1, c1) or b1 justMethod0() justMethod2(c1, b1)
//yes, it works, but it may be confusing idea
val d2 = MyBool(true).justMethod2(b1,c1).or(b1).justMethod0().justMethod2(c1, b1)
d1 == d2
//looks familiar? This is where it should be used:
List(1,2,3) filter(_>1) map(_*2)

Примеры предупреждений:

предупреждение: было 1 предупреждение об отказе; перезапустить с -deprecation для получения дополнительной информации: postfix operator tail должен быть включен, сделав отображается неявное значение scala.language.postfixOps. Это может быть достигнуто добавлением импортной позиции "импорт" scala.language.postfixOps 'или путем установки параметра компилятора -Language: postfixOps. См. Документы Scala для значения scala.language.postfixOps для обсуждения, почему функция должна быть явно включен.

Ответ 3

Он ссылается на способность вызывать нулевой (без списка аргументов или пустой список аргументов) как постфиксный оператор:

Пример:

case class MyBool(value: Boolean) {
    def negated = new MyBool(!value)
}
val b1 = MyBool( true )
val b2 = b1 negated // Same as b1.negated

Смотрите: http://www.scala-lang.org/node/118