55

Scalaで関数を定義するための次の構成を前提として、違いは何であり、その意味は何であるかを説明できますか?

def foo = {}

対。

def foo() = {}

アップデート

迅速な対応に感謝します。これらは素晴らしいです。私に残っている唯一の質問は:

括弧を省略しても、関数を渡す方法はありますか?これは私がreplで取得するものです:

scala> def foo = {}
foo: Unit

scala> def baz() = {}
baz: ()Unit

scala> def test(arg: () => Unit) = { arg }
test: (arg: () => Unit)() => Unit

scala> test(foo)
<console>:10: error: type mismatch;
 found   : Unit
 required: () => Unit
              test(foo)
                   ^

scala> test(baz)
res1: () => Unit = <function0>

更新2012-09-14

これが私が気づいたいくつかの同様の質問です:

  1. 括弧付きと括弧なしの機能の違い
  2. 引数のないScalaメソッド
4

4 に答える 4

40

重複した質問に投稿した回答をコピーさせてください:

アリティが 0 の Scala 2.x メソッドは、括弧の有無にかかわらず定義できます()。これは、後でval.

Scala でのプログラミングを参照してください。

このようなパラメーターなしのメソッドは、Scala では非常に一般的です。対照的に、def height(): Int などの空の括弧で定義されたメソッドは、空括弧メソッドと呼ばれます。推奨される規則は、パラメーターがなく、メソッドが包含オブジェクトのフィールドを読み取ることによってのみ可変状態にアクセスする場合は常にパラメーターなしのメソッドを使用することです (特に、可変状態を変更しません)。

この規則は、均一アクセスの原則をサポートしています [...]

要約すると、Scala のスタイルでは、パラメーターをとらず、パラメーターなしのメソッドとして副作用のないメソッドを定義することが推奨されます。つまり、空の括弧を省略します。一方、括弧なしで副作用を持つメソッドを定義するべきではありません。そのメソッドの呼び出しがフィールド選択のように見えるからです。

用語

アリティが 0 のメソッドには紛らわしい用語がいくつかあるため、ここに表を作成します。

Scala でのプログラミング スカラ/スカラ専門用語
def foo: Int パラメーターなしのメソッド ゼロ法
def foo(): Int 空括弧メソッド ニラリー法

「nullary メソッド」と言うのはクールに聞こえますが、多くの人はそれを間違って言い、読者も混乱するでしょう。そのため、人々がすでに専門用語。

() は Scala 2.13 または 3.0 ではオプションではなくなりました

The great () insertで、Martin Odersky は Scala 3 に変更を加え、 で定義されたメソッドを呼び出す必要がありまし()()。これは、Scala 3 移行ガイドに次のように記載されています。

自動適用は、空の引数リストを渡さずに nullary メソッドを呼び出す構文です。

: 移行ドキュメントでは用語が間違っています。次のように読む必要があります。

自動適用は、空の引数リストを渡さずに空の括弧 (または「ニラリー」) メソッドを呼び出す構文です。

Scala 2.13 は Scala 3.x に続き、予想される型が Function0 の場合、Eta-expand 0-arity メソッドでの empty-paren メソッドの自動適用を非推奨にしました。この規則の注目すべき例外は、Java 定義のメソッドです。toStringwithoutなどの Java メソッドを引き続き呼び出すことができます()

于 2011-09-30T05:16:13.697 に答える
40

定義に括弧を含めると、メソッドを呼び出すときに必要に応じて省略できます。定義でそれらを省略すると、メソッドを呼び出すときにそれらを使用できません。

scala> def foo() {}
foo: ()Unit

scala> def bar {}
bar: Unit

scala> foo

scala> bar()
<console>:12: error: Unit does not take parameters
       bar()
          ^

さらに、高階関数で同様のことを行うことができます。

scala> def baz(f: () => Unit) {}
baz: (f: () => Unit)Unit

scala> def bat(f: => Unit) {}
bat: (f: => Unit)Unit

scala> baz(foo)    

scala> baz(bar)
<console>:13: error: type mismatch;
 found   : Unit
 required: () => Unit
       baz(bar)
           ^
scala> bat(foo)

scala> bat(bar)  // both ok

ここでbazは取るだけで、ではfoo()ありませんbar。これが何の役に立つのか、私にはわかりません。しかし、それはタイプが異なることを示しています。

于 2011-09-13T23:15:26.193 に答える
7

2 番目の質問に答えるには、次を追加し_ます。

scala> def foo = println("foo!")
foo: Unit

scala> def test(arg: () => Unit) = { arg }
test: (arg: () => Unit)() => Unit

scala> test(foo _)
res10: () => Unit = <function0>

scala> test(foo _)()
foo!

scala>            
于 2015-11-13T20:13:38.850 に答える