web-dev-qa-db-ja.com

Scalaの「後置演算子」

私は30分間検索しましたが、まだわかりません。

SIP:Modularizing Language Features には、Scala 2.10(import language.feature)。それらの中にはpostfixOpsがありますが、どこにも参照が見つかりません。この機能では何が許可されますか?

55
dmitry

これにより、後置位置で演算子構文を使用できます。例えば

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

タイプforeachUnit呼び出しの結果に対して:::メソッドを呼び出そうとします。これはおそらくプログラマーが意図したものではありません。正しい結果を得るには、最初の行の後にセミコロンを挿入する必要があります。

58
Kim Stebel

これまでで最も単純な答え:

パラメータなしのメソッドからドットを削除することは [〜#〜] 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)

高次関数 map、filter、countなどのパラメーターを1つ取るメソッドにドットをドロップしても問題ありません!また、 純粋に機能する 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)

ロングアンサーWHY

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)後置演算子-実際にはパラメーターなし(a!== a。!)で角括弧なしのメソッド呼び出しです。 (安全ではないと考えられ、非推奨)

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

2)Postfix演算子はメソッドであり、行を終了する必要があります。そうでなければ、中置として扱われます。

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)中置演算子は、1つのパラメーターを持つメソッドであり、ドットと括弧なしで呼び出すことができます。 純粋に機能する メソッドのみ

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

4)パラメーターを指定して呼び出すと、1つ以上のパラメーターを指定したメソッドがドットなしで連鎖します。 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を指定して再実行します。暗黙的な値scala.language.postfixOpsを表示することにより、後置演算子の末尾を有効にする必要があります。これは、import句 'import scala.language.postfixOps'を追加するか、コンパイラオプション-language:postfixOpsを設定することで実現できます。この機能を明示的に有効にする必要がある理由については、Scalaの値scala.language.postfixOpsのドキュメントを参照してください。

30
Alex

これは、後置演算子としてヌル引数(引数リストなしまたは空の引数リスト付き)メソッドを呼び出す機能を指します。

例:

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

5