Mais conteúdo relacionado Semelhante a Scala勉強会 (20) Scala勉強会4. はじめに
> 対象者?
日常的(?)にJavaが扱える人を対象とします
が、私はまだまだScala勉強中ですので、そこらへん
のご理解ある方(間違っていても優しくご指摘頂け
る方)に限ります
12. 第1部:JavaとScala
● Scalaって?
● REPL
● 変数宣言
● 制御構文/コレクションのライブラリ
● Tuple
● 無名関数
● クラスとオブジェクト
● Option型
● 引数について(+部分適用とカリー化)
● クロージャ
13. 第1部:JavaとScala - Scalaって?
特徴その1
スイス連邦工科大学(EPFL) のMartin Odersky先生と
いうかたが作った、オブジェクト指向型プログラミ
ング言語と関数型プログラミング言語の良い所取り
をしたようなプログラミング言語
※Martin Odersky先生
JavaのGenerics<T>や、Javacを作った方
14. 第1部:JavaとScala - Scalaって?
特徴その2
Javaと同じく、JVM上で動作
コンパイルされるとclassファイルになる
つまり、これまで作られてきたJavaプロダクトのす
べてをScalaから使うことができる
もちろん、classファイルになるのでJava側からも
Scalaプロダクトを使うことができる
19. 第1部:JavaとScala - Scalaって?
特徴その-1(Scalaのあまり良くないところ)
Date関連のAPIがない
→あるかもしれないけど、みんなJavaのDateをよく
使っている
def nowDate: java.util.Date = new java.util.Date
22. 第1部:JavaとScala - Scalaって?
特徴その-4(Scalaのあまり良くないところ)
仕事が無い
SI業やってるうちはScalaなんてやらない方が良い
脱SI目指すなら、ScalaでなくSwiftの方が良いんじゃないか
とか思ってたり
23. 第1部:JavaとScala
● Scalaって?
● REPL
● 変数宣言
● 制御構文/コレクションのライブラリ
● Tuple
● 無名関数
● クラスとオブジェクト
● Option型
● 引数について(+部分適用とカリー化)
● クロージャ
24. 第1部:JavaとScala - REPL
コマンドラインでScalaプログラムを実行できる機能
Scalaをインストールすれば使うことができる
ちょっとした動作確認をするときなど便利
$ scala
Welcome to Scala version 2.10.3 (Java HotSpot(TM) Client VM, Java 1.7.0_55).
Type in expressions to have them evaluated.
Type :help for more information.
scala> 1 + 1
res0: Int = 2
scala>_
25. 第1部:JavaとScala
● Scalaって?
● REPL
● 変数宣言
● 制御構文/コレクションのライブラリ
● Tuple
● 無名関数
● クラスとオブジェクト
● Option型
● 引数について(+部分適用とカリー化)
● クロージャ
27. Scala 第1部:JavaとScala - 変数宣言
varとvalがある
var name: String = "シャア・アズナブル"
val name: String = "アムロ・レイ"
varはvariable(変数)という意味で再代入が可能
valはvalue(値)という意味で再代入が不可能
28. 第1部:JavaとScala
● Scalaって?
● REPL
● 変数宣言
● 制御構文/コレクションのライブラリ
● Tuple
● 無名関数
● クラスとオブジェクト
● Option型
● 引数について(+部分適用とカリー化)
● クロージャ
30. Scala 第1部:JavaとScala - 制御構文
Javaに良く似ている
if (true/false) {} else {}
for (val <- list) {}
もちろん、while文やdo~whileもあるけど割愛
31. Scala 第1部:JavaとScala - 制御構文
for文の中にif文を書く事が出来る
val nameList: List[String] = List("シャア・アズナブル","","アムロ・レイ")
for (name <- nameList if !name.isEmpty) {
println(name)
}
32. Scala 第1部:JavaとScala - 制御構文
yieldを使うことで、処理結果をコレクションと
して受け取る事が出来る
val nameList: List[String] = List("シャア・アズナブル","","アムロ・レイ")
val resultList: List[String] = for (name <- nameList if !name.isEmpty) yield {
name
}
println(resultList)
33. Java 第1部:JavaとScala - 制御構文
Javaでやろうとするとこんな感じ
List<String> nameList = Arrays.asList("シャア・アズナブル","","アムロ・レイ");
List<String> resultList = new ArrayList<String>();
for (String name : nameList) {
if (name.isEmpty()) continue;
resultList.add(name);
}
System.out.println(resultList);
34. 第1部:JavaとScala - 制御構文
for文のネストについて
例えば、リストの中にリストが入る構造のデータが
あったとする
firstList
secondList secondList
ガンダム
ジム
ガンタンク
ザクII
グフ
ジオング
35. Java 第1部:JavaとScala - 制御構文
Javaで初期化するとこう
List<List<String>> firstList = Arrays.asList(
Arrays.asList("ガンダム","ジム","ガンタンク")
,Arrays.asList("ザクII","グフ","ジオング")
);
36. Scala 第1部:JavaとScala - 制御構文
Scalaで初期化するとこう
val firstList: List[List[String]] = List(
List("ガンダム","ジム","ガンタンク")
,List("ザクII","グフ","ジオング")
)
37. Java 第1部:JavaとScala - 制御構文
ネストforループのしかた
Javaではおなじみ
for (List<String> secondList : firstList) {
for (String name : secondList) {
System.out.println(name);
}
}
38. Scala 第1部:JavaとScala - 制御構文
ネストforループのしかた
セミコロンで区切って簡潔に記述可能
for (secondList <- firstList ; name <- secondList) {
println(name)
}
39. 第1部:JavaとScala - 制御構文
パターンマッチについて(match~case)
Javaのswitch~caseに似ているが、Scalaの
match~caseは、主力といっても良いほどちょー強力
な機能
40. Java 第1部:JavaとScala - 制御構文
Javaのswitch~caseで書いた例
String name = "シャア・アズナブル";
switch (name) {
case "シャア・アズナブル":
System.out.println("ジオン公国軍"); break;
case "アムロ・レイ":
System.out.println("地球連邦軍"); break;
default:
System.out.println("民間人"); break;
}
41. Scala 第1部:JavaとScala - 制御構文
Scalaのmatch~caseだとこう
あまり変わりないけど...
val name: String = "シャア・アズナブル"
name match {
case "シャア・アズナブル" => println("ジオン公国軍")
case "アムロ・レイ" => println("地球連邦軍")
case _ => println("民間人")
}
42. Scalaのmatch~caseは型でもパターンマッチ出来た
り...
abstract class MS(val name: String)
class NewGundam(override val name: String) extends MS(name)
class Sazaby(override val name: String) extends MS(name)
class Unicorn(override val name: String) extends MS(name)
def matcher(ms: MS) = ms match {
case mss: NewGundam => println(mss.name + " by ニューガンダム")
case mss: Sazaby => println(mss.name + " by サザビー")
case _ => println("所属不明機")
}
Scala 第1部:JavaとScala - 制御構文
43. Scala 第1部:JavaとScala - 制御構文
他にも柔軟なパターンマッチを実現することができ
たり
List.range(1, 10) foreach { i =>
(i % 3, i % 5) match {
case (0, 0) => println("FizzBuzz")
case (0, _) => println("Fizz")
case (_, 0) => println("Buzz")
case _ => println(i)
}
}
46. Scala 第1部:JavaとScala - コレクションライブラリ
mapとforeachの紹介
A.基本的にコレクションに対する値の操作
さて、冒頭で「Scalaのコレクションにはちょー強力なライブラ
リが多い」と述べたとおり
実は、それらを利用すると、for文自体使わなくても良いケースが
多かったりする
47. Scala 第1部:JavaとScala - コレクションライブラリ
foreach
例えば先ほどの下記は
val nameList: List[String] = List("シャア・アズナブル","","アムロ・レイ")
for (name: String <- nameList if !name.isEmpty) {
println(name)
}
48. Scala 第1部:JavaとScala - コレクションライブラリ
この様に記述できる
val nameList: List[String] = List("シャア・アズナブル","","アムロ・レイ")
nameList.filter(x => !x.isEmpty).foreach {
println(_)
}
省略できる
nameList.filter(x => !x.isEmpty) foreach(println(_))
さらに省略できる(やりすぎると意味不明に...)
nameList.filter(x => !x.isEmpty) foreach println
49. Scala 第1部:JavaとScala - コレクションライブラリ
他にもいろいろなライブラリ
この場合は
val nameList: List[String] = List("シャア・アズナブル","","アムロ・レイ")
val resultList: List[String] = for (name: String <- nameList if !name.isEmpty) yield {
name
}
filterメソッドを使えば一発
val nameList: List[String] = List("シャア・アズナブル","","アムロ・レイ")
val resultList: List[String] = nameList.filter(x => !x.isEmpty)
50. Scala 第1部:JavaとScala - コレクションライブラリ
map
mapメソッドを使うと、より柔軟かつ簡潔な記述が
出来る
val nameList: List[String] = List("シャア・アズナブル","","アムロ・レイ")
val resultList:List[String] = nameList.filter(x => !x.isEmpty) map { name =>
name.replace("シャア・アズナブル","キャスバル・レム・ダイクン")
}
println(resultList)
51. Scala 第1部:JavaとScala - コレクションライブラリ
foreachとmapの使い分け
どちらも要素に対して順次操作するが
・foreachはループ処理内だけで処理を完結
・mapはループ処理から戻り値を取得
する使い分けとなるとのこと
52. Scala 第1部:JavaとScala - コレクションライブラリ
foreach
要素による処理を実行
nameList.filter(x => !x.isEmpty) foreach { name =>
println(name)
}
53. Scala 第1部:JavaとScala - コレクションライブラリ
map
要素に変更を加える処理を実行
ただし、Scalaでは副作用を引き起こす“要素そのものに変更を加える”事を良しとしないので、新しいコレクショ
ンを生成する
val resultList:List[String] = nameList.filter(x => !x.isEmpty) map { name =>
name.replace("シャア・アズナブル","キャスバル・レム・ダイクン")
}
54. 第1部:JavaとScala
● Scalaって?
● REPL
● 変数宣言
● 制御構文/コレクションのライブラリ
● Tuple
● 無名関数
● クラスとオブジェクト
● Option型
● 引数について(+部分適用とカリー化)
● クロージャ
55. 第1部:JavaとScala - Tuple
Scala
Tuple
Tuple(タプル)とは、複数のさまざまな型のデータ
を一つにまとめる事が出来る機能
さまざまなシーンで使える
ただし、格納出来るオブジェクトは22個まで(タプ
ル23問題)
57. 第1部:JavaとScala - Tuple
Javaのメソッドの戻り値は一つ
public String getFirstName() {
return this.firstName;
}
public String getLastName() {
return this.lastName;
}
public int getAge() {
return this.age;
}
public String getFullName() {
return this.firstName + this.lastName;
}
Java
58. Scala 第1部:JavaとScala - Tuple
メソッドの戻り値にTupleを使えば...
case class Employee(val firstName: String, val lastName: String, val age: Int) {
def allData = (firstName, lastName, age) // Tupleを返却する
}
val emp: Employee = Employee("kazuomi","Endo",31)
val allData = emp.allData
println(allData._1) // kazuomi
println(allData._2) // endo
println(allData._3) // 31
println(allData._4) // これはコンパイルエラー
60. 第1部:JavaとScala
● Scalaって?
● REPL
● 変数宣言
● 制御構文/コレクションのライブラリ
● Tuple
● 無名関数
● クラスとオブジェクト
● Option型
● 引数について(+部分適用とカリー化)
● クロージャ
62. Scala 第1部:JavaとScala - 無名関数
無名関数
これはJavaで言う無名クラスの様なもので、省略せ
ずに書くとこうなる
nameList.filter {
(x: String) => {
!x.isEmpty
}
}
65. Scala 第1部:JavaとScala - 無名関数
無名関数
ちなみに、コレクションで説明した例の記述をあえ
てJavaで書くと
val nameList: List[String] = List("シャア・アズナブル","","アムロ・レイ")
val filteredList: List[String] = nameList.filter(x => !x.isEmpty)
println(filteredList)
66. Java 第1部:JavaとScala - 無名関数
無名クラス
interface MyList {
public List<String> filter(List<String> nameList);
}
MyList filterList = new MyList() {
public List<String> filter(List<String> nameList) {
List<String> returnList = new ArrayList<String>();
for (String name : nameList) {
if (name != null && name != ””) {
returnList.add(name);
}
}
return returnList;
}
};
67. Java 第1部:JavaとScala - 無名関数
ここらへんが無名クラス
interface MyList {
public List<String> filter(List<String> nameList);
}
MyList filterList = new MyList() {
public List<String> filter(List<String> nameList) {
List<String> returnList = new ArrayList<String>();
for (String name : nameList) {
if (name != null && name != ””) {
returnList.add(name);
}
}
return returnList;
}
};
68. Java 第1部:JavaとScala - 無名関数
実行
List<String> nameList = Arrays.asList("シャア・アズナブル","","アムロ・レイ");
List<String> filteredList = filterList.filter(nameList);
System.out.println(filteredList);
70. 第1部:JavaとScala
● Scalaって?
● REPL
● 変数宣言
● 制御構文/コレクションのライブラリ
● Tuple
● 無名関数
● クラスとオブジェクト
● Option型
● 引数について(+部分適用とカリー化)
● クロージャ
76. 第1部:JavaとScala - クラスとオブジェクト
クラスの定義
Scalaの場合、クラスの定義に引数を記述
class MyClass(name: String) {
// ここにコンストラクタの処理を定義
println("Hello World! %s".format(name))
}
---
val nameC = new MyClass("アムロ!")
Hello World! アムロ!
nameC: MyClass = MyClass@1835d850
Scala
77. 第1部:JavaとScala - クラスとオブジェクト
クラスの定義
二つ以上のコンストラクタ(オーバーロード)
class MyClass {
public MyClass(String name) {
}
public MyClass(String name, int age) {
}
}
Java
78. 第1部:JavaとScala - クラスとオブジェクト
クラスの定義
Scalaでは2つめ以降のコンストラクタを「補助コンストラク
タ」と言い、その前に定義されたコンストラクタを呼び出す必要
がある
class MyClass(name: String) {
println("Hello World! %s".format(name))
// 補助コンストラクタ
def this(name: String, age: Int) = {
this(name)
println("Hello World! %s %d".format(name, age))
}
}
Scala
79. 第1部:JavaとScala - クラスとオブジェクト
Scala
オブジェクトの定義
Scalaにはstaticの概念は無いが、シングルトンオブ
ジェクト(アプリ内に1つしかないオブジェクト)
を定義する事が出来る
object MyObject {
val limit = 1000
}
80. Scala
第1部:JavaとScala - クラスとオブジェクト
コンパニオンオブジェクトの定義
同名のクラスとオブジェクトを同一ソースに定義す
ると、そのオブジェクトはコンパニオンオブジェク
トと呼ばれるものになり、オブジェクトとクラス間
でprivateメンバへのアクセスが可能となる
主にクラスを生成する役目として利用する(ファク
トリー)
81. 第1部:JavaとScala - クラスとオブジェクト
コンパニオンオブジェクトの定義
class MyName(name: String) {
println("Hello World! %s".format(name))
}
object MyName {
// applyの定義が必要
def apply(name: String) = new MyName(name)
}
MyName.apply("Name") // Hello World! TEST
MyName("Name") // applyは少し特殊で、省略可能
Scala
82. 第1部:JavaとScala - クラスとオブジェクト
Scala
ケースクラスの定義
いくつかの便利なメソッドやコンパニオンオブジェ
クトが自動的に生成される
コンストラクタに対するパターンマッチが利用出来
たり、値を保持するDTOとしての定義に利用
case class MyClass(name: String) {
println("Hello World! %s".format(name))
}
83. 第1部:JavaとScala
● Scalaって?
● REPL
● 変数宣言
● 制御構文/コレクションのライブラリ
● Tuple
● 無名関数
● クラスとオブジェクト
● Option型
● 引数について(+部分適用とカリー化)
● クロージャ
87. Java 第1部:JavaとScala - Option型
Mapを使った例
下記はコンパイルエラーにならず、実行してもエラ
ーにはならない
final Map<String, String> pilotMap = new HashMap<String, String>() {{
put("1", "ガンダム");
put("2", null); }};
System.out.println(pilotMap.get("1").length());
88. Java 第1部:JavaとScala - Option型
Mapを使った例
しかし、key:2を指定すると、実行時にヌルポが発
生する(当たり前)
final Map<String, String> pilotMap = new HashMap<String, String>() {{
put("1", "ガンダム");
put("2", null); }};
System.out.println(pilotMap.get("2").length());
89. Java 第1部:JavaとScala - Option型
Mapを使った例
しかし、key:3を指定しても、実行時にヌルポが発
生する(当たり前)
final Map<String, String> pilotMap = new HashMap<String, String>() {{
put("1", "ガンダム");
put("2", null); }};
System.out.println(pilotMap.get("3").length());
90. Java 第1部:JavaとScala - Option型
Mapを使った例
さて、key:2とkey:3指定した時、どちらも実行時に
ヌルポで落ちたが
● 値がなくてヌルポが発生したのか
● keyがなくてヌルポが発生したのか
一見どちらが原因でエラーとなったのか不明
91. Java 第1部:JavaとScala - Option型
Mapを使った例
対応するとしたら下記の様な対応か?
・keyの存在チェック
・nullチェックする
しかし、そもそもコンパイラは、これらの対応がさ
れているか分からない
92. Java 第1部:JavaとScala - Option型
Mapを使った例
final Map<String, String> pilotMap = new HashMap<String, String>() {{
put("1", "ガンダム");
put("2", null); }};
if (pilotMap.containsKey("1") && pilotMap.get("1") != null)
System.out.println(pilotMap.get("1").length());
if (pilotMap.containsKey("2") && pilotMap.get("2") != null)
System.out.println(pilotMap.get("2").length());
if (pilotMap.containsKey("3") && pilotMap.get("3") != null)
System.out.println(pilotMap.get("3").length());
93. Scala 第1部:JavaとScala - Option型
Mapを使った例
こうしたコンパイルチェック時に検出できない潜在
バグを極力なくしていくのが、ScalaのOption型(だ
と思っている)
では実際にどうやって先ほどの問題を解決するのか
94. Scala 第1部:JavaとScala - Option型
Mapを使った例
そこでパターンマッチ(match~case)を使う
Option型は、値が存在する場合はSome型、値が存
在しない場合None型を返すため、パターンマッチで
それらを検出する
95. Scala 第1部:JavaとScala - Option型
Mapを使った例
val pilotMap: Map[String, String] = Map("1" -> "ガンダム", "2" -> null)
def checkValue(key: String) = pilotMap.get(key) match {
case Some(v) if v == null => "nullです"
case Some(v) => "%sです" format v
case None => "値はありません"
}
println(checkValue("1")) // ガンダムです
println(checkValue("2")) // nullです
println(checkValue("3")) // 値はありません
96. Scala 第1部:JavaとScala - Option型
Mapを使った例
値にnullが入るのは仕方のないことなので、やはり
nullチェックは必要
しかし、Mapのkeyが存在しない場合については、
Noneが帰ってくるため、明示的な実装が可能になる
97. Scala 第1部:JavaとScala - Option型
Mapを使った例
もちろん、Javaでもkeyと値が存在するかどうかの
チェックメソッドを一つ作れば良い話だけど、標準
で安全なプログラミングをサポートしているという
感じが良い
98. 第1部:JavaとScala
● Scalaって?
● REPL
● 変数宣言
● 制御構文/コレクションのライブラリ
● Tuple
● 無名関数
● クラスとオブジェクト
● Option型
● 引数について(+部分適用とカリー化)
● クロージャ
100. Scala 第1部:JavaとScala - 引数について(+部分適用とカリー化)
引数について- 変数名指定
def f(arg1: String,arg2: String): String = {
"%sと%s".format(arg1,arg2)
}
println(f(arg1 = "引数①",arg2 = "引数②"))
---実行結果---
引数①と引数②
101. Scala 第1部:JavaとScala - 引数について(+部分適用とカリー化)
引数について- 可変長引数
def f(args: String*) = args foreach println
f("引数①","引数②")
---実行結果---
引数①
引数②
102. Scala 第1部:JavaとScala - 引数について(+部分適用とカリー化)
引数について- 可変長引数
引数が可変長引数の場合、コレクションも渡すこと
ができる(ただし、_*をつける必要あり)
def f(args: String*) = args foreach println
f(List("引数①","引数②"): _*)
---実行結果---
{同じ}
103. Scala 第1部:JavaとScala - 引数について(+部分適用とカリー化)
引数について- 初期値
def f(arg1: String,arg2: String = "引数②"): String = {
"%sと%s".format(arg1,arg2)
}
println(f("引数①"))
---実行結果---
引数①と引数②
104. Scala 第1部:JavaとScala - 引数について(+部分適用とカリー化)
引数について- 初期値
これはコンパイラがどの引数に入れたら良いのか分
からないので、コンパイルエラーとなる
def f(arg1: String = "引数①",arg2: String): String = {
"%sと%s".format(arg1,arg2)
}
println(f("引数②"))
105. Scala 第1部:JavaとScala - 引数について(+部分適用とカリー化)
引数について- 初期値
変数名指定すればOK
def f(arg1: String = "引数①",arg2: String): String = {
"%sと%s".format(arg1,arg2)
}
println(f(arg2 = "引数②"))
---実行結果---
引数①と引数②
106. Scala 第1部:JavaとScala - 引数について(+部分適用とカリー化)
引数について- 初期値
指定した値を優先する
def f(arg1: String = "引数①",arg2: String): String = {
"%sと%s".format(arg1,arg2)
}
println(f(arg1 = "引数③",arg2 = "引数②"))
---実行結果---
引数③と引数②
108. Scala 第1部:JavaとScala - 引数について(+部分適用とカリー化)
部分適用
def f1(arg1: String, arg2: String): String = "%sと%s".format(arg1, arg2)
val f2 = f1("引数①", _:String) // 引数1を固定して関数オブジェクトを作成
println(f2("引数②"))
val f3 = f1(_:String, "引数②") // 引数2を固定して関数オブジェクトを作成
println(f3("引数①"))
---実行結果---
引数①と引数②
引数①と引数②
110. Scala 第1部:JavaとScala - 引数について(+部分適用とカリー化)
カリー化
// メソッドを定義
def method(arg1: String, arg2: String): String = "%sと%s".format(arg1, arg2)
※当該メソッドの処理内容
methodは二つの引数を取り、それぞれの値を"%sと%s"にバインドStringInterpolationし、
String型として返します。
111. Scala 第1部:JavaとScala - 引数について(+部分適用とカリー化)
カリー化
// メソッドを定義
def method(arg1: String, arg2: String): String = "%sと%s".format(arg1, arg2)
val functionObject = method _ // メソッドを関数オブジェクト化
112. Scala 第1部:JavaとScala - 引数について(+部分適用とカリー化)
カリー化
// メソッドを定義
def method(arg1: String, arg2: String): String = "%sと%s".format(arg1, arg2)
val functionObject = method _ // メソッドを関数オブジェクト化
val curreidFunction = functionObject.curried // 関数オブジェクトをカリー化
113. Scala 第1部:JavaとScala - 引数について(+部分適用とカリー化)
カリー化
// メソッドを定義
def method(arg1: String, arg2: String): String = "%sと%s".format(arg1, arg2)
val functionObject = method _ // メソッドを関数オブジェクト化
val curreidFunction = functionObject.curried // 関数オブジェクトをカリー化
// 第1引数を指定し、第2引数を引数として受け取る関数オブジェクトを作成
val function1 = curreidFunction("引数①")
114. Scala 第1部:JavaとScala - 引数について(+部分適用とカリー化)
カリー化
// メソッドを定義
def method(arg1: String, arg2: String): String = "%sと%s".format(arg1, arg2)
val functionObject = method _ // メソッドを関数オブジェクト化
val curreidFunction = functionObject.curried // 関数オブジェクトをカリー化
// 第1引数を指定し、第2引数を引数として受け取る関数オブジェクトを作成
val function1 = curreidFunction("引数①")
println(function1("引数②-1")) // 第2引数を指定して処理を実行
---実行結果---
引数①と引数②-1
115. Scala 第1部:JavaとScala - 引数について(+部分適用とカリー化)
カリー化
初めからカリー化されたメソッドを定義した場合
// メソッドを定義
def method(arg1: String) = (arg2: String) => "%sと%s".format(arg1, arg2)
// 第1引数を指定し、第2引数を引数として受け取る関数オブジェクトを作成
val function1 = method("引数①")
println(function1("引数②-1")) // 第2引数を指定して処理を実行
---実行結果---
引数①と引数②-1
116. Scala 第1部:JavaとScala - 引数について(+部分適用とカリー化)
カリー化
いっぺんに実行することも可能
// メソッドを定義
def method(arg1: String) = (arg2: String) => "%sと%s".format(arg1, arg2)
println(method("引数①")("引数②-1"))
---実行結果---
引数①と引数②-1
117. 第1部:JavaとScala
● Scalaって?
● REPL
● 変数宣言
● 制御構文/コレクションのライブラリ
● Tuple
● 無名関数
● クラスとオブジェクト
● Option型
● 引数について(+部分適用とカリー化)
● クロージャ
118. 第1部:JavaとScala - クロージャScala
クロージャ
まずは静的スコープのお話
ブロックAの変数xとブロックBの変数xは同じ名前をもつがブロックが異なる為別のも
のである。またBの中ではCのようにさらに内側の変数を見ることができず、逆にCから
はBのxとCのyが見える※Wikipediaから引用
A {var x} // A内のみ参照可能
B {
var x // BとCから参照可能で、A内のxとは別物
C {var y} // C内のみ参照可能
}
119. Scala 第1部:JavaとScala - クロージャ
クロージャ
よくある例
var count = 100
def counter() = {
var count = 200
() => {
count += 10
count
}
}
val c1 = counter()
println(c1())
println(c1())
120. Scala 第1部:JavaとScala - クロージャ
クロージャ
この場合、無名関数()が参照するcountは、直近スコ
ープにある200で初期化されたものが利用される
var count = 100
def counter() = {
var count = 200
() => {
count += 10
count
}
}
124. 第2部:Play Framework
● Play Frameworkって?
● インストール
● プロジェクトの作成・起動
● リクエスト→レスポンスの流れ
● ルーティング
● Database接続設定
● Evolution機能
● DB操作
● Formの定義
● まとめ(JavaとScala比べ)
125. 第2部:Play Framework
Play Frameworkって?
JavaとScalaどちらでも実装出来るWebアプリケー
ションフレームワーク
・MVC
・ホットリローディングあり
・ステートレス(セッション無し)
130. 第2部:Play Framework
● Play Frameworkって?
● インストール
● プロジェクトの作成・起動
● リクエスト→レスポンスの流れ
● ルーティング
● Database接続設定
● Evolution機能
● DB操作
● Formの定義
● まとめ(JavaとScala比べ)
131. Scala Java 第2部:Play Framework
インストール
2.2まではPlayのzipをダウンロードして、$PATHに
通すだけで良かった
2.3からは下記サイトからActivatorを取得し、$PATH
に追加するか、「brew install typesafe-sctivator」す
る
Playframework
http://www.playframework.com/
132. 第2部:Play Framework
● Play Frameworkって?
● インストール
● プロジェクトの作成・起動
● リクエスト→レスポンスの流れ
● ルーティング
● Database接続設定
● Evolution機能
● DB操作
● Formの定義
● まとめ(JavaとScala比べ)
133. Scala Java 第2部:Play Framework
プロジェクトの作成、起動
まずは「activator new」コマンドを実行する
$ activator new
~割愛~
134. Java 第2部:Play Framework
プロジェクトの作成、起動
作成するプロジェクトの形式を選択する
例ではScalaを選択
Scala
~割愛~
Choose from these featured templates or enter a template name:
1) minimal-java
2) minimal-scala
3) play-java
4) play-scala
(hit tab to see a list of all templates)
> 4
135. 第2部:Play Framework
プロジェクトの作成、起動
アプリケーション名を入力する
例では「My App」を入力
Scala Java
~割愛~
Enter a name for your application (just press enter for 'play-scala')
> MyApp
OK, application "MyApp" is being created using the "play-scala" template.
~割愛~
136. Scala Java
第2部:Play Framework
プロジェクトの作成、起動
作成された「My App」ディレクトリに移動し
「activator run」コマンドを実行して移動
$ cd MyApp/
$ activator run
~割愛~
[info] play - Listening for HTTP on /0:0:0:0:0:0:0:0:9000
137. 第2部:Play Framework
● Play Frameworkって?
● インストール
● プロジェクトの作成・起動
● リクエスト→レスポンスの流れ
● ルーティング
● Database接続設定
● Evolution機能
● DB操作
● Formの定義
● まとめ(JavaとScala比べ)
139. Scala Java 第2部:Play Framework
リクエスト→レスポンスの流れ
すると、「conf/routes」ファイルに記載されている下記の内容を
もとに、呼び出す処理を解決する
GET / controllers.Application.index
→ app/controllers/Application.java
→ app/controllers/Application.scala
のindexメソッド
140. Java 第2部:Play Framework
リクエスト→レスポンスの流れ
JavaのControllerはこのような記述
public static Result index() {
Ok(index.render("Hello World!"));
}
141. Scala 第2部:Play Framework
リクエスト→レスポンスの流れ
ScalaのContrllerはこの様な記述
def index() = Action { implicit request =>
Ok(html.index("Hello World!"))
}
142. Scala Java 第2部:Play Framework
リクエスト→レスポンスの流れ
次に、Okメソッドに指定したページをレスポンスと
して返す
app/views/index.scala.html
143. Scala Java 第2部:Play Framework
app/views/index.scala.html
画面の定義はJavaとScalaほぼ同じ
@(text: String)
@main("indexページ") {
<p>@text</p>
}
144. Scala Java 第2部:Play Framework
app/views/index.scala.html
@はじまりの箇所はすべてScalaのロジック
@(text: String)
@main("indexページ") {
<p>@text</p>
}
145. Scala Java 第2部:Play Framework
app/views/index.scala.html
さらにここからmainと定義されたページテンプレー
トを呼び出す
@main("indexページ") {}
→ app/views/main.scala.html
146. Scala Java 第2部:Play Framework
リクエスト→レスポンスの流れ
app/views/main.scala.html
contentに先述のindexページが格納されている
@(title: String)(content: Html)
<html>
<head>
<title>@title</title>
</head>
<body>
@content
</body>
</html>
147. 第2部:Play Framework
● Play Frameworkって?
● インストール
● プロジェクトの作成・起動
● リクエスト→レスポンスの流れ
● ルーティング
● Database接続設定
● Evolution機能
● DB操作
● Formの定義
● まとめ(JavaとScala比べ)
148. Scala Java 第2部:Play Framework
ルーティング
リクエストパラメータは下記の様に指定する
View
<a href="@routes.Application.index(1)">トップ</a>
conf/routes
GET / controllers.Application.index(p: Int)
149. Java 第2部:Play Framework
ルーティング
リクエストパラメータは下記の様に指定する
Controller
public static Result index(int p) {
Ok(index.render("Hello World!"));
}
150. Scala 第2部:Play Framework
ルーティング
リクエストパラメータは下記の様に指定する
Controller
def index(p: Int) = Action { implicit request =>
Ok(html.index("Hello World!"))
}
151. Scala Java 第2部:Play Framework
ルーティング
下記の様に記述することで、初期値を指定でき
る
conf/routes
GET / controllers.Application.index(p: Int ?= 1)
152. Scala Java 第2部:Play Framework
ルーティング
下記の様に記述することで、リクエストパラメータ
をURLの一部に指定できる
conf/routes
GET /:p controllers.Application.index(p: Int)
URL
http://localhost:9000/1
153. Scala Java 第2部:Play Framework
ルーティング
リバースルーティングも可能(初期指定済み)
conf/routes
GET /assets/*file controllers.Assets.at(path="/public", file)
View
<script type="text/javascript"
src="@routes.Assets.at("javascripts/bootstrap.min.js")"></script>
154. 第2部:Play Framework
● Play Frameworkって?
● インストール
● プロジェクトの作成・起動
● リクエスト→レスポンスの流れ
● ルーティング
● Database接続設定
● Evolution機能
● DB操作
● Formの定義
● まとめ(JavaとScala比べ)
155. Scala Java 第2部:Play Framework
Database接続設定
Database接続を行うには、下記ファイルにエンドポ
イントを記述する
conf/application.conf
156. Scala Java 第2部:Play Framework
Database接続設定
PlayにはH2が組み込まれており、下記の記述を有効
化するだけで利用できる
db.default.driver=org.h2.Driver
db.default.url="jdbc:h2:mem:play"
db.default.user=sa
db.default.password=""
157. Scala Java 第2部:Play Framework
Database接続設定
MySQLを利用する場合
下記の様にエンドポイントを記述し...
db.default.driver=com.mysql.jdbc.Driver
db.default.url="jdbc:mysql://localhost:3306/{DATABASE_NAME}
db.default.user={USER_NAME}
db.default.password="{PASS_WORD}"
158. Scala Java 第2部:Play Framework
Database接続設定
MySQLを利用する場合
Configuration Fileに下記の様な記述を行う
build.sbt
val appDependencies = Seq(
// Add your project dependencies here,
"mysql" % "mysql-connector-java" % "5.1.20"
)
159. Scala Java 第2部:Play Framework
Database接続設定
Configuration Fileはsbt※のものなので詳細は割愛
※簡単に言うと、必要なライブラリを管理出来るビ
ルドツール
160. 第2部:Play Framework
● Play Frameworkって?
● インストール
● プロジェクトの作成・起動
● リクエスト→レスポンスの流れ
● ルーティング
● Database接続設定
● Evolution機能
● DB操作
● Formの定義
● まとめ(JavaとScala比べ)
161. Scala Java 第2部:Play Framework
Revolution機能
play runすると、
conf¥evolutions¥default¥1.sql
というファイルに定義されたSQLを実行してくれる。
開発中のDB定義マイグレーションに便利。
162. Scala Java 第2部:Play Framework
Evolution機能
http://localhost:9000/ にアクセスすると、下記
の様にDBを構築するスクリプトが表示される
ので、「Apply this script now!」を押下する。
※スクリプトはdefault¥1.sqlの中身。
164. 第2部:Play Framework
● Play Frameworkって?
● インストール
● プロジェクトの作成・起動
● リクエスト→レスポンスの流れ
● ルーティング
● Database接続設定
● Evolution機能
● DB操作
● Formの定義
● まとめ(JavaとScala比べ)
165. Scala Java 第2部:Play Framework
DB操作
親テーブル(1)と子テーブル(N)という2つのテ
ーブルが存在するデータベースがあったとする。
各テーブルからデータを登録・読取・更新・削
除する場合の実装方法例を記載する。
166. Java 第2部:Play Framework
DB操作
Java版では、Ebeanを利用(Playに同梱済み)。
conf/application.conf
に
ebean.default="models.*"
を記述してモデルクラス格納パッケージを指定する。
Ebean
http://www.avaje.org/ebean/documentation.html
168. Java 第2部:Play Framework
DB操作- 親テーブル定義例
@Entity
public class Parent extends Model {
private static final long serialVersionUID = 1L;
@Id
public Long id;
@Required
public String name;
@OneToMany(cascade = CascadeType.ALL, mappedBy = "parent")
public List<Child> child = new ArrayList<Child>();
protected Timestamp createDate;
@Version
protected Timestamp updateDate;
public static Finder<Long,Parent> find = new Finder<Long,Parent>(Long.class, Parent.class);
}
169. Java 第2部:Play Framework
DB操作- 子テーブル定義例
@Entity
public class Child extends Model {
private static final long serialVersionUID = 1L;
@Id
public Long id;
@Required
public String name;
@ManyToOne
@JoinColumn(name = "child")
public Parent parent;
protected Timestamp createDate;
@Version
protected Timestamp updateDate;
public static Finder<Long,Child> find = new Finder<Long,Child>(Long.class, Child.class);
}
171. Java 第2部:Play Framework
DB操作
実際のデータ取得は、先のモデルクラスに定義した
public static Finder<Long,Parent> find
= new Finder<Long,Parent>(Long.class, Parent.class);
を使用する。
172. Java 第2部:Play Framework
DB操作
データ取得例
List<Parent> parentList = Parent.find.findList();
List<Parent> parentList = Parent.find.where().eq(“name”, “omiend").findList();
List<Parent> parentList = Parent.find.setFirstRow(0).setMaxRows(10).findList();
int rowCount = Parent.find.findRowCount();
174. 第2部:Play Framework
DB操作
Configuration Fileに下記の様な記述を行う
build.sbt
val appDependencies = Seq(
// Add your project dependencies here,
anorm
)
Scala
175. 第2部:Play Framework
DB操作
モデルクラスを用意する
下記は先述のケースクラスとオブジェクト(コンパニオンオブジェクト)を一緒に
ParentModel.scalaに定義した例
DDLはオブジェクト内に定義して行く事となる
case class Parent(id: Pk[Long] = NotAssigned
,name: String
,var createDate: Option[Date]
,var updateDate: Option[Date]) {
}
object Parent {
}
Scala
176. 第2部:Play Framework
Scala
DB操作
取得したデータをモデルにマッピングする為の定義
をする
object Parent {
val simple = {
get[Pk[Long]]("parent.id") ~
get[String]("parent.name") ~
get[Date]("parent.create_date") ~
get[Date]("parent.update_date") map {
case id~name~createDate~updateDate => Parent(id, name, Option(createDate), Option(updateDate))
}
}
}
177. 第2部:Play Framework
DB操作
DDLを定義する
object Parent {
def findByName(name: String): Seq[Parent] = {
DB.withConnection { implicit connection =>
SQL("""
select *
from parent
where name = {name}
""").on(
'name -> name
).as(Parent.simple *)
}}}
Scala
179. 第2部:Play Framework
● Play Frameworkって?
● インストール
● プロジェクトの作成・起動
● リクエスト→レスポンスの流れ
● ルーティング
● Database接続設定
● Evolution機能
● DB操作
● Formの定義
● まとめ(JavaとScala比べ)
180. Java
第2部:Play Framework
Formの定義
Javaの場合、下記の様にモデルクラスを利用して
Formを作成する
Form<Parent> parentForm = form(Parent.class);
return ok(create.render(parentForm));
181. 第2部:Play Framework
Formの定義
Scalaの場合、下記の様なモデルへのマッピングオブ
ジェクトを作成する
val parentForm = Form(
mapping(
"id" -> ignored(NotAssigned: Pk[Long]),
"name" -> nonEmptyText,
"createDate" -> optional(date("yyyy-MM-dd")),
"updateDate" -> optional(date("yyyy-MM-dd"))
)(Parent.apply)(Parent.unapply)
)
Ok(html.create(parentForm))
Scala
182. Scala Java 第2部:Play Framework
Formの定義- Viewの定義例
@(parentForm: Form[Parent])
@import helper._
@main() {
@form(routes.Application.insertParent()) {
<fieldset>
@inputText(parentForm("name"))
</fieldset>
<div class="actions">
<input type="submit" value="登録"> or
<a href="@routes.Application.index()" class="btn">Cancel</a>
</div>
}
}
184. Scala Java 第2部:Play Framework
Formの定義- Viewの定義例
POST先のroutes設定はこんな感じ
conf/routes
POST /insertParent
controller.Application.insertParent
185. 第2部:Play Framework
● Play Frameworkって?
● インストール
● プロジェクトの作成・起動
● リクエスト→レスポンスの流れ
● ルーティング
● Database接続設定
● Evolution機能
● DB操作
● Formの定義
● まとめ(JavaとScala比べ)
186. Scala Java 第2部:Play Framework
まとめ(Java版とScala版比べ)
● Viewの定義方法はどちらも同じ
● EbeanとAnormでは、Ebeanの方が実装が容易
● Formの定義もJava版の方が容易
● Java版でも、Javaでの実装はControllerとModelだ
けで、他はすべてScalaで実装する必要がある
● ビルドはScalaのsbtが利用されるので、その辺の
知識は必須