Scalaで「20秒」はどのように機能しますか?


130

以下はどのようにコンパイルされますか:

import scala.concurrent.duration._

val time = 20 seconds

ここで実際に何が起こっているのですか?

回答:


171

いくつかのことが進行中です。

まず、Scalaでは多くのメソッド呼び出しでドットと括弧を省略できるため20 seconds20.seconds()* と同等です。

次に、「暗黙の変換」が適用されます。以来で20あるIntInt何も持っていないseconds取り暗黙的な変換のための方法、コンパイラを検索Intし、何かを返していないseconds、あなたのメソッド呼び出しの範囲によって制約検索して、方法を。

スコープにDurationIntをインポートしました。以来DurationIntと暗黙のクラスであるIntパラメータ、そのコンストラクタは、暗黙的な定義Int => DurationInt変換。DurationInt持っているseconds方法を、それを満たすすべての検索条件。したがって、コンパイラは呼び出しをnew DurationInt(20).seconds**に書き換えます。

*ゆるいという意味です。メソッドにはパラメータリストがないため、メソッド呼び出しで括弧を省略する必要20.seconds()あるため、実際には無効です。seconds

**実際には、これはDurationInt値クラスなので真実ではありません。コンパイラーは、可能であれば整数をラップしないようにします。


83
十分に進歩した技術は、魔法と区別がつきません。
ripper234 2013

4
幸い、ほとんどのIDEはそれを区別できます。暗黙的な変換はScalaでかなり頻繁に使用されます。テキストファイルを読んでいるだけでは混乱する可能性がありますが(「その方法はどこから来たのか」)、適切なツールサポートがあれば、方法を見つけることができるはずです。その時点で、Scalaは美しく意味のある簡潔なものになります。(たとえば、20.secondsは、new DurationInt(20).seconds()それがどのように行われるかを知っている限り、はるかに読みやすくなります)
William Billingsley

1
インプリシットを使用していることに気付いた場合は、常に助けなしに同じことを達成する方法があるかどうかを自問してください。 twitter.github.com/effectivescala/#Types and Generics-Implicits
oluies

4
実際、secondsメソッドは括弧なしで定義されているため、括弧で呼び出すとエラーになります。
フランクS.トーマス

1
@フランクそれは良い点です。私は、あなたが20.seconds()Scalaで書けることを示唆するつもりはありませんでした。コンパイラーがその呼び出しをそのように翻訳しているということだけです。この場合のように、対応するメソッドにパラメーターリストがない場合、Scala では括弧を省略する必要があることを指摘しておくのは価値があります。
アーロンノヴストラップ、2013

7

そこで行われている「魔法」は「暗黙の変換」と呼ばれます。暗黙的な変換をインポートしており、その一部はInt(およびDouble)からDurationへの変換を処理します。それはあなたが扱っているものです。


1
インポートがimport scala.concurrent.duration._解決する20 secondsが、実際にDurationConversionsトレイトをインポートしない理由は何ですか? 編集:ちょうど彼らが実際にインポートしているものであることに気づきましたDurationInt。これは実際の特性をインポートできないためだと思いますか?特性の具体的な実装のみですか?
フランクリン
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.