スカラ。 皆のために夕暮れから抜け出しましょう!

そして今、あなたは吹く必要があります、あなたが吹かないならば、何も働かないからです。

-偉大な名言



そしてこんにちは!



今日は暗黙のScala言語についてお話します。 まだ推測していない人は、暗黙の変換、パラメーター、クラスなどについて話します。XenovExplicitを使用するすべての新規ユーザー、特にPythonの愛好家はImplicitよりも優れています。 1つの記事でコンパイラ全体と原則全体をカバーすることは不可能ですが、道は圧倒されますか?


1.暗黙の変換



そして、暗黙的な変換の比較的単純なセクションから始めます。 そして人生の例。

ヴァシリーは、メーカーのルノーの車を望んでいます。 家族全員が長い間お金を節約していましたが、彼らは全額を貯めることができませんでした。 新しいWHAに十分なお金のみ。 そして、突然拍手! ルノーがAvtoVAZを買収。 製造業者が今必要であり、十分なお金があるようです。 そして、暗黙のうちに、ヴァシャは外国車の幸せな所有者になりました。

次に、これをコードの形式で形式化しようとします。



人生の例
case class Vasiliy(auto: Renault) { println("Vasiliy owns "+auto) } case class Renault(isRussian: Boolean = false) case class VAZ(isRussian: Boolean = true) object VAZ { implicit def vaz2renault(vaz: VAZ): Renault = Renault(vaz.isRussian) //   } object Family { def present = { Vasiliy(VAZ()) //  .   ! } }
      
      





Family.present



の実行の結果、 Vasiliy owns Renault(true)



する行が表示されVasiliy owns Renault(true)



。 これがScalaがこの困難な生活の中で普通の人々を助ける方法です!

もっとプログラム的な例を挙げれば(私のプロジェクトで似たようなものを使用します):



生気のない例
 case class PermissionsList(permissions: Set[String] = Set("UL")); object PermissionsList { implicit def str2permissions(str: String) = PermissionsList(str.split(";").toSet) implicit def permissions2str(p: PermissionsList) = p.permissions.mkString(";") } // case class User(login: String, permissions: PermissionsList) /* somewhere in a galaxy far far away */ User(login = "Vasiliy", permissions = "UL;AL") //      
      
      





上記のコードにより、文字列を暗黙的にアクセスオブジェクトにキャストしたり、その逆を行うことができます。 これは、同じWeb上で作業するときに便利です。クライアントに"UL;AL"



という形式の目的の行を"UL;AL"



付けて、サーバーに送信するだけで、適切なタイミングでオブジェクトに変換されます。

そして、私たちは重要なポイントに来ました 。 VAZ カボチャがいつどのような条件下でルノーになり、文字列がPermissionsListオブジェクトになりますか?



ほとんどの場合、Scalaのすべての魔法はコンパイル時に発生します(言語は強く型付けされています)。 ローカルコンパイラは非常に賢く、機知に富んだ生き物です。 存在しなかったVAZクラスのインスタンスでexat()メソッドを呼び出そうとするとすぐに、コンパイラーは真剣に起動し metaをクックして VAZのexat()が実行可能なものへの暗黙的な変換を探します。 つまり、 implicit def a2b(a: A): B





彼は暗黙的な変換を探しています:

ところで、存在しないメソッドを呼び出すだけでなく、コンパイラは、異なるデータ型のパラメーターを必要とするメソッド/関数にオブジェクトを渡そうとすると、オブジェクトを変換しようとします。 これは、ヴァシリーと彼の家族の例からです。


1.1暗黙のクラス



バージョン2.10から、暗黙クラスがScalaに登場し、既存クラスの拡張機能を簡単にグループ化(メソッドを追加)できるようになりました。 以下に簡単な例を示します。



 object MySimpleHelper { implicit class StringExtended(str: String) { def sayIt = println(str) def sayItLouderBitch = println(str.toUpperCase +"!!!") } }
      
      





引用された生データからわかるように、単一の引数(文字列)をとるオブジェクト内で宣言されたクラスがあります。 この行は、クラスメソッドの断片に引き裂かれるように与えられています。 そして、このことは単純に苦しめられます。



 import MySimpleHelper._ "oh gosh" sayIt > oh gosh "oh gosh" sayItLouderBitch > OH GOSH!!!
      
      





ただし、ここで注意しなければならない制限がいくつかあります。



実際、 StringExtended



はコンパイラによって次のように変換されます。



 class StringExtended(str: String) { def sayIt = println(str) def sayItLouderBitch = println(str.toUpperCase +"!!!") } implicit def String2StringExtended(str: String): StringExtended = new StringExtended(str)
      
      





おなじみですか?


2.暗黙のパラメーター



どういうわけか、すべてが単純すぎて、あなたはすでに退屈していますか? それは少しハードコアの時間です! 脳を動かして岩の根源に登りましょう:



Surlyコード
 /** * TraversableOnce.scala: minBy * ,  ,      ,      ,    ,    B    A . ,   B    ,    A,  B  . - . */ def minBy[B](f: A => B)(implicit cmp: Ordering[B]): A = { //   -   ? if (isEmpty) throw new UnsupportedOperationException("empty.minBy") //     var minF: B = null.asInstanceOf[B] var minElem: A = null.asInstanceOf[A] var first = true //    //   for (elem <- self) { //    A,   B val fx = f(elem) if (first || cmp.lt(fx, minF)) { //     -     . //  cmp.lt  true   ,  f: B <   minF: B minElem = elem minF = fx first = false } } minElem }
      
      





プッシュされた、それはすべてが明らかであるようだ。

ストップ、2番目。 ただし、次のようなminByを使用します。
 val cities = Seq(new City(population = 100000), new City(500000)) val smallCity = cities.minBy( city => city.population )
      
      





そして、 cmp: Ordering[B] ( B == Int)



渡しませんcmp: Ordering[B] ( B == Int)



。 コードは機能しているように見えますが...リラックスしてください。 これは魔法です。

インポートされたスコープ、特にscala.math.Ordering



存在する



そのようなコード
 object Ordering extends LowPriorityOrderingImplicits { ... trait IntOrdering extends Ordering[Int] { def compare(x: Int, y: Int) = if (x < y) -1 else if (x == y) 0 else 1 } implicit object Int extends IntOrdering ... }
      
      





最後の行に注意しましょう-IntOrdering IntOrdering



Ordering[Int]



継承するときに実装されるcompare



メソッドを含む暗黙のIntオブジェクトがありIntOrdering



。 実際、このオブジェクトは比較のために使用され、暗黙的に不運なminBy



ます。

非常に単純化された例は次のようになります。



フレンドリーコード
 implicit val myValue: Int = 5 object Jules { def doesHeLookLikeABitch(answer: String)(implicit times: Int) = { for(x <- 1 to times) println(answer ) } } Jules.doesHeLookLikeABitch("WHAT?") >WHAT? >WHAT? >WHAT? >WHAT? >WHAT?
      
      





もちろん、ハンドルによって暗黙的なパラメーターを転送することを禁止する人はいません。 いいえ、まあ、突然必要になります。

そして、繰り返しますが、制限はありません。


3.ビュー/コンテキストの境界



脳がすでに溶けている場合は、休憩してコーヒーを飲むか、何か強いものを飲んでください。 今日の最新の非自明性についてお話します。

新しい車( exat()



車)を運転するVasilyが成功した人、つまりプログラマーになったとしましょう。 そして今、VasilyはScalaについて書いており、彼はもう1つのSUGAR ARRHHを望んでいました。 マーティンは考えて言った-わかりました。 そして、それらにタイプと制限を導入しました。 同じdef f[T](a: T)







3.1ビューの境界


型を宣言するときのこの制限は、コンパイラに真の暗黙的な変換がどこかに近いことを伝えます。



 def f[A <% B](a: A) = a.bMethod
      
      





つまり アクセス可能なスコープでA



からB



への暗黙的な変換があります。 原則として、次の形式のエントリを想像できます。



 def f[A](a: A) (implicit a2b: A => B) = a.bMethod:
      
      





ロシア人に近い例は次のようになります。



 class Car { def exat() = println("POEXALI") } class VAZ object VAZ { implicit def vaz2car(v: VAZ): Car = new Car() } def go[A <% Car](a: A) = a.exat() go(new VAZ()) > POEXALI
      
      





いいね! 人生は美しくなり、髪は元に戻り、妻は戻ってきました。

しかし、ヴァシリーはそれを求めました、そして、マーティンはもう止められませんでした...それで、それは現れました



3.2コンテキスト境界


この制限はScala 2.8で導入されたもので、View Boundsとは異なり、暗黙的な変換には責任を負いませんが、暗黙的なパラメーターには責任があります



 def f[A : B](a: A) = g(a) //  g    B[A]
      
      





最も単純な例は、そのようなペアです。



 def f[A : Ordering](a: A, b: A) = if (implicitly[Ordering[A]].lt(a, b)) a else b vs def f[A](a: A, b: A)(implicit ord: Ordering[A]) = { import ord._ if (a < b) a else b }
      
      





実際、これはHaskellと彼のタイプクラスパターンの遠いあいさつです。


あとがきの代わりに



道はそれで終わりではありません;長い間Scalaについて話すことができます。 しかし、一度にすべてではありません。なぜなら、主なことは理解と理解への欲求だからです。 欲求には、何が起こっているのかが認識されます。

この記事を読んだ後、暗黙的な変換を使用するプロジェクトのコードを理解できない場合は、メモ帳を閉じて通常のIDEを開くことをお勧めします。 そして、私の頭は沸騰しません、私は行きます。 ご清聴ありがとうございました。



All Articles