Ipros techmeetup 20131218_scala_handson

104
未未未未未未未未 Scala 未未未未未未未未 未未未未

description

2013/12/18に株式会社イプロスにて開催されたScalaハンズオン勉強会の後半パートで使用したスライドです。

Transcript of Ipros techmeetup 20131218_scala_handson

Page 1: Ipros techmeetup 20131218_scala_handson

未経験者のための Scala

株式会社イプロス 本多陽平

Page 2: Ipros techmeetup 20131218_scala_handson

2 COPYRIGHT © 2013 IPROS CORPORATION ALL RIGHTS RESERVED

後半パート

Scala の真髄に少しだけ触れる

Page 3: Ipros techmeetup 20131218_scala_handson

3 COPYRIGHT © 2013 IPROS CORPORATION ALL RIGHTS RESERVED

自己紹介

• 本多陽平

• 2012 年 2 月イプロス入社

• Java 歴 1 年半→ Scala 歴半年

• 現在は広告系サービスの開発を担当

• 去年登山を始めました

• サッカーを観たり、梅干しをつけたり、温泉に行ったり、が趣味

Page 4: Ipros techmeetup 20131218_scala_handson

4 COPYRIGHT © 2013 IPROS CORPORATION ALL RIGHTS RESERVED

後半パートについて

後半パートでは、 Scala の• オブジェクト指向要素• 関数プログラミング要素の両側面に簡単に触れるとともに、SBT を使ったビルドについても触れます。

Page 5: Ipros techmeetup 20131218_scala_handson

5 COPYRIGHT © 2013 IPROS CORPORATION ALL RIGHTS RESERVED

アジェンダ1. Scala でオブジェクト指向

1. クラスハンズオン

2. トレイト2. Scala で関数プログラミング

1. 高階関数ハンズオン

3. SBT によるビルド1. コンパイル

ハンズオン2. 実行

ハンズオン3. パッケージング

ハンズオン

Page 6: Ipros techmeetup 20131218_scala_handson

6 COPYRIGHT © 2013 IPROS CORPORATION ALL RIGHTS RESERVED

前置き

Scala の言語仕様を網羅的に説明しているわけではないので、ご了承下さい

Page 7: Ipros techmeetup 20131218_scala_handson

7 COPYRIGHT © 2013 IPROS CORPORATION ALL RIGHTS RESERVED

サンプルコードについて

後半パートで使用するサンプルコードは以下にアップロードしてあります。

イプロス開発ブログhttp://ipros-creators.tumblr.com/※ 「イプロス 開発」で検索

Page 8: Ipros techmeetup 20131218_scala_handson

8 COPYRIGHT © 2013 IPROS CORPORATION ALL RIGHTS RESERVED

オブジェクト指向要素編

Scala でオブジェクト指向

Page 9: Ipros techmeetup 20131218_scala_handson

9 COPYRIGHT © 2013 IPROS CORPORATION ALL RIGHTS RESERVED

クラス

Scala は関数型言語であり、オブジェクト指向言語でもあるので、クラスを使えます

Page 10: Ipros techmeetup 20131218_scala_handson

10 COPYRIGHT © 2013 IPROS CORPORATION ALL RIGHTS RESERVED

クラス > コンストラクタ

クラス定義

scala> class Mountain (name: String) { | val printName = "Mt. " + name | def this() = { | this("Unknown") } }defined class Mountain

C-1

Page 11: Ipros techmeetup 20131218_scala_handson

11 COPYRIGHT © 2013 IPROS CORPORATION ALL RIGHTS RESERVED

クラス > コンストラクタ > 基本コンストラクタ

インスタンスが生成される度に呼ばれます

scala> class Mountain (name: String) { | val printName = "Mt. " + name | def this() = { | this("Unknown") } }defined class Mountain

C-1

Page 12: Ipros techmeetup 20131218_scala_handson

12 COPYRIGHT © 2013 IPROS CORPORATION ALL RIGHTS RESERVED

クラス > コンストラクタ > クラスパラメータ

クラスパラメータは基本コンストラクタのパラメータとなります

scala> class Mountain (name: String) { | val printName = "Mt. " + name | def this() = { | this("Unknown") } }defined class Mountain

C-1

Page 13: Ipros techmeetup 20131218_scala_handson

13 COPYRIGHT © 2013 IPROS CORPORATION ALL RIGHTS RESERVED

クラス > コンストラクタ > 補助コンストラクタ

this キーワードをつけると、補助コンストラクタとなります

scala> class Mountain (name: String) { | val printName = "Mt. " + name | def this() = { | this("Unknown") } }defined class Mountain

※ 必ず初めに基本コンストラクタを呼ぶ必要がある

C-1

Page 14: Ipros techmeetup 20131218_scala_handson

14 COPYRIGHT © 2013 IPROS CORPORATION ALL RIGHTS RESERVED

クラス > コンストラクタ

基本コンストラクタでインスタンス生成

scala> class Mountain (name: String) { | val printName = "Mt. " + name | def this() = { | this("Unknown") } }defined class Mountain

scala> val fuji = new Mountain("Fuji")fuji: Mountain = Mountain@23e9436c

C-1

Page 15: Ipros techmeetup 20131218_scala_handson

