これらの質問のそれぞれは、このサイトの他の場所で回答されていますが、私はそれらをすべて一緒に扱うものはないと思います。それで:
中括弧と等しい
等号で定義されたメソッドは、値を返します(最後に評価されたものは何でも)。中括弧のみで定義されたメソッドはを返しUnit
ます。等しいを使用するが、最後のものがに評価されるUnit
場合、違いはありません。等号の後の単一のステートメントの場合、中括弧は必要ありません。これはバイトコードに違いはありません。したがって、1。、2。、および5.はすべて本質的に同一です。
def f1(s: String) = { println(s) } // println returns `Unit`
def f2(s: String) { println(s) } // `Unit` return again
def f5(s: String) = println(s) // Don't need braces; there's only one statement
関数とメソッド
多くの場合、と書かれる関数は、クラスA => B
の1つのサブクラスです。このクラスにはメソッドがあり、メソッド名なしでparensを使用すると、Scalaが魔法のように呼び出すため、メソッド呼び出しのように見えます。ただし、そのオブジェクトに対する呼び出しである点が異なります。だからあなたが書くならFunction
Function1[A,B]
apply
Function
def f3 = (s: String) => println(s)
次に、あなたが言っているのは、「のようなメソッドを持つf3
インスタンスを作成する必要がある」ということです。つまり、と言うと、これは最初に関数オブジェクトを作成するための呼び出しであり、次にメソッドを呼び出します。Function1[String,Unit]
apply
def apply(s: String) = println(s)
f3("Hi")
f3
apply
関数オブジェクトを使用するたびに作成するのはかなり無駄なので、関数オブジェクトを変数に格納する方が理にかなっています。
val f4 = (s: String) => println(s)
これは、(メソッド)が返すのと同じ関数オブジェクトのインスタンスを1つ保持するdef
ため、毎回再作成する必要はありません。
いつ何を使うか
: Unit = ...
との慣習は人によって異なります{ }
。個人的にはUnit
、等号なしで返されるすべてのメソッドを記述します。これは、何らかの副作用(変数の変更、IOの実行など)がない限り、メソッドがほぼ確実に役に立たないことを示しています。また、私は通常、複数のステートメントがあるか、単一のステートメントが非常に複雑であるため、必要な場合にのみ中括弧を使用します。視覚的な補助で、それがどこで終了するかを教えてください。
メソッドは、必要なときにいつでも使用する必要があります。関数オブジェクトは、他のメソッドに渡して使用するときはいつでも作成する必要があります(または、関数を適用できるようにするときはいつでもパラメーターとして指定する必要があります)。たとえば、値をスケーリングできるようにしたいとします。
class Scalable(d: Double) {
def scale(/* What goes here? */) = ...
}
定数乗数を指定できます。または、追加するものと乗算するものを提供することもできます。Double
しかし、最も柔軟な方法として、からまでの任意の関数を要求するだけですDouble
。
def scale(f: Double => Double) = f(d)
さて、あなたはデフォルトのスケールのアイデアを持っているかもしれません。それはおそらくスケーリングではありません。したがって、を取りDouble
、まったく同じを返す関数が必要になる場合がありますDouble
。
val unscaled = (d: Double) => d
val
関数を何度も作成し続けたくないので、関数をに格納します。これで、この関数をデフォルトの引数として使用できます。
class Scalable(d: Double) {
val unscaled = (d: Double) => d
def scale(f: Double => Double = unscaled) = f(d)
}
x.scale
これで、andx.scale(_*2)
とandの両方を呼び出すことができ、x.scale(math.sqrt)
すべて機能します。