0
Upcoming SlideShare
×

Thanks for flagging this SlideShare!

Oops! An error has occurred.

×
Saving this for later? Get the SlideShare app to save on your phone or tablet. Read anywhere, anytime – even offline.
Standard text messaging rates apply

# Implicit Explicit Scala

2,859

Published on

Scalaのimplicit parameter入門的な何かです。

Scalaのimplicit parameter入門的な何かです。

Published in: Technology
3 Likes
Statistics
Notes
• Full Name
Comment goes here.

Are you sure you want to Yes No
• Be the first to comment

Views
Total Views
2,859
On Slideshare
0
From Embeds
0
Number of Embeds
1
Actions
Shares
0
11
0
Likes
3
Embeds 0
No embeds

No notes for slide

### Transcript

• 1. Implicit Explicit Scala 水島 宏太 (@kmizu)
• 2. 自己紹介
• 3. の前にお約束
• 4. JIT(Just In Tsukkomi)歓迎
• 6. Continuation Workshop 2011 (2011/09/24)限定継続の人(Tiark Rompf)が来てた あ、ありのまま(ry
• 7. ちなみにこの自己紹介は(ry
• 8. 今回説明すること
• 9. その前にQuiz * 3
• 10. ルール：-Xprint:typer禁止
• 11. Q.1 A1-A3, B1-B3 を埋めてくださいval m = Map("A" -> 1, "B" -> 2)m.map{case (x, y) => (y, x)}m.map{case (x, y) => x}m.map[A1, A2]({case (x, y) => (y, x) })(?:A3)m.map[B1, B2]{case (x, y) => x })(?:B3)
• 12. A.1val m = Map("A" -> 1, "B" -> 2)m.map{case (x, y) => (y, x)}m.map{case (x, y) => x}m.map[(Int, String), Map[Int, String]]{ case (x, y) => (y, x) }(?:CanBuildFrom[Map[String, Int], String, Map[Int, String])m.map[String, Iterable[String]]({ case (x, y) => x })(?:CanBuildFrom[Map[String, Int], String, Iterable[String]]
• 13. Why ?
• 14. Q.2 A1, A2, B1, B2 を埋めてくださいval l1 = List(1, 2, 3)val l2 = List(1.5, 2.5, 3.5)l1.suml2.suml1.sum[A1](?:A2)l2.sum[B2](?:B2)
• 15. A.2val l1 = List(1, 2, 3)val l2 = List(1.5, 2.5, 3.5)l1.suml2.suml1.sum[Int](?:Numeric[Int])l2.sum[Double](?:Numeric[Double])
• 16. Why ?
• 17. Q.3 A1-A3, B1-B3 を埋めてくださいval l1 = List("A" -> 1, "B" -> 2)val l2 = List(1, 2, 3)l1.toMapl2.toMapl1.toMap[A1, A2](?:A3)l2.toMap[B1, B2](?:B3)
• 18. A.3val l1 = List("A" -> 1, "B" -> 2)val l2 = List(1, 2, 3)l1.toMapl2.toMapl1.toMap[String, Int](?: (String, Int) <:< (String, Int))l2.toMap[B1, B2](?:B3)→ error: Cannot prove that Int <:< (T, U).
• 19. Why ?
• 20. 3つに共通するもの
• 21. それは
• 22. Implicit Parameter
• 23. Implicit Parameter
• 24. 最も誤解されてきた機能
• 25. 実はとても強力な機能
• 26. implicit parameter=省略可能引数
• 27. とりあえず
• 28. implicit parameter
• 29. が今回のメイン
• 30. A.1～A.3の意味がわかる ようになる(はず)
• 31. 基本
• 32. def hoge(implicit x: Int) = x + 3implicit val INT: Int = 3println(hoge) → println(hoge(INT)) → 6
• 33. 間違いではないが
• 34. 全然嬉しくない
• 35. 基本
• 36. trait Addible[A] { def plus(x: A, y: A): A def zero: A}implicit object IntAddible extends Addible[Int] { def plus(x: Int, y: Int): Int = x + y def zero: Int = 0}def sum[A](nums: List[A])(implicit addible: Addible[A]): A = { nums.foldLeft(addible.zero)((x, y) => addible.plus(x, y))}println(sum(List(1, 2, 3, 4, 5)))→ println(sum(List(1, 2, 3, 4, 5))(IntAddible))
• 37. implicit宣言された型に適合する implicitな値を拾ってくれる
• 38. implicit探索規則
• 39. 基本：静的スコープで決まる
• 40. メソッド呼び出し時に「直接参 照可能な」implicitな値が対象
• 41. 「直接参照可能な」の意味1. 同一スコープにimplicitな値が定義されている2. importによってimplicitな値が導入されている
• 42. 例外規則
• 43. implicit parameterの型に「関連付けられ たクラス/トレイト」のコンパニオンオ ブジェクトも探索対象
• 44. 「関連付けられたクラス/トレイト」
• 45. trait G[A, B, C] の場合：G, A, B, C のコンパニオンオブジェクトを探索
• 46. trait Addible[A] { def plus(x: A, y: A): A def zero: A}object Addible { //companion object implicit object IntAddible extends Addible[Int] { def plus(x: Int, y: Int): Int = x + y def zero: Int = 0 }}def sum[A](nums: List[A])(implicit addible: Addible[A]): A = { nums.foldLeft(addible.zero)((x, y) => addible.plus(x, y))}println(sum(List(1, 2, 3, 4, 5)))→ println(sum(List(1, 2, 3, 4, 5))(IntAddible)) // OK
• 47. デフォルトで探索対象にして欲しいimplicitな値をコンパニオンオブジェクト に入れると便利
• 48. 何が嬉しい？
• 49. Doubleもsumしたくなった
• 50. implicit object DoubleAddible extends Addible[Int] { def plus(x: Double, y: Double): Double = x + y def zero: Double = 0.0}println(sum(List(1.0, 2.0, 3.0)))→ println(sum(List(1.0, 2.0, 3.0))(DoubleAddible))
• 51. 元のデータ型に変更を加えずに
• 52. データ型の性質を新しく定義
• 53. 特殊：implicit推論規則
• 54. implicitな値から型パラメータを 「逆向きに」推論可能
• 55. Scala 2.8で導入
• 56. implicit val tupleA: (Int, String) = (1, "A")implicit val tupleB: (Double, String) = (1.5, "B")def useImplicitTuple2[A, B](value: A)(implicit tuple: (A, B)): B = { tuple._2}println(useImplicitTuple2(100)) // Aprintln(useImplicitTuple2(1.5)) // B
• 57. Aに応じて推論されるBが変わる
• 58. 2.8コレクションには不可欠
• 59. A.1 ～ A.3の定義をもう一度見てみる
• 60. A.1val m = Map("A" -> 1, "B" -> 2)// def map [B, That] (f: ((A, B)) ⇒ B)(implicit bf: CanBuildFrom[Map[A, B], B, That]): Thatm.map{case (x, y) => (y, x)}m.map{case (x, y) => x}m.map[(Int, String), Map[Int, String]]{ case (x, y) => (y, x) }(?:CanBuildFrom[Map[String, Int], String, Map[Int, String])m.map[String, Iterable[String]]({ case (x, y) => x })(?:CanBuildFrom[Map[Int, String], String, Iterable[String]])
• 61. 引数の型情報から順方向に推論 したのではThatはわからないimplicit推論規則による解決
• 62. scala.collection.immutable.Map のコンパニオンオブジェクト
• 63. package scala.collectionpackage immutableobject Map ... { .. //Coll = Map[_, _] implicit def canBuildFrom[A, B]: CanBuildFrom[Coll, (A, B), Map[A, B]] = new MapCanBuildFrom[A, B]}
• 64. (1) 任意の型A, B について CanBuildFrom[Map[_, _], (A, B), Map[A, B]]型のimplicitな値を生成可能
• 65. scala.collection.Iterableのコンパニオンオブジェクト
• 66. package scala.collection...object Iterable ... { .. //Coll = Iterable[A] implicit def canBuildFrom[A]: CanBuildFrom[Coll, (A), Iterable[A]] = new GenericCanBuildFrom[A]}
• 67. (2) 任意の型A, B について CanBuildFrom[Iterable[_, _], (A), Iterable[A]]型のimplicitな値を生成可能
• 68. 適用優先度： (1) > (2)
• 69. (1)が適合していなくても (2)が適合すればOK
• 70. A.2val l1 = List(1, 2, 3)val l2 = List(1.5, 2.5, 3.5)l1.suml2.sum// def sum [B >: A] (implicit num: Numeric[B]): Bl1.sum[Int](?:Numeric[Int])l2.sum[Double](?:Numeric[Double])
• 71. package scala.math...object Numeric { trait IntIsIntegral extends Integral[Int] { def plus(x: Int, y: Int): Int = x + y def minus(x: Int, y: Int): Int = x - y def times(x: Int, y: Int): Int = x * y def quot(x: Int, y: Int): Int = x / y def rem(x: Int, y: Int): Int = x % y def negate(x: Int): Int = -x def fromInt(x: Int): Int = x def toInt(x: Int): Int = x.toInt def toLong(x: Int): Long = x def toFloat(x: Int): Float = x def toDouble(x: Int): Double = x } .. // Integeral[T] <: Numeric[T] なので、 Numeric[Int]のimplicitな値も同時に定義 // していることになる implicit object IntIsIntegral extends IntIsIntegral with Ordering.IntOrdering}
• 72. A.3val l1 = List("A" -> 1, "B" -> 2)val l2 = List(1, 2, 3)l1.toMapl2.toMap 名状し難い型l1.toMap[String, Int](?: (String, Int) <:< (String, Int))l2.toMap[B1, B2](?:B3)→ error: Cannot prove that Int <:< (T, U).
• 73. 答えはPredefの中に
• 74. package scala.math...object Predef ... { @implicitNotFound(msg = "Cannot prove that \${From} <:< \${To}.") sealed abstract class <:<[-From, +To] extends (From => To) with Serializable 名状し難い型の定義 private[this] final val singleton_<:< = new <:<[Any,Any] { def apply(x: Any): Any = x } // not in the <:< companion object because it is also // intended to subsume identity (which is no longer implicit) implicit def conforms[A]: A <:< A = singleton_<:<.asInstanceOf[A <:< A]}
• 75. ポイント
• 76. sealed abstract class <:<[-From, +To]implicit def conforms[A]: A <:< A = singleton_<:<.asInstanceOf[A <:< A]
• 77. 任意の型AについてA <: A 型のimplicitな値を生成 可能(多相的なimplicit)
• 78. 名状し難い <:< の左辺：contravariant (-) 右辺: covariant(+)
• 79. def fun[A, B](a: A, b: B)(implicit ev: A <:< B)
• 80. A = Int, B = Any つまり A <: B のとき(Int <:< Any) なimplicitな値が必要
• 81. (Int <:< Int) <: (Int <:< Any) なので (<:< の右辺はcovariant)conforms[Int]: Int <: Int で適合する
• 82. A = Any, B = Int つまり A <: B のとき(Any <:< Int) なimplicitな値が必要
• 83. (Any <:< Any) <: (Any <: Int) かつ (Int <:< Int) <: (Any <: Int) (<:< の左辺はcontravariant) →コンパイルエラー
• 84. implicit parameterを使ったライブラリ/フレームワーク
• 85. Scala標準ライブラリ Scalaz sjson ScalaCheck spray Akka Squeryl ...
• 86. たくさんある
• 87. implicit parameterを活用してみてください
• 88. 通称コップ本 第二版 好評発売中Scala 2.8対応+付録Scala 2.9記事(by @kmizu)
• 89. 宣伝(2)
• 90. こんなキーワードにピンと来たら(ry Cakeパターン, CONCEPTパターン, 限定継続 現場でのScala, Javaとの連携