第一回社内 Scala 勉強会(一部抜粋)

3,390 views
3,330 views

Published on

社内勉強会の資料から一部抜粋
アップロード時点でまだ勉強は実施されていない :-(

Published in: Technology
0 Comments
16 Likes
Statistics
Notes
  • Be the first to comment

No Downloads
Views
Total views
3,390
On SlideShare
0
From Embeds
0
Number of Embeds
178
Actions
Shares
0
Downloads
13
Comments
0
Likes
16
Embeds 0
No embeds

No notes for slide

第一回社内 Scala 勉強会(一部抜粋)

  1. 1. Scala の言語機能  ここからが本番です  全ての言語機能について語るのは無理  本が書けるよ(多分上下巻)!  Scala で何ができるようになるか、を重点した  つもり…https://lepidum.co.jp/ Copyright © 2004-2012 Lepidum Co. Ltd. All rights reserved. Confidential
  2. 2. Scala の言語機能 – 型に対する制約  Java の場合  Nominal Subtyping  あるクラスと派生クラスの関係に基づく制約 public class Duck { … } public class UglyDuck extends Duck { … } public class DuckBreeder<T extends Duck> { … }https://lepidum.co.jp/ Copyright © 2004-2012 Lepidum Co. Ltd. All rights reserved. Confidential
  3. 3. Scala の言語機能 – 型に対する制約  Java の場合  Nominal Subtyping  あるクラスと派生クラスの関係に基づく制約  予め継承している必要がある public class Duck { … } public class UglyDuck extends Duck { … } public class DuckBreeder<T extends Duck> { … }https://lepidum.co.jp/ Copyright © 2004-2012 Lepidum Co. Ltd. All rights reserved. Confidential
  4. 4. Scala の言語機能 – 型に対する制約  Scala の場合  Nominal Subtyping  勿論 Scala にもある class Duck { … } class UglyDuck extends Duck { … } class DuckBreeder[T <: Duck] { … }https://lepidum.co.jp/ Copyright © 2004-2012 Lepidum Co. Ltd. All rights reserved. Confidential
  5. 5. Scala の言語機能 – 型に対する制約  Java の場合  Nominal Subtyping  あるクラスとその派生型のみを許容  予め継承している必要がある  問題点:機能を備えていても、継承していないとダメ public static boolean genericIsEmpty<T extends ???>(T t) { return t.isEmpty(); } // String も List も isEmpty を持ってはいるが… genericIsEmpty(“”); genericIsEmpty(new ArrayList());https://lepidum.co.jp/ Copyright © 2004-2012 Lepidum Co. Ltd. All rights reserved. Confidential
  6. 6. Scala の言語機能 – 型に対する制約  Scala の場合  Structural Subtyping  クラスの構造に基づく制約  必要な機能を備えてさえいれば、継承関係は必要ない type HasIsEmpty = { def isEmpty(): Boolean } def genericIsEmpty[T <: HasIsEmpty](t: T) = t.isEmpty() genericIsEmpty(“”) genericIsEmpty(new java.util.ArrayList())https://lepidum.co.jp/ Copyright © 2004-2012 Lepidum Co. Ltd. All rights reserved. Confidential
  7. 7. Scala の言語機能 – 型に対する制約  Scala の場合  Structural Subtyping  クラスの構造に基づく制約  必要な機能を備えてさえいれば、継承関係は必要ない  実は名前をつける必要も制約にする必要もない def genericIsEmpty(v: { def isEmpty(): Boolean }) = v.isEmpty() genericIsEmpty(“”) genericIsEmpty(new java.util.ArrayList())https://lepidum.co.jp/ Copyright © 2004-2012 Lepidum Co. Ltd. All rights reserved. Confidential
  8. 8. Scala の言語機能 – 型に対する制約  Scala の場合  Structural Subtyping  クラスの構造に基づく制約  必要な機能を備えてさえいれば、継承関係は必要ない  実装にはリフレクションが使われているので注意  通常のメソッド呼び出しに比べると遙かに遅い  メソッドキャッシュもあるし、そこまで気にしなくてもいいけれど…  分割コンパイルの実現のために仕方なくこうなっているhttps://lepidum.co.jp/ Copyright © 2004-2012 Lepidum Co. Ltd. All rights reserved. Confidential
  9. 9. Scala の言語機能 – 型に対する制約  Java の場合  機能を備えていないが、定義することができる場合  問題点:制約がどうのこうの以前の問題だ… public static char genericHead<T extends ???>(T t) { return t.head(); } genericHead(“akari”);https://lepidum.co.jp/ Copyright © 2004-2012 Lepidum Co. Ltd. All rights reserved. Confidential
  10. 10. Scala の言語機能 – 型に対する制約  Java の場合  機能を備えていないが、定義することができる場合  問題点:制約がどうのこうの以前の問題だ…  解決:Adapter pattern(GoF) を利用する public interface Headable { char head(); } public class StringHeadableAdapter implements Headable { private String str; public StringHeadable(String str) { this.str = str; } @Override public char head() { return str.charAt(0); } }https://lepidum.co.jp/ Copyright © 2004-2012 Lepidum Co. Ltd. All rights reserved. Confidential
  11. 11. Scala の言語機能 – 型に対する制約  Java の場合  機能を備えていないが、定義することができる場合  問題点:制約がどうのこうの以前の問題だ…  解決:Adapter pattern(GoF) を利用する  問題点:一々 Adapter 通すのが面倒… public static char genericHead<T extends Headable>(T t) { return t.head(); } genericHead(new StringHeadableAdapter(“akari”));https://lepidum.co.jp/ Copyright © 2004-2012 Lepidum Co. Ltd. All rights reserved. Confidential
  12. 12. Scala の言語機能 – 型に対する制約  Scala の場合  機能を備えていないが、定義することができる場合  Implicit Conversions により機能を備えた型に変換  Implicit と修飾された引数を一つ取る関数により定義 trait Headable { def head(): Char } class StringHeadable(str: String) extends Headable { def head() = str.charAt(0) } implicit def stringIsHeadable(str: String) = new StringHeadable(str)https://lepidum.co.jp/ Copyright © 2004-2012 Lepidum Co. Ltd. All rights reserved. Confidential
  13. 13. Scala の言語機能 – 型に対する制約  Scala の場合  機能を備えていないが、定義することができる場合  Implicit Conversions により機能を備えた型に変換  Implicit と修飾された引数を一つ取る関数により定義  View Bounds と呼ばれる型制約が利用可能 // T から Headable へ暗黙に変換可能なことを要求 def genericHead[T <% Headable](t: T) = t.head()https://lepidum.co.jp/ Copyright © 2004-2012 Lepidum Co. Ltd. All rights reserved. Confidential
  14. 14. Scala の言語機能 – 型に対する制約  Scala の場合  機能を備えていないが、定義することができる場合  Implicit Conversions により機能を備えた型に変換  Implicit と修飾された引数を一つ取る関数により定義  View Bounds と呼ばれる型制約が利用可能  変換は暗黙に行われる  Java の問題点を解決  明示的に変換することもできる genericHead(“akari”) genericHead(stringIsHeadable(“akari”)) genericHead(new StringHeadable(“akari”))https://lepidum.co.jp/ Copyright © 2004-2012 Lepidum Co. Ltd. All rights reserved. Confidential
  15. 15. Scala の言語機能 – 型に対する制約  Pimp My Library (pattern)  Implicit Conversions による機能追加の名称  Scala 標準ライブラリでも普通に使われている  Scala の String は java.lang.String  でも何故か何もしなくても head メソッドが呼べてしまう  予めリッチな型への暗黙変換が定義されているため  他にも色々  RichXXX とか WrappedXXX とか XXXOps とかhttps://lepidum.co.jp/ Copyright © 2004-2012 Lepidum Co. Ltd. All rights reserved. Confidential
  16. 16. Scala の言語機能 – 型に対する制約  Pimp My Library と他言語の機能の比較  Ruby の Open Classes  グローバルに影響してしまう  Scala なら import によりコントロール可能  メソッドが「本当に」追加される(善し悪しは兎も角)  動的型付きなので型制約に関しては特になし  C# の Exntension Methods  単なる Syntax Sugar に過ぎない  よって、拡張したクラスが満たすことのできる制約は増えないhttps://lepidum.co.jp/ Copyright © 2004-2012 Lepidum Co. Ltd. All rights reserved. Confidential
  17. 17. Scala の言語機能 – 型に対する制約  Implicit Conversions の弱点  定義が面倒なことがある  2.10 で導入される Implicit Classes である程度解決  変換の度に中間オブジェクトが生成される  2.10 で導入される Value Classes で解決  C# の Extension Methods とほとんど同じ  暗黙に行われるため、コードが追いづらい  Eclipse, IntelliJ IDEA なら変換箇所はハイライトされる  頑張れhttps://lepidum.co.jp/ Copyright © 2004-2012 Lepidum Co. Ltd. All rights reserved. Confidential
  18. 18. Scala の言語機能 – 型に対する制約 ちょっと戻るhttps://lepidum.co.jp/ Copyright © 2004-2012 Lepidum Co. Ltd. All rights reserved. Confidential
  19. 19. Scala の言語機能 – 型に対する制約  Java の場合  機能を備えていないが、定義することができる場合  問題点:制約がどうのこうの以前の問題だ…  解決:Adapter pattern をちょっと変形して利用  何を扱う Adapter なのかを型パラメタを取ることで分かるように public interface Headable<T> { char head(T t); } public class StringHeadable implements Headable<String> { @Override public char head(String str) { return str.charAt(0); } }https://lepidum.co.jp/ Copyright © 2004-2012 Lepidum Co. Ltd. All rights reserved. Confidential
  20. 20. Scala の言語機能 – 型に対する制約  Java の場合  機能を備えていないが、定義することができる場合  問題点:制約がどうのこうの以前の問題だ…  解決:Adapter pattern をちょっと変形して利用  問題点:やっぱり面倒…  型情報から何とかして適切な Adapter を選択できないか? public static char genericHead<T>(T t, Headable<T> ev) { return ev.head(t); } genericHead(“akari”, new StringHeadable());https://lepidum.co.jp/ Copyright © 2004-2012 Lepidum Co. Ltd. All rights reserved. Confidential
  21. 21. Scala の言語機能 – 型に対する制約  Scala の場合  機能を備えていないが、定義することができる場合  Implicit Patameter により機能を備えた値を要求  値は「型に基づいて」自動的に探索される(詳細は後述)  Adapter Pattern をちょっと変形したのはこれのため  Java の問題点解決! def genericHead[T](T t)(implicit ev: Headable[T]) = { ev.head(t) } genericHead(“akari”) // ev は適切な値が見つかれば自動的に渡されるhttps://lepidum.co.jp/ Copyright © 2004-2012 Lepidum Co. Ltd. All rights reserved. Confidential
  22. 22. Scala の言語機能 – 型に対する制約  Scala の場合  機能を備えていないが、定義することができる場合  Implicit Patameter により機能を備えた値を要求  Context Bounds と呼ばれる型制約も利用可能  直接は使わないが、必要とするメソッドを呼ぶとき等に // Headable[T] が暗黙に定義されていることを要求 def genericHeadAsString[T : Headable](T t) = { genericHead(t).toString }https://lepidum.co.jp/ Copyright © 2004-2012 Lepidum Co. Ltd. All rights reserved. Confidential
  23. 23. Scala の言語機能 – 型に対する制約  Scala の場合  機能を備えていないが、定義することができる場合  Implicit Patameter により機能を備えた値を要求  implicit と修飾された val, var, def, object が対象  var はやめておきましょうね… trait Headable[T] { def head(t: T): Char } implicit object stringHeadable extends Headable[String] { def head(str: String) = str.charAt(0) }https://lepidum.co.jp/ Copyright © 2004-2012 Lepidum Co. Ltd. All rights reserved. Confidential
  24. 24. Scala の言語機能 – 型に対する制約  Scala の Implicit Parameters  引数の候補はどこから選ばれる?  メソッドの利用箇所から見える定義群と(自明)  要求されている型のコンパニオンオブジェクト内から  複数見つかった場合は?  最も定義場所の近い物が優先される  同じ名前空間で複数見つかった場合はエラーhttps://lepidum.co.jp/ Copyright © 2004-2012 Lepidum Co. Ltd. All rights reserved. Confidential
  25. 25. Scala の言語機能 – 型に対する制約  コンパニオンオブジェクトとは?  クラスと同名のオブジェクト  User オブジェクトはコンパニオンオブジェクト  ここではこれ以上は触れません class User(name: String, age: Int) object User { … }https://lepidum.co.jp/ Copyright © 2004-2012 Lepidum Co. Ltd. All rights reserved. Confidential
  26. 26. Scala の言語機能 – 型に対する制約 _人人人人人人人人人人_ > 突然の Type Classes <  ̄Y^Y^Y^Y^Y^Y^Y^Y ̄https://lepidum.co.jp/ Copyright © 2004-2012 Lepidum Co. Ltd. All rights reserved. Confidential
  27. 27. Scala の言語機能 – 型に対する制約  Scala の Implicit Parameters  実は Type Classes を実現するための言語機能  これまでのコードは下の Haskell コードと完全に一致  完全に一致、分かりましたですね? class Headable a where head :: a -> Char instance Headable String where head str = str !! 0 headAsString :: Headable a => a -> String headAsString a = show (head a)https://lepidum.co.jp/ Copyright © 2004-2012 Lepidum Co. Ltd. All rights reserved. Confidential
  28. 28. Scala の言語機能 – 型に対する制約  Type Classes  Functor, Applicative, Monad …  じゃない!!  モナモナするためだけのものではない  Type Classes = 型に機能を外から与える仕組み  あれ…なんだかデジャブ?  Implicit Conversions と Implicit Parameters って似てる?  実は Implicit Conversions も似たような物  手前味噌ですが参考  より詳細な話は今回はしませんhttps://lepidum.co.jp/ Copyright © 2004-2012 Lepidum Co. Ltd. All rights reserved. Confidential
  29. 29. Scala の言語機能 – 型に対する制約  標準ライブラリにおける Type Classes の実例  scala.reflect.ClassManifest  ClassManifest[T] は T の型情報を扱う  配列の生成時によく使われる  scala.collection.generic.CanBuildFrom  CanBuildFrom[From, Elem, To] 三つも型パラメタが!  From というコレクションから  Elem を要素とする  To というコレクションを生成する  ための Builder[Elem, To] を提供するhttps://lepidum.co.jp/ Copyright © 2004-2012 Lepidum Co. Ltd. All rights reserved. Confidential
  30. 30. Scala の言語機能 – 型に対する制約  Implicit Parameters のその他の用法  Type Classes と全く関係ない利用法も  Fighting type erasure(pdf 注意、スライドです)  何らかのコンテキストを引き回す  android.os.Context の引き回し  弊社のアンドロイドアプリのコードでも使われている  play.api.Application の引き回し  弊社の API サーバーのコードでも使われている  play.api.db.Connection の引き回し  弊社の API サーバーのコードでも使われて…なかったhttps://lepidum.co.jp/ Copyright © 2004-2012 Lepidum Co. Ltd. All rights reserved. Confidential
  31. 31. Scala の言語機能 – 型に対する制約  まとめ 1  Structural Subtyping  継承関係ではなく構造に基づいた制約が可能  Implicit Conversions(View Bounds)  暗黙に変換可能かどうかに基づいた制約が可能  実は Implicit Parameters と大差ない  Implicit Parameters(Context Bounds)  暗黙に定義されているかどうかに基づいた制約が可能  実は Type Classes が実現可能https://lepidum.co.jp/ Copyright © 2004-2012 Lepidum Co. Ltd. All rights reserved. Confidential
  32. 32. Scala の言語機能 – 型に対する制約  まとめ 2  Scala では様々な種類の型に対する制約がある  制約の種類が多い=柔軟に抽象的な設計が可能  アブストラクションヤッター!  触れなかったこと  Variance  Type constructor parameters  Lower bounds  これはまあ Java にもあるしね…  forSomehttps://lepidum.co.jp/ Copyright © 2004-2012 Lepidum Co. Ltd. All rights reserved. Confidential

×