1. ホーム
  2. syntax

[解決済み] 括弧、ドット、中括弧、=(関数)などを省略できる場合の正確なルールを教えてください。

2022-10-24 03:03:29

質問

括弧、ドット、中括弧、=(関数)などを省略(オミット)できる場合の正確なルールを教えてください。

例えば

(service.findAllPresentations.get.first.votes.size) must be equalTo(2).

  • service は私のオブジェクトです
  • def findAllPresentations: Option[List[Presentation]]
  • votes リターン List[Vote]
  • 必須 そして である はどちらもspecの関数

なぜ行けないのか。

(service findAllPresentations get first votes size) must be equalTo(2)

?

コンパイラのエラーは

"RestServicesSpecTest.this.service.findAllPresentationsの場合 タイプの Option[List[com.sharca.Presentation]] を使用します。 はパラメータを取りません"。

なぜパラメータを渡そうとしていると思われるのでしょうか?なぜすべてのメソッド呼び出しにドットを使用しなければならないのですか?

なぜ (service.findAllPresentations get first votes size) be equalTo(2) result in:

"見つかりません: 値が先です"

それでも、"must be equalTo 2"の (service.findAllPresentations.get.first.votes.size) はmust be equalTo 2、つまりメソッドチェイニングは問題なく動作するのでしょうか?- オブジェクトチェインチェインパラメータです。

Scalaの本やウェブサイトに目を通しましたが、包括的な説明を見つけることができません。

実際は、Stack Overflowの質問でRob Hが説明しているように Scalaではどの文字を省略することができますか? を省略できるのは、quot;operand operator operand"形式の操作だけで、メソッドチェイニングには使えないということですね?

どのように解決するのですか?

クラスの定義です。

val または var はクラスパラメータから省略することができ、これによりパラメータはプライベートになります。

varやvalをつけるとpublicになります(つまり、メソッドアクセサやミューテータが生成されます)。

{} は、クラスにボディがない場合は省略できる、ということです。

class EmptyClass


クラスのインスタンス化。

一般的なパラメータは、コンパイラが推測できる場合は省略することができます。しかし、型が一致しない場合、型パラメータは常に一致するように推論されることに注意してください。そのため、型を指定しないと、期待通りのものが得られないかもしれません - つまり、与えられた

class D[T](val x:T, val y:T);

これはタイプエラーになります (Intが見つかり、Stringが予想される)

var zz = new D[String]("Hi1", 1) // type error

一方、これはうまく動作します。

var z = new D("Hi1", 1)
== D{def x: Any; def y: Any}

なぜなら、型パラメータであるTは、2つのうち最も共通性の低いスーパータイプであるAnyとして推論されるからです。


関数の定義です。

= は、関数がUnit(何もない)を返す場合、削除することができます。

{} は、関数が単一のステートメントである場合は削除することができますが、ステートメントが値を返す場合のみ、関数本体に対する = の記号が必要)、つまり

def returnAString = "Hi!"

とありますが、これではうまくいきません。

def returnAString "Hi!" // Compile error - '=' expected but string literal found."

関数の戻り値の型は、推測できる場合は省略可能です(再帰的なメソッドは戻り値の型を指定する必要があります)。

() は、関数が引数を取らない場合は、省略することができます。

def endOfString {
  return "myDog".substring(2,1)
}

は、慣習的に副作用のないメソッドのために予約されています - これについては後で説明します。

() を定義するとき、実際にはそれ自体が削除されるわけではありません。 という名前で渡すことができます。 というパラメータがありますが、実は意味的にかなり違う表記になっている、ということです。

def myOp(passByNameString: => String)

myOp は関数パラメータとは対照的に、結果的に String (つまり、文字列を返すコードブロック) となる pass-by-name パラメータを取ると述べています。

def myOp(functionParam: () => String)

というのは myOp は、0個のパラメータを持つ関数を受け取り、文字列を返します。

(注意: 名前で渡すパラメータは関数にコンパイルされます; それは単に構文をより良くするだけです)。

() は、例えば関数が1つの引数しか取らない場合、関数のパラメータ定義で削除することができます。

def myOp2(passByNameString:(Int) => String) { .. } // - You can drop the ()
def myOp2(passByNameString:Int => String) { .. }

ただし、複数の引数を取る場合は、()を入れる必要があります。

def myOp2(passByNameString:(Int, String) => String) { .. }


ステートメント

. を落とすと、演算子表記を使うことができます。 だけ は infix 演算子 (引数を取るメソッドの演算子) に使用されます。参照 ダニエルの回答 を参照してください。

  • . は、postfixの関数に対しても削除することができます。 リストテール

  • () は、postfixオペレータのために削除することができます。 リスト.tail

  • () と定義されたメソッドでは使用できません。

    def aMethod = "hi!" // Missing () on method definition
    aMethod // Works
    aMethod() // Compile error when calling method
    
    

なぜなら、この表記はList#tailのような副作用のないメソッドのために慣習的に予約されているからです(つまり、副作用のない関数の呼び出しは、その戻り値以外、観察可能な効果がないことを意味します)。

  • () は、単一の引数を渡す場合、演算子記法のために削除することができます。

  • () は、文の末尾にない後置演算子を使用する必要がある場合があります。

  • () は、ネストされたステートメント、無名関数の末尾、または複数のパラメータを取る演算子を指定するために必要となる場合があります。

関数を受け取る関数を呼び出すとき、例えば内部の関数定義から()を省略することはできません。

def myOp3(paramFunc0:() => String) {
    println(paramFunc0)
}
myOp3(() => "myop3") // Works
myOp3(=> "myop3") // Doesn't work

バイネーム引数を取る関数を呼び出す場合、引数をパラメータなしの無名関数として指定することはできません。例えば、与えられた

def myOp2(passByNameString:Int => String) {
  println(passByNameString)
}

として呼び出す必要があります。

myOp("myop3")

または

myOp({
  val source = sourceProvider.source
  val p = myObject.findNameFromSource(source)
  p
})

が、そうではない。

myOp(() => "myop3") // Doesn't work

IMOでは、ドロップリターン型の多用は、再利用されるコードにとって有害である可能性があります。コードに明示的な情報がないために可読性が低下している良い例として、仕様書を見ればわかるでしょう。変数の型が何であるかを実際に把握するために、何段階ものインダイレクトが必要になることがあります。より良いツールがこの問題を回避し、私たちのコードを簡潔に保つことができればよいのですが。

(OK, より完全で簡潔な回答をコンパイルするために (私が何かを見逃していたり、何か間違っていたり不正確だったりしたら、コメントをお願いします)、回答の冒頭に追加しています。これは言語仕様ではないので、正確に学問的に正しいものにしようとはしていません - ただ、リファレンスカードのようなものです)。