Upload
honda-y
View
1.969
Download
0
Embed Size (px)
DESCRIPTION
2013/12/18に株式会社イプロスにて開催されたScalaハンズオン勉強会の後半パートで使用したスライドです。
Citation preview
未経験者のための Scala
株式会社イプロス 本多陽平
2 COPYRIGHT © 2013 IPROS CORPORATION ALL RIGHTS RESERVED
後半パート
Scala の真髄に少しだけ触れる
3 COPYRIGHT © 2013 IPROS CORPORATION ALL RIGHTS RESERVED
自己紹介
• 本多陽平
• 2012 年 2 月イプロス入社
• Java 歴 1 年半→ Scala 歴半年
• 現在は広告系サービスの開発を担当
• 去年登山を始めました
• サッカーを観たり、梅干しをつけたり、温泉に行ったり、が趣味
4 COPYRIGHT © 2013 IPROS CORPORATION ALL RIGHTS RESERVED
後半パートについて
後半パートでは、 Scala の• オブジェクト指向要素• 関数プログラミング要素の両側面に簡単に触れるとともに、SBT を使ったビルドについても触れます。
5 COPYRIGHT © 2013 IPROS CORPORATION ALL RIGHTS RESERVED
アジェンダ1. Scala でオブジェクト指向
1. クラスハンズオン
2. トレイト2. Scala で関数プログラミング
1. 高階関数ハンズオン
3. SBT によるビルド1. コンパイル
ハンズオン2. 実行
ハンズオン3. パッケージング
ハンズオン
6 COPYRIGHT © 2013 IPROS CORPORATION ALL RIGHTS RESERVED
前置き
Scala の言語仕様を網羅的に説明しているわけではないので、ご了承下さい
7 COPYRIGHT © 2013 IPROS CORPORATION ALL RIGHTS RESERVED
サンプルコードについて
後半パートで使用するサンプルコードは以下にアップロードしてあります。
イプロス開発ブログhttp://ipros-creators.tumblr.com/※ 「イプロス 開発」で検索
8 COPYRIGHT © 2013 IPROS CORPORATION ALL RIGHTS RESERVED
オブジェクト指向要素編
Scala でオブジェクト指向
9 COPYRIGHT © 2013 IPROS CORPORATION ALL RIGHTS RESERVED
クラス
Scala は関数型言語であり、オブジェクト指向言語でもあるので、クラスを使えます
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
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
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
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
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
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
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
17 COPYRIGHT © 2013 IPROS CORPORATION ALL RIGHTS RESERVED
クラス > コンストラクタ
名前は?
scala> fuji.asInstanceOf isInstanceOf printName toString
scala > fuji.printNameres0: String = Mt. Fuj
C-1
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
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
20 COPYRIGHT © 2013 IPROS CORPORATION ALL RIGHTS RESERVED
クラス > コンストラクタ
クラスパラメータがフィールドにありません
scala> fuji.asInstanceOf isInstanceOf printName toString
C-1
21 COPYRIGHT © 2013 IPROS CORPORATION ALL RIGHTS RESERVED
クラス > コンストラクタ
val をつけて定義するとフィールドになります
scala> class Mountain (val name: String)defined class Mountain
C-2
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
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") }}
24 COPYRIGHT © 2013 IPROS CORPORATION ALL RIGHTS RESERVED
クラス > メソッド
メソッド
25 COPYRIGHT © 2013 IPROS CORPORATION ALL RIGHTS RESERVED
クラス > メソッド
メソッド定義は簡単で、関数定義と同じです
scala> class Mountain (val name: String) { | def erupt = { println("erupted!") }}defined class Mountain
※ 呼び方(ということが多いです) 関数単体 = 関数 クラス内の関数 = メソッド
C-3
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
27 COPYRIGHT © 2013 IPROS CORPORATION ALL RIGHTS RESERVED
クラス > ハンズオン
噴火する度に標高が下がる山
を作ってみましょう
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
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
← 下がってる
← 下がってる
30 COPYRIGHT © 2013 IPROS CORPORATION ALL RIGHTS RESERVED
トレイト
実装の定義も可能な Java のインターフェース
という感じです
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
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
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
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
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
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
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
38 COPYRIGHT © 2013 IPROS CORPORATION ALL RIGHTS RESERVED
トレイト
トレイトは複数ミックスインできます
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
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
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
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
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 }
44 COPYRIGHT © 2013 IPROS CORPORATION ALL RIGHTS RESERVED
オブジェクト指向要素編 > まとめ
Java と文法が異なり、また Java にはないトレイトという概念が存在しますが、 Java と大きく異なる点はありません。
45 COPYRIGHT © 2013 IPROS CORPORATION ALL RIGHTS RESERVED
オブジェクト指向要素編 > まとめ
JDK 8 にはトレイトに似た機能として仮想拡張メソッド( Virtual Extension Methods )が追加される予定です
46 COPYRIGHT © 2013 IPROS CORPORATION ALL RIGHTS RESERVED
関数プログラミング要素編
Scala で関数プログラミング
47 COPYRIGHT © 2013 IPROS CORPORATION ALL RIGHTS RESERVED
関数 > 高階関数
高階関数とは
48 COPYRIGHT © 2013 IPROS CORPORATION ALL RIGHTS RESERVED
関数 > 高階関数
パラメータとして関数を取ったり、関数を返す関数
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
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
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
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
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
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
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
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
57 COPYRIGHT © 2013 IPROS CORPORATION ALL RIGHTS RESERVED
文字列をフィルタする関数を実行し、フィルタの結果を表示する高階関数
を作ってみましょう
関数 > 高階関数 > ハンズオン
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
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
60 COPYRIGHT © 2013 IPROS CORPORATION ALL RIGHTS RESERVED
関数 > 高階関数 > ハンズオン > コーディング例
動作確認
scala> filterBy(" 明日は晴れると良いな ", lengthFilter)not
scala> filterBy(" 明日は雲ひとつない晴天となるでしょう ", lengthFilter)passed
61 COPYRIGHT © 2013 IPROS CORPORATION ALL RIGHTS RESERVED
同じ文字列に対していろんなフィルタをかけたい時
関数 > 高階関数 > カリー化
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
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
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
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
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
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
68 COPYRIGHT © 2013 IPROS CORPORATION ALL RIGHTS RESERVED
文字列フィルタを追加し、カリー化した先ほどの高階関数を使ってフィルタしてみましょ
う
関数 > 高階関数 > カリー化 > ハンズオン
69 COPYRIGHT © 2013 IPROS CORPORATION ALL RIGHTS RESERVED
関数 > 高階関数 > カリー化 > ハンズオン > コーディング例
フィルタ関数
scala> def matchingFilter(str: String) = { | if (str.contains("scala")) true | else false }matchingFilter: (str: String)Boolean
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>
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
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
73 COPYRIGHT © 2013 IPROS CORPORATION ALL RIGHTS RESERVED
高階関数と同様の機能が JDK 8 には搭載される予定です
関数編 > さいごに
74 COPYRIGHT © 2013 IPROS CORPORATION ALL RIGHTS RESERVED
SBT 編
SBT
75 COPYRIGHT © 2013 IPROS CORPORATION ALL RIGHTS RESERVED
SBT 編
目的• SBT の簡単な説明• ビルド定義ファイルを書いてみる• jar ファイルを作る
76 COPYRIGHT © 2013 IPROS CORPORATION ALL RIGHTS RESERVED
SBT > 概要
• コンパイル• 実行• テスト• パッケージング• ライブラリ管理などを行えます。プラグインで機能拡張が可能です。
SBT とは Java, Scala 向けビルドツールです (SBT = Simple Build Tool)
77 COPYRIGHT © 2013 IPROS CORPORATION ALL RIGHTS RESERVED
SBT > 概要
• コンパイル• 実行• テスト• パッケージング• ライブラリ管理
今回は以下を取り上げます
78 COPYRIGHT © 2013 IPROS CORPORATION ALL RIGHTS RESERVED
SBT > 構成要素
1. SBT 本体 → インストール済み
2. Scala ソースコード → 以降で紹介
3. ビルド定義ファイル → 以降で紹介
SBT を利用する場合最低限必要なもの
79 COPYRIGHT © 2013 IPROS CORPORATION ALL RIGHTS RESERVED
SBT > 構成要素 > ディレクトリ構成
SBT プロジェクトのディレクトリ構成
src/ main/ resources/ リソースファイルディレクトリ scala/ Scala ソースファイルディレクトリ java/ Java ソースファイルディレクトリ test/ resources/ リソースファイルディレクトリ scala/ Scala ソースファイル java/ Java ソースファイル
※src配下にある上記以外のディレクトリは無視されます
80 COPYRIGHT © 2013 IPROS CORPORATION ALL RIGHTS RESERVED
SBT > ビルド定義ファイル
1. build.sbt
ビルド定義ファイルは 2種類あります
2. Build.scala
• シンプルなビルド定義であればこちらで OK• 各設定は 1 行あけて記述する
• build.sbt で事足りない場合にはこちらを使う• Scala のコードをそのまま書くことができる
81 COPYRIGHT © 2013 IPROS CORPORATION ALL RIGHTS RESERVED
SBT > ビルド定義ファイル
1. build.sbt
今回はこちらを取り上げます
2. Build.scala
• シンプルなビルド定義であればこちらで OK• 各設定は 1 行あけて記述する
• build.sbt で事足りない場合にはこちらを使う• Scala のコードをそのまま書くことができる
82 COPYRIGHT © 2013 IPROS CORPORATION ALL RIGHTS RESERVED
SBT > ビルド定義ファイル > build.sbt
サンプル
name := "hello"
version := "1.0"
scalaVersion := "2.10.3"
83 COPYRIGHT © 2013 IPROS CORPORATION ALL RIGHTS RESERVED
SBT > ビルド定義ファイル > build.sbt
プロジェクトの名前です
name := "hello"
version := "1.0"
scalaVersion := "2.10.3"
84 COPYRIGHT © 2013 IPROS CORPORATION ALL RIGHTS RESERVED
SBT > ビルド定義ファイル > build.sbt
プロジェクトのバージョンです
name := "hello"
version := "1.0"
scalaVersion := "2.10.3"
85 COPYRIGHT © 2013 IPROS CORPORATION ALL RIGHTS RESERVED
SBT > ビルド定義ファイル > build.sbt
使用する Scala のバージョンです
name := "hello"
version := "1.0"
scalaVersion := "2.10.3"
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
87 COPYRIGHT © 2013 IPROS CORPORATION ALL RIGHTS RESERVED
SBT > ハンズオン①
ディレクトリ構成
src/ build.sbt main/ scala/ Hello.scala
S-3
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
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>
90 COPYRIGHT © 2013 IPROS CORPORATION ALL RIGHTS RESERVED
SBT > ハンズオン①
続いて実行してみます
> run
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>
← 表示された!
92 COPYRIGHT © 2013 IPROS CORPORATION ALL RIGHTS RESERVED
SBT > ハンズオン②
パッケージングも簡単です
> package
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
← できた!
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配下にあるはず
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
96 COPYRIGHT © 2013 IPROS CORPORATION ALL RIGHTS RESERVED
SBT > ハンズオン③
package で生成する jar ファイル名を
scala-handson_2.10-9.9.jarに変えてみましょう
97 COPYRIGHT © 2013 IPROS CORPORATION ALL RIGHTS RESERVED
SBT > ハンズオン③ > 設定例
build.sbt を変えます
name := "scala-handson"
version := "9.9"
scalaVersion := "2.10.3"
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
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 ファイルを生成できる
色々と便利なプラグインがあります
100 COPYRIGHT © 2013 IPROS CORPORATION ALL RIGHTS RESERVED
SBT > プラグイン
プラグインを利用すれば、大抵のことはできます。イプロスでは Jenkins と併せて、ビルド、 DBマイグレーション、デプロイまでをSBT で実施しています。
101 COPYRIGHT © 2013 IPROS CORPORATION ALL RIGHTS RESERVED
まとめ
まとめ
102 COPYRIGHT © 2013 IPROS CORPORATION ALL RIGHTS RESERVED
まとめ
イプロスでは広告系システムの開発に Scalaを導入し、 REST API サービス及びバッチを開発しています。
Scala の持つ概念の一部が JDK 8 でも取り入れられる予定であることから、今日ご紹介した内容は今後当たり前になっていくと思います。
103 COPYRIGHT © 2013 IPROS CORPORATION ALL RIGHTS RESERVED
まとめ
この勉強会が Scala を学ぶ契機となったならば幸いです。
104 COPYRIGHT © 2013 IPROS CORPORATION ALL RIGHTS RESERVED
おしまい
ありがとうございました