1. ホーム
  2. スカラ

[解決済み】Scalaのimplicitを理解する。

2022-04-29 02:24:13

質問

Scalaのplayframeworkのチュートリアルを進めていたところ、このコードの断片に遭遇し、困惑しています。

def newTask = Action { implicit request =>
taskForm.bindFromRequest.fold(
        errors => BadRequest(views.html.index(Task.all(), errors)),
        label => {
          Task.create(label)
          Redirect(routes.Application.tasks())
        } 
  )
}

そこで、調査することにしたのですが、出会ったのが この記事 .

まだわからない

これのどこが違うんだ。

implicit def double2Int(d : Double) : Int = d.toInt

そして

def double2IntNonImplicit(d : Double) : Int = d.toInt

は、メソッド名が異なるという明らかな事実以外、何もありません。

どのような場合に implicit とその理由を教えてください。

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

以下、インプリシットの主な使用例を説明しますが、より詳しい説明は Scalaのプログラミングの関連する章 .

暗黙のパラメータ

メソッドの最終パラメータリストには、以下のようなマークが付けられます。 implicit これは、値が呼び出されたコンテキストから取得されることを意味します。スコープ内に正しい型の暗黙の値がない場合は、コンパイルされません。暗黙の値は単一の値に解決されなければならないので、 衝突を避けるために、その型はその目的に特化したものにするのがよいでしょう。 Int !

の例です。

  // probably in a library
class Prefixer(val prefix: String)
def addPrefix(s: String)(implicit p: Prefixer) = p.prefix + s

  // then probably in your application
implicit val myImplicitPrefixer = new Prefixer("***")
addPrefix("abc")  // returns "***abc"

暗黙の変換

コンパイラは、コンテキストに合わない型の式を見つけると、その式に対応する暗黙の Function の値は、型チェックができるような型のものでなければならない。したがって、もし A が要求され B の暗黙の値を探します。 B => A のような他の場所もチェックします。 BA コンパニオンオブジェクトが存在する場合)。このため def は、quot;eta-expanded" にすることができます。 Function オブジェクトは implicit def xyz(arg: B): A も同様です。

つまり、あなた方のメソッドの違いは implicit を指定すると、コンパイラが代わりに挿入してくれます。 Double が見つかりましたが Int が必要です。

implicit def doubleToInt(d: Double) = d.toInt
val x: Int = 42.0

と同じ働きをします。

def doubleToInt(d: Double) = d.toInt
val x: Int = doubleToInt(42.0)

2番目の例では手動で変換を挿入しているが、1番目の例ではコンパイラが自動的に同じことを行っている。変換が必要なのは、左側の型注釈のためです。


Playの最初のスニペットについて。

アクションの説明は このページ は、Play のドキュメントから ( APIドキュメント ). あなたが使っているのは

apply(block: (Request[AnyContent]) ⇒ Result): Action[AnyContent]

を追加しました。 Action オブジェクトを作成します (これは、同名のトライットに付随するものです)。

そこで、引数としてFunctionを与える必要があります。これは、次のような形式のリテラルとして書くことができます。

request => ...

関数リテラルの中で => は値の宣言であり implicit のように、必要であれば、他の val の宣言があります。ここで request ではありません。 はマークする必要があります。 implicit をタイプチェックすることができますが、そうすることで 暗黙の値として利用可能 は、関数内でそれを必要とする可能性のあるすべてのメソッドで使用できます (もちろん、明示的に使用することも可能です)。この場合、これは bindFromRequest メソッドで フォーム クラスでは、暗黙のうちに Request 引数を指定します。