15 COPYRIGHT © 2013 IPROS CORPORATION ALL RIGHTS RESERVED

クラス > コンストラクタ

名前は?

scala> class Mountain (name: String) { | val printName = "Mt. " + name | def this() = { | this("Unknown") } }defined class Mountain

scala> val fuji = new Mountain("Fuji")fuji: Mountain = Mountain@23e9436c

scala> fuji. tab キーで補完

C-1

Page 16: Ipros techmeetup 20131218_scala_handson

16 COPYRIGHT © 2013 IPROS CORPORATION ALL RIGHTS RESERVED

クラス > コンストラクタ

名前は?

scala> class Mountain (name: String) { | val printName = "Mt. " + name | def this() = { | this("Unknown") } }defined class Mountain

scala> val fuji = new Mountain("Fuji")fuji: Mountain = Mountain@23e9436c

scala> fuji.asInstanceOf isInstanceOf printName toString

↑ 可視性はデフォルトで Public

C-1

Page 17: Ipros techmeetup 20131218_scala_handson

17 COPYRIGHT © 2013 IPROS CORPORATION ALL RIGHTS RESERVED

クラス > コンストラクタ

名前は?

scala> fuji.asInstanceOf isInstanceOf printName toString

scala > fuji.printNameres0: String = Mt. Fuj

C-1

Page 18: Ipros techmeetup 20131218_scala_handson

18 COPYRIGHT © 2013 IPROS CORPORATION ALL RIGHTS RESERVED

クラス > コンストラクタ

補助コンストラクタでインスタンス生成

scala> class Mountain (name: String) { | val printName = "Mt. " + name | def this() = { | this("Unknown") } }defined class Mountain

scala> val nanashi = new Mountain()nanashi: Mountain = Mountain@233a4b09

C-1

Page 19: Ipros techmeetup 20131218_scala_handson

19 COPYRIGHT © 2013 IPROS CORPORATION ALL RIGHTS RESERVED

クラス > コンストラクタ

名前のない山ができました

scala> class Mountain (name: String) { | val printName = "Mt. " + name | def this() = { | this("Unknown") } }defined class Mountain

scala> val nanashi = new Mountain()nanashi: Mountain = Mountain@233a4b09

scala> nanashi.printNameres0: String = Mt. Unknown

C-1

Page 20: Ipros techmeetup 20131218_scala_handson

20 COPYRIGHT © 2013 IPROS CORPORATION ALL RIGHTS RESERVED

クラス > コンストラクタ

クラスパラメータがフィールドにありません

scala> fuji.asInstanceOf isInstanceOf printName toString

C-1

Page 21: Ipros techmeetup 20131218_scala_handson

21 COPYRIGHT © 2013 IPROS CORPORATION ALL RIGHTS RESERVED

クラス > コンストラクタ

val をつけて定義するとフィールドになります

scala> class Mountain (val name: String)defined class Mountain

C-2

Page 22: Ipros techmeetup 20131218_scala_handson

22 COPYRIGHT © 2013 IPROS CORPORATION ALL RIGHTS RESERVED

クラス > コンストラクタ

name にアクセスできました

scala> class Mountain (val name: String)defined class Mountain

scala> val fuji = new Mountain("Fuji")fuji: Mountain = Mountain@55a4221f

scala> fuji.asInstanceOf isInstanceOf name toString

scala> fuji.nameres1: String = Fuji

C-2

Page 23: Ipros techmeetup 20131218_scala_handson

23 COPYRIGHT © 2013 IPROS CORPORATION ALL RIGHTS RESERVED

クラス > コンストラクタ

1. 基本コンストラクタ

2. 補助コンストラクタ

3. クラスパラメータ1. フィールド指定なし

2. フィールド指定あり

ここまでのまとめ

class Mountain { val name = "Fuji" }

class Mountain (name: String)

class Mountain (val name: String)

class Mountain (val name: String) { def this() = { this("Unknown") }}

Page 24: Ipros techmeetup 20131218_scala_handson

24 COPYRIGHT © 2013 IPROS CORPORATION ALL RIGHTS RESERVED

クラス > メソッド

メソッド

Page 25: Ipros techmeetup 20131218_scala_handson

25 COPYRIGHT © 2013 IPROS CORPORATION ALL RIGHTS RESERVED

クラス > メソッド

メソッド定義は簡単で、関数定義と同じです

scala> class Mountain (val name: String) { | def erupt = { println("erupted!") }}defined class Mountain

※ 呼び方(ということが多いです) 関数単体 = 関数 クラス内の関数 = メソッド

C-3

Page 26: Ipros techmeetup 20131218_scala_handson

26 COPYRIGHT © 2013 IPROS CORPORATION ALL RIGHTS RESERVED

クラス > メソッド

呼び出し

scala> class Mountain (val name: String) { | def erupt = { println("erupted!") }}defined class Mountain

scala> val vesuvius = new Mountain("Vesuvius")vesuvius: Mountain = Mountain@6f9c2c4

scala> vesuvius.erupterupted!

C-3

Page 27: Ipros techmeetup 20131218_scala_handson

27 COPYRIGHT © 2013 IPROS CORPORATION ALL RIGHTS RESERVED

クラス > ハンズオン

噴火する度に標高が下がる山

を作ってみましょう

