Scalaのメソッド実行パズル

まずクラスを宣言します:

class Op(var x : Int) {
  def +++(op: Op) = {
    println(this.x + " +++ " + op.x)
    this.x += op.x
    this
  } 
  def ***(op: Op) = {
    println(this.x + " *** " + op.x)
    this.x *= op.x
    this
  }
}

今度はREPLで式を実行します。

op1 +++ op2 +++ op3 *** op4

出力する

enter image description here

しかし、なぜ *** メソッドが先に進まないのでしょうか? *** の優先順位が +++ よりも高いのではないですか? JavaとCについてはどうですか? Scalaと同じですか?

5
なぜ *** の優先順位は +++ よりも高いのですか?漠然として乗算や加算のように見えますから?
追加された 著者 Jesper,
うーん、私はそれがそうだと思う
追加された 著者 爱国者,
いいえ。スカラーのメソッドの優先順位は、メソッド名の最初の文字によって決まります。詳細については、第5章のセクション8の<プログラミングin scala、2nd edition>を参照してください。
追加された 著者 爱国者,

2 答え

op1 +++ op2 +++ op3 *** op4

((op1 +++ op2) +++ (op3 *** op4))

メソッド呼び出しは左結合型であるためです。したがって、最初の(op1 +++ op2)は2番目の +++ の最初のオペランドであるため評価されます。次に、2番目のオペランド(op3 *** op4)が評価されます。最後に、一番外側の演算子が評価されます。

CやJavaの op1 + op2 + op3 * op4 についても同様です。

13
追加された

単純なルール

op1 +++ op2 +++ op3 *** op4 式の評価順序を決定するルールは2つあります。

まず、*で始まる演算子が+で始まる演算子よりも優先されるため、式は次のように変換されます。

op1 +++ op2 +++ (op3 *** op4)

次に、同じ優先順位の複数の演算子が並べて表示されるため(op1 +++ op2 +++ ...)、それらは左から右にグループ化されます。

(op1 +++ op2) +++ (op3 *** op4)

以下の式を考えてみよう。

op1 +++ op2 +++ op3 +++ op4 *** op5

Following the same two 単純なルール it will be evaluated as:

((op1 +++ op2) +++ op3) +++ (op4 *** op5)

Another 例

あるいは、同じ2つのルールを op1 +++ op2 +++ op3 +++ op4 *** op5 *** op6 に適用してみましょう。

*で始まる演算子は、+で始まる演算子よりも優先されます。

op1 +++ op2 +++ op3 +++ (op4 *** op5 *** op6)

次に、左から右へ同じ優先順位で演算子をグループ化します。

((op1 +++ op2) +++ op3) +++ ((op4 *** op5) *** op6)

変更可能なオブジェクト:注意の言葉

+++ メソッドと *** メソッドに副作用がない場合、グループ化は完全な数学的意味を持ちます。検討してください:

op1 +++ op2 +++ op1 *** op2

+++ メソッドと *** メソッドが元のコードサンプルで生成する不都合な副作用オブジェクト内に格納されている値)は、期待される値ではなく12を保持するオブジェクトになります。

そのため、そのような式を作成するときは、不変オブジェクトに専ら依存することが最善です。

case class Op ( x: Int) {
  def +++(that: Op) = {
    println(this.x + " +++ " + that.x)
    Op(this.x+that.x)
  } 
  def ***(that: Op) = {
    println(this.x + " *** " + that.x)
    Op(this.x * that.x)
  }  
}

Op(5)の式は、 Op(1)+++ Op(2)+++ Op(1)*** Op(2)期待される。

5
追加された