Page 28: Ipros techmeetup 20131218_scala_handson

28 COPYRIGHT © 2013 IPROS CORPORATION ALL RIGHTS RESERVED

クラス > ハンズオン > コーディング例

こんな感じ

scala> class Mountain (val name: String, var alt: Int) { | def erupt = { | alt -= 100 | println("erupted! alt = " + alt) }}defined class Mountain

Page 29: Ipros techmeetup 20131218_scala_handson

29 COPYRIGHT © 2013 IPROS CORPORATION ALL RIGHTS RESERVED

クラス > ハンズオン > コーディング例 > 動作確認

動かしてみましょう

scala> class Mountain (val name: String, var alt: Int) { | def erupt = { | alt -= 100 | println("erupted! alt = " + alt) }}defined class Mountain

scala> val vesuvius = new Mountain("Vesuvius", 1281)vesuvius: Mountain = Mountain@4e3ecc02

scala> vesuvius.erupterupted! alt = 1181

scala> vesuvius.erupterupted! alt = 1081

← 下がってる

← 下がってる

Page 30: Ipros techmeetup 20131218_scala_handson

30 COPYRIGHT © 2013 IPROS CORPORATION ALL RIGHTS RESERVED

トレイト

実装の定義も可能な Java のインターフェース

という感じです

Page 31: Ipros techmeetup 20131218_scala_handson

31 COPYRIGHT © 2013 IPROS CORPORATION ALL RIGHTS RESERVED

トレイト

trait キーワードをつけて定義します

scala> trait Mountain { | def getName: String | def getAlt: Int | def getInfo = { | println(getName + getAlt) }}defined trait Mountain

T-1

Page 32: Ipros techmeetup 20131218_scala_handson

32 COPYRIGHT © 2013 IPROS CORPORATION ALL RIGHTS RESERVED

トレイト

メソッド宣言

scala> trait Mountain { | def getName: String | def getAlt: Int | def getInfo = { | println(getName + getAlt) }}defined trait Mountain

T-1

Page 33: Ipros techmeetup 20131218_scala_handson

33 COPYRIGHT © 2013 IPROS CORPORATION ALL RIGHTS RESERVED

トレイト

メソッド定義

scala> trait Mountain { | def getName: String | def getAlt: Int | def getInfo = { | println(getName + getAlt) }}defined trait Mountain

T-1

Page 34: Ipros techmeetup 20131218_scala_handson

34 COPYRIGHT © 2013 IPROS CORPORATION ALL RIGHTS RESERVED

トレイト > 具象クラス

extends して作ります = ミックスイン

scala> trait Mountain { | def getName: String | def getAlt: Int | def getInfo = { | println(getName + getAlt) }}defined trait Mountain

scala> class Fuji extends Mountain { | def getName = "Fuji" | def getAlt = 3776 }defined class Fuji

T-2

Page 35: Ipros techmeetup 20131218_scala_handson

35 COPYRIGHT © 2013 IPROS CORPORATION ALL RIGHTS RESERVED

トレイト > 具象クラス

こうした方が親切です( Scala 文化的にはつけないようですが)

scala> class Fuji extends Mountain { | override def getName = "Fuji" | override def getAlt = 3776 }defined class Fuji

T-3

Page 36: Ipros techmeetup 20131218_scala_handson

36 COPYRIGHT © 2013 IPROS CORPORATION ALL RIGHTS RESERVED

トレイト > 抽象フィールド

val をつけてフィールド宣言

scala> trait Mountain { | val name: String | val alt: Int | def getInfo = { | println(name + alt) }}defined trait Mountain

T-4

Page 37: Ipros techmeetup 20131218_scala_handson

37 COPYRIGHT © 2013 IPROS CORPORATION ALL RIGHTS RESERVED

トレイト > 抽象フィールド > 具象クラス

具象クラスの作成

scala> trait Mountain { | val name: String | val alt: Int | def getInfo = { | println(name + alt) }}defined trait Mountain

scala> class Fuji extends Mountain { | val name = "Fuji" | val alt = 3776 }defined class Fuji

T-5

Page 38: Ipros techmeetup 20131218_scala_handson

38 COPYRIGHT © 2013 IPROS CORPORATION ALL RIGHTS RESERVED

トレイト

トレイトは複数ミックスインできます

Page 39: Ipros techmeetup 20131218_scala_handson

39 COPYRIGHT © 2013 IPROS CORPORATION ALL RIGHTS RESERVED

トレイト > 複数トレイトのミックスイン

1 つ目のトレイト

scala> trait Mountain { | val name: String | val alt: Int | def getInfo = { | println(name + alt) }}defined trait Mountain

T-6-1

Page 40: Ipros techmeetup 20131218_scala_handson

40 COPYRIGHT © 2013 IPROS CORPORATION ALL RIGHTS RESERVED

トレイト > 複数トレイトのミックスイン

2 つ目のトレイト

scala> trait Mountain { | val name: String | val alt: Int | def getInfo = { | println(name + alt) }}defined trait Mountain

scala> trait Volcano { | def erupt() { println("erupted!") }}defined trait Volcano

T-6-2

Page 41: Ipros techmeetup 20131218_scala_handson

41 COPYRIGHT © 2013 IPROS CORPORATION ALL RIGHTS RESERVED

トレイト > 複数トレイトのミックスイン

これらをミックスインすると、

scala> class Shinmoe extends Mountain with Volcano { | val name = "ShinmoeDake" | val alt = 1421 }defined class Shinmoe

↑2 つ目からは with

T-6-3

Page 42: Ipros techmeetup 20131218_scala_handson

42 COPYRIGHT © 2013 IPROS CORPORATION ALL RIGHTS RESERVED

トレイト > 複数トレイトのミックスイン

それぞれの特性を持ったクラスを作ることができます

scala> class Shinmoe extends Mountain with Volcano { | val name = "ShinmoeDake" | val alt = 1421 }defined class Shinmoe

scala> val shinmoe = new Shinmoeshinmoe: Shinmoe = Shinmoe@1b827696

scala> shinmoe.altres2: Int = 1421

scala> shinmoe.erupterupted!

T-6-3

Page 43: Ipros techmeetup 20131218_scala_handson

43 COPYRIGHT © 2013 IPROS CORPORATION ALL RIGHTS RESERVED

トレイト > まとめ

1. メソッドもフィールドも抽象化できる

2. 複数のトレイトをミックスインすることができる

Scala には抽象クラスもありますが、基本トレイトで事足ります

trait Mountain { def getName: String val alt: Int }

class Shinmoe extends Mountain with Volcano { val name = "ShinmoeDake" val alt = 1421 }

Page 44: Ipros techmeetup 20131218_scala_handson

44 COPYRIGHT © 2013 IPROS CORPORATION ALL RIGHTS RESERVED

オブジェクト指向要素編 > まとめ

Java と文法が異なり、また Java にはないトレイトという概念が存在しますが、 Java と大きく異なる点はありません。

Page 45: Ipros techmeetup 20131218_scala_handson

45 COPYRIGHT © 2013 IPROS CORPORATION ALL RIGHTS RESERVED

オブジェクト指向要素編 > まとめ

JDK 8 にはトレイトに似た機能として仮想拡張メソッド( Virtual Extension Methods )が追加される予定です

Page 46: Ipros techmeetup 20131218_scala_handson

46 COPYRIGHT © 2013 IPROS CORPORATION ALL RIGHTS RESERVED

関数プログラミング要素編

Scala で関数プログラミング

Page 47: Ipros techmeetup 20131218_scala_handson

47 COPYRIGHT © 2013 IPROS CORPORATION ALL RIGHTS RESERVED

関数 > 高階関数

高階関数とは

Page 48: Ipros techmeetup 20131218_scala_handson

48 COPYRIGHT © 2013 IPROS CORPORATION ALL RIGHTS RESERVED

関数 > 高階関数

パラメータとして関数を取ったり、関数を返す関数

Page 49: Ipros techmeetup 20131218_scala_handson

49 COPYRIGHT © 2013 IPROS CORPORATION ALL RIGHTS RESERVED

関数 > 高階関数

高階関数の定義

scala> def exec(num: Int, execFunc: Int => Boolean) = { | execFunc(num) }exec: (num: Int, execFunc: Int => Boolean)Boolean

FH-1

Page 50: Ipros techmeetup 20131218_scala_handson

50 COPYRIGHT © 2013 IPROS CORPORATION ALL RIGHTS RESERVED

関数 > 高階関数

execFunc というこの関数は

scala> def exec(num: Int, execFunc: Int => Boolean) = { | execFunc(num) }exec: (num: Int, execFunc: Int => Boolean)Boolean

FH-1

Page 51: Ipros techmeetup 20131218_scala_handson

51 COPYRIGHT © 2013 IPROS CORPORATION ALL RIGHTS RESERVED

関数 > 高階関数

Int 型の引数を受け取り

scala> def exec(num: Int, execFunc: Int => Boolean) = { | execFunc(num) }exec: (num: Int, execFunc: Int => Boolean)Boolean

FH-1

Page 52: Ipros techmeetup 20131218_scala_handson

52 COPYRIGHT © 2013 IPROS CORPORATION ALL RIGHTS RESERVED

関数 > 高階関数

Boolean を返します

scala> def exec(num: Int, execFunc: Int => Boolean) = { | execFunc(num) }exec: (num: Int, execFunc: Int => Boolean)Boolean

FH-1

Page 53: Ipros techmeetup 20131218_scala_handson

53 COPYRIGHT © 2013 IPROS CORPORATION ALL RIGHTS RESERVED

関数 > 高階関数

exec は execFunc を呼びます

scala> def exec(num: Int, execFunc: Int => Boolean) = { | execFunc(num) }exec: (num: Int, execFunc: Int => Boolean)Boolean

FH-1

Page 54: Ipros techmeetup 20131218_scala_handson

54 COPYRIGHT © 2013 IPROS CORPORATION ALL RIGHTS RESERVED

関数 > 高階関数

execFunc の定義

scala> def exec(num: Int, execFunc: Int => Boolean) = { | execFunc(num) }exec: (num: Int, execFunc: Int => Boolean)Boolean

scala> def isZero(num: Int) = { | if (num == 0) true else false }isZero: (num: Int)Boolean

FH-1

Page 55: Ipros techmeetup 20131218_scala_handson

55 COPYRIGHT © 2013 IPROS CORPORATION ALL RIGHTS RESERVED

関数 > 高階関数

使ってみましょう

scala> def exec(num: Int, execFunc: Int => Boolean) = { | execFunc(num) }exec: (num: Int, execFunc: Int => Boolean)Boolean

scala> def isZero(num: Int) = { | if (num == 0) true else false }isZero: (num: Int)Boolean

scala> exec(0, isZero)res1: Boolean = true

FH-1

Page 56: Ipros techmeetup 20131218_scala_handson

56 COPYRIGHT © 2013 IPROS CORPORATION ALL RIGHTS RESERVED

関数 > 高階関数

使ってみましょう

scala> def exec(num: Int, execFunc: Int => Boolean) = { | execFunc(num) }exec: (num: Int, execFunc: Int => Boolean)Boolean

scala> def isZero(num: Int) = { | if (num == 0) true else false }isZero: (num: Int)Boolean

scala> exec(0, isZero)res1: Boolean = true

scala> exec(1, isZero)res2: Boolean = false

FH-1

Page 57: Ipros techmeetup 20131218_scala_handson

57 COPYRIGHT © 2013 IPROS CORPORATION ALL RIGHTS RESERVED

文字列をフィルタする関数を実行し、フィルタの結果を表示する高階関数

を作ってみましょう

関数 > 高階関数 > ハンズオン

Page 58: Ipros techmeetup 20131218_scala_handson

58 COPYRIGHT © 2013 IPROS CORPORATION ALL RIGHTS RESERVED

関数 > 高階関数 > ハンズオン > コーディング例

高階関数

scala> def filterBy(str: String, filter: String => Boolean) = { | if (filter(str)) println("passed") | else println("not") }filterBy: (str: String, filter: String => Boolean)Unit

Page 59: Ipros techmeetup 20131218_scala_handson

59 COPYRIGHT © 2013 IPROS CORPORATION ALL RIGHTS RESERVED

関数 > 高階関数 > ハンズオン > コーディング例

フィルタ関数

scala> def filterBy(str: String, filter: String => Boolean) = { | if (filter(str)) println("passed") | else println("not") }filterBy: (str: String, filter: String => Boolean)Unit

scala> def lengthFilter(str: String) = { | if (str.length > 10) true | else false }lengthFilter: (str: String)Boolean

Page 60: Ipros techmeetup 20131218_scala_handson

60 COPYRIGHT © 2013 IPROS CORPORATION ALL RIGHTS RESERVED

関数 > 高階関数 > ハンズオン > コーディング例

動作確認

scala> filterBy(" 明日は晴れると良いな ", lengthFilter)not

scala> filterBy(" 明日は雲ひとつない晴天となるでしょう ", lengthFilter)passed

Page 61: Ipros techmeetup 20131218_scala_handson

61 COPYRIGHT © 2013 IPROS CORPORATION ALL RIGHTS RESERVED

同じ文字列に対していろんなフィルタをかけたい時

関数 > 高階関数 > カリー化

Page 62: Ipros techmeetup 20131218_scala_handson

62 COPYRIGHT © 2013 IPROS CORPORATION ALL RIGHTS RESERVED

関数 > 高階関数 > カリー化

高階関数

scala> def filterBy(str: String, filter: String => Boolean) = { | if (filter(str)) println("passed") | else println("not") }filterBy: (str: String, filter: String => Boolean)Unit

FH-2

Page 63: Ipros techmeetup 20131218_scala_handson

63 COPYRIGHT © 2013 IPROS CORPORATION ALL RIGHTS RESERVED

関数 > 高階関数 > カリー化

を、カリー化してみる

scala> def filterBy(str: String, filter: String => Boolean) = { | if (filter(str)) println("passed") | else println("not") }filterBy: (str: String, filter: String => Boolean)Unit

scala> val curriedFilterBy = (filterBy _).curriedcurriedFilterBy: String => ((String => Boolean) => Unit) = <function1>

※カリー化複数の引数を取る関数を、ある引数 xを取り残りの引数を取る関数に変換すること

FH-2

Page 64: Ipros techmeetup 20131218_scala_handson

64 COPYRIGHT © 2013 IPROS CORPORATION ALL RIGHTS RESERVED

関数 > 高階関数 > カリー化

curriedFilterBy は String 型の引数を取り、

scala> def filterBy(str: String, filter: String => Boolean) = { | if (filter(str)) println("passed") | else println("not") }filterBy: (str: String, filter: String => Boolean)Unit

scala> val curriedFilterBy = (filterBy _).curriedcurriedFilterBy: String => ((String => Boolean) => Unit) = <function1>

FH-2

Page 65: Ipros techmeetup 20131218_scala_handson

65 COPYRIGHT © 2013 IPROS CORPORATION ALL RIGHTS RESERVED

関数 > 高階関数 > カリー化

String 型の引数から Boolean 型の結果を返す関数を返しますよ

scala> def filterBy(str: String, filter: String => Boolean) = { | if (filter(str)) println("passed") | else println("not") }filterBy: (str: String, filter: String => Boolean)Unit

scala> val curriedFilterBy = (filterBy _).curriedcurriedFilterBy: String => ((String => Boolean) => Unit) = <function1>

FH-2

Page 66: Ipros techmeetup 20131218_scala_handson

66 COPYRIGHT © 2013 IPROS CORPORATION ALL RIGHTS RESERVED

関数 > 高階関数 > カリー化

パラメータを 1 つしか指定してなくても呼べます

scala> def filterBy(str: String, filter: String => Boolean) = { | if (filter(str)) println("passed") | else println("not") }filterBy: (str: String, filter: String => Boolean)Unit

scala> val curriedFilterBy = (filterBy _).curriedcurriedFilterBy: String => ((String => Boolean) => Unit) = <function1>

scala> curriedFilterBy("1234567890")res19: (String => Boolean) => Unit = <function1>

※部分適用引数の一部だけを関数に適用すること

FH-2

Page 67: Ipros techmeetup 20131218_scala_handson

67 COPYRIGHT © 2013 IPROS CORPORATION ALL RIGHTS RESERVED

関数 > 高階関数 > カリー化

lengthFilter を渡すと、フィルタ結果が表示されます

scala> def filterBy(str: String, filter: String => Boolean) = { | if (filter(str)) println("passed") | else println("not") }filterBy: (str: String, filter: String => Boolean)Unit

scala> val curriedFilterBy = (filterBy _).curriedcurriedFilterBy: String => ((String => Boolean) => Unit) = <function1>

scala> curriedFilterBy("1234567890")res19: (String => Boolean) => Unit = <function1>

scala> curriedFilterBy("1234567890")(lengthFilter)not

FH-2

Page 68: Ipros techmeetup 20131218_scala_handson

68 COPYRIGHT © 2013 IPROS CORPORATION ALL RIGHTS RESERVED

文字列フィルタを追加し、カリー化した先ほどの高階関数を使ってフィルタしてみましょ

関数 > 高階関数 > カリー化 > ハンズオン

Page 69: Ipros techmeetup 20131218_scala_handson

69 COPYRIGHT © 2013 IPROS CORPORATION ALL RIGHTS RESERVED

関数 > 高階関数 > カリー化 > ハンズオン > コーディング例

フィルタ関数

scala> def matchingFilter(str: String) = { | if (str.contains("scala")) true | else false }matchingFilter: (str: String)Boolean

Page 70: Ipros techmeetup 20131218_scala_handson

70 COPYRIGHT © 2013 IPROS CORPORATION ALL RIGHTS RESERVED

関数 > 高階関数 > カリー化 > ハンズオン > コーディング例

フィルタ対象文字列まで部分適用した関数オブジェクトを作り

scala> def matchingFilter(str: String) = { | if (str.contains("scala")) true | else false }matchingFilter: (str: String)Boolean

scala> val func = curriedFilterBy("Scala は面白い言語です ")func: (String => Boolean) => Unit = <function1>

Page 71: Ipros techmeetup 20131218_scala_handson

71 COPYRIGHT © 2013 IPROS CORPORATION ALL RIGHTS RESERVED

関数 > 高階関数 > カリー化 > ハンズオン > コーディング例

フィルタにかけてみます

scala> def matchingFilter(str: String) = { | if (str.contains("scala")) true | else false }matchingFilter: (str: String)Boolean

scala> val func = curriedFilterBy("Scala は面白い言語です ")func: (String => Boolean) => Unit = <function1>

scala> func(lengthFilter)passed

Page 72: Ipros techmeetup 20131218_scala_handson

72 COPYRIGHT © 2013 IPROS CORPORATION ALL RIGHTS RESERVED

関数 > 高階関数 > カリー化 > ハンズオン > コーディング例

フィルタにかけてみます

scala> def matchingFilter(str: String) = { | if (str.contains("scala")) true | else false }matchingFilter: (str: String)Boolean

scala> val func = curriedFilterBy("Scala は面白い言語です ")func: (String => Boolean) => Unit = <function1>

scala> func(lengthFilter)passed

scala> func(matchingFilter)not

Page 73: Ipros techmeetup 20131218_scala_handson

73 COPYRIGHT © 2013 IPROS CORPORATION ALL RIGHTS RESERVED

高階関数と同様の機能が JDK 8 には搭載される予定です

関数編 > さいごに

Page 74: Ipros techmeetup 20131218_scala_handson

74 COPYRIGHT © 2013 IPROS CORPORATION ALL RIGHTS RESERVED

SBT 編

SBT

Page 75: Ipros techmeetup 20131218_scala_handson

75 COPYRIGHT © 2013 IPROS CORPORATION ALL RIGHTS RESERVED

SBT 編

目的• SBT の簡単な説明• ビルド定義ファイルを書いてみる• jar ファイルを作る

Page 76: Ipros techmeetup 20131218_scala_handson

76 COPYRIGHT © 2013 IPROS CORPORATION ALL RIGHTS RESERVED

SBT > 概要

• コンパイル• 実行• テスト• パッケージング• ライブラリ管理などを行えます。プラグインで機能拡張が可能です。

SBT とは Java, Scala 向けビルドツールです (SBT = Simple Build Tool)

Page 77: Ipros techmeetup 20131218_scala_handson

77 COPYRIGHT © 2013 IPROS CORPORATION ALL RIGHTS RESERVED

SBT > 概要

• コンパイル• 実行• テスト• パッケージング• ライブラリ管理

今回は以下を取り上げます

Page 78: Ipros techmeetup 20131218_scala_handson

78 COPYRIGHT © 2013 IPROS CORPORATION ALL RIGHTS RESERVED

SBT > 構成要素

1. SBT 本体 → インストール済み

2. Scala ソースコード → 以降で紹介

3. ビルド定義ファイル → 以降で紹介

SBT を利用する場合最低限必要なもの

Page 79: Ipros techmeetup 20131218_scala_handson

79 COPYRIGHT © 2013 IPROS CORPORATION ALL RIGHTS RESERVED

SBT > 構成要素 > ディレクトリ構成

SBT プロジェクトのディレクトリ構成

src/ main/ resources/ リソースファイルディレクトリ scala/ Scala ソースファイルディレクトリ java/ Java ソースファイルディレクトリ test/ resources/ リソースファイルディレクトリ scala/ Scala ソースファイル java/ Java ソースファイル

※src配下にある上記以外のディレクトリは無視されます

Page 80: Ipros techmeetup 20131218_scala_handson

80 COPYRIGHT © 2013 IPROS CORPORATION ALL RIGHTS RESERVED

SBT > ビルド定義ファイル

1. build.sbt

ビルド定義ファイルは 2種類あります

2. Build.scala

• シンプルなビルド定義であればこちらで OK• 各設定は 1 行あけて記述する

• build.sbt で事足りない場合にはこちらを使う• Scala のコードをそのまま書くことができる

Page 81: Ipros techmeetup 20131218_scala_handson

81 COPYRIGHT © 2013 IPROS CORPORATION ALL RIGHTS RESERVED

SBT > ビルド定義ファイル

1. build.sbt

今回はこちらを取り上げます

2. Build.scala

• シンプルなビルド定義であればこちらで OK• 各設定は 1 行あけて記述する

• build.sbt で事足りない場合にはこちらを使う• Scala のコードをそのまま書くことができる

Page 82: Ipros techmeetup 20131218_scala_handson

82 COPYRIGHT © 2013 IPROS CORPORATION ALL RIGHTS RESERVED

SBT > ビルド定義ファイル > build.sbt

サンプル

name := "hello"

version := "1.0"

scalaVersion := "2.10.3"

Page 83: Ipros techmeetup 20131218_scala_handson

83 COPYRIGHT © 2013 IPROS CORPORATION ALL RIGHTS RESERVED

SBT > ビルド定義ファイル > build.sbt

プロジェクトの名前です

name := "hello"

version := "1.0"

scalaVersion := "2.10.3"

Page 84: Ipros techmeetup 20131218_scala_handson

84 COPYRIGHT © 2013 IPROS CORPORATION ALL RIGHTS RESERVED

SBT > ビルド定義ファイル > build.sbt

プロジェクトのバージョンです

name := "hello"

version := "1.0"

scalaVersion := "2.10.3"

Page 85: Ipros techmeetup 20131218_scala_handson

85 COPYRIGHT © 2013 IPROS CORPORATION ALL RIGHTS RESERVED

SBT > ビルド定義ファイル > build.sbt

使用する Scala のバージョンです

name := "hello"

version := "1.0"

scalaVersion := "2.10.3"

Page 86: Ipros techmeetup 20131218_scala_handson

86 COPYRIGHT © 2013 IPROS CORPORATION ALL RIGHTS RESERVED

SBT > ハンズオン①

任意のディレクトリ配下に以下のファイルを作成します

name := "hello"

version := "1.0"

scalaVersion := "2.10.3"

1. build.sbt

2. Hello.scalaobject Main { def main(args: Array[String]): Unit = { println("Hello") }} ※object = シングルトンオブジェクト

S-1

S-2

Page 87: Ipros techmeetup 20131218_scala_handson

87 COPYRIGHT © 2013 IPROS CORPORATION ALL RIGHTS RESERVED

SBT > ハンズオン①

ディレクトリ構成

src/ build.sbt main/ scala/ Hello.scala

S-3

Page 88: Ipros techmeetup 20131218_scala_handson

88 COPYRIGHT © 2013 IPROS CORPORATION ALL RIGHTS RESERVED

SBT > ハンズオン①

SBT を起動してまずはコンパイル

$ cd /path/to/project

$ sbt[info] Set current project to sbt (in build file:/path/to/project)> compile

Page 89: Ipros techmeetup 20131218_scala_handson

89 COPYRIGHT © 2013 IPROS CORPORATION ALL RIGHTS RESERVED

SBT > ハンズオン①

コンパイルされました

$ cd /path/to/project

$ sbt[info] Set current project to sbt (in build file:/path/to/project)> compile[info] Updating {file:/path/to/project/}sbt...[info] Resolving org.fusesource.jansi#jansi;1.4 ...[info] Done updating.[info] Compiling 1 Scala source to /path/to/project/target/scala-2.10/classes...[success] Total time: 1 s, completed 2013/12/10 19:57:20>

Page 90: Ipros techmeetup 20131218_scala_handson

90 COPYRIGHT © 2013 IPROS CORPORATION ALL RIGHTS RESERVED

SBT > ハンズオン①

続いて実行してみます

> run

Page 91: Ipros techmeetup 20131218_scala_handson

91 COPYRIGHT © 2013 IPROS CORPORATION ALL RIGHTS RESERVED

SBT > ハンズオン①

実行結果

> run[info] Running Main Hello[success] Total time: 0 s, completed 2013/12/10 19:59:30>

← 表示された!

Page 92: Ipros techmeetup 20131218_scala_handson

92 COPYRIGHT © 2013 IPROS CORPORATION ALL RIGHTS RESERVED

SBT > ハンズオン②

パッケージングも簡単です

> package

Page 93: Ipros techmeetup 20131218_scala_handson

93 COPYRIGHT © 2013 IPROS CORPORATION ALL RIGHTS RESERVED

SBT > ハンズオン②

実行結果

> package[info] Packaging /path/to/project/target/scala-2.10/sbt_2.10-1.0.jar ...[info] Done packaging.[success] Total time: 0 s, completed 2013/12/10 20:01:37

← できた!

Page 94: Ipros techmeetup 20131218_scala_handson

94 COPYRIGHT © 2013 IPROS CORPORATION ALL RIGHTS RESERVED

SBT > ハンズオン②

java コマンドで実行してみます

> package[info] Packaging /path/to/project/target/scala-2.10/sbt_2.10-1.0.jar ...[info] Done packaging.[success] Total time: 0 s, completed 2013/12/10 20:01:37> exit$ ls$ build.sbt project src target$ cd target/scala-2.10/$ lsclasses sbt_2.10-1.0.jar$ java -cp ./sbt_2.10-1.0.jar:/path/to/scala-library.jar Hello

※ホームディレクトリ /.sbt配下にあるはず

Page 95: Ipros techmeetup 20131218_scala_handson

95 COPYRIGHT © 2013 IPROS CORPORATION ALL RIGHTS RESERVED

SBT > ハンズオン②

実行結果

> package[info] Packaging /path/to/project/target/scala-2.10/sbt_2.10-1.0.jar ...[info] Done packaging.[success] Total time: 0 s, completed 2013/12/10 20:01:37> exit$ build.sbt project src target$ cd target/scala-2.10/$ lsclasses sbt_2.10-1.0.jar$ java -cp ./sbt_2.10-1.0.jar:/path/to/scala-library.jar HelloHello

Page 96: Ipros techmeetup 20131218_scala_handson

96 COPYRIGHT © 2013 IPROS CORPORATION ALL RIGHTS RESERVED

SBT > ハンズオン③

package で生成する jar ファイル名を

scala-handson_2.10-9.9.jarに変えてみましょう

Page 97: Ipros techmeetup 20131218_scala_handson

97 COPYRIGHT © 2013 IPROS CORPORATION ALL RIGHTS RESERVED

SBT > ハンズオン③ > 設定例

build.sbt を変えます

name := "scala-handson"

version := "9.9"

scalaVersion := "2.10.3"

Page 98: Ipros techmeetup 20131218_scala_handson

98 COPYRIGHT © 2013 IPROS CORPORATION ALL RIGHTS RESERVED

SBT > ハンズオン③ > 設定例 > 実行結果

変わっていますね

> package[info] Packaging /path/to/project/target/scala-2.10/scala-handson_2.10-9.9.jar ...[info] Done packaging.[success] Total time: 0 s, completed 2013/12/10 20:25:17

Page 99: Ipros techmeetup 20131218_scala_handson

99 COPYRIGHT © 2013 IPROS CORPORATION ALL RIGHTS RESERVED

SBT > プラグイン

• sbt-eclipse (https://github.com/typesafehub/sbteclipse)

• Eclipse のプロジェクトファイルを生成できる

• xsbt-web-plugin (https://github.com/JamesEarlDouglas/xsbt-web-plugin)

• Web 開発用のプラグイン

• sbt-assembly (https://github.com/sbt/sbt-assembly)

• オールインワンの jar ファイルを生成できる

色々と便利なプラグインがあります

Page 100: Ipros techmeetup 20131218_scala_handson

100 COPYRIGHT © 2013 IPROS CORPORATION ALL RIGHTS RESERVED

SBT > プラグイン

プラグインを利用すれば、大抵のことはできます。イプロスでは Jenkins と併せて、ビルド、 DBマイグレーション、デプロイまでをSBT で実施しています。

Page 101: Ipros techmeetup 20131218_scala_handson

101 COPYRIGHT © 2013 IPROS CORPORATION ALL RIGHTS RESERVED

まとめ

まとめ

Page 102: Ipros techmeetup 20131218_scala_handson

102 COPYRIGHT © 2013 IPROS CORPORATION ALL RIGHTS RESERVED

まとめ

イプロスでは広告系システムの開発に Scalaを導入し、 REST API サービス及びバッチを開発しています。

Scala の持つ概念の一部が JDK 8 でも取り入れられる予定であることから、今日ご紹介した内容は今後当たり前になっていくと思います。

Page 103: Ipros techmeetup 20131218_scala_handson

103 COPYRIGHT © 2013 IPROS CORPORATION ALL RIGHTS RESERVED

まとめ

この勉強会が Scala を学ぶ契機となったならば幸いです。

Page 104: Ipros techmeetup 20131218_scala_handson

104 COPYRIGHT © 2013 IPROS CORPORATION ALL RIGHTS RESERVED

おしまい

ありがとうございました