2017/05/20 JJUG CCC 2017 Spring JJUG CCC 2017 Spring http://www.java-users.jp/ccc2017spring/
- Abe Asami “きの子”
- 大阪のフリーランスプログラマ
- http://nocono.net/
- @aa7th
- Scala、Andorid(Kotlin)
- 祝・KotlinAndroid公式化
- Scala関西、関西Java女子部 主催
- 関西最大のScalaカンファレンス
- 去年の参加者は関係者込みで約180人
- 9/9(土) 天満研修センター
- 大阪駅の隣の駅
- summit.scala-kansai.org
- Scalaのはじめかた
- 基本文法のほんの1部を紹介
- 私的に便利だなーと感じている機能
- String Interpolation
- 中置記法
- case class
- パターンマッチ
- Scalaを始めた頃戸惑った文法
- 括弧記法ルール
- implicits paramater
- ここが好きだよScala
- Javaをやっている方なら理解に困らないであろう機能
- クラス
- 基本制御構文
- trait (JavaでいうところのInterface)
- ラムダ式
- Option (Optional)
などはあまり 説明しません。
- オブジェクト指向と関数型言語両方の特性を併せ持つJVM言語
- コンパイルをするとJavaのバイトコードが生成される
- Javaのライブラリを利用することが可能
- 関数を第1級オブジェクトとして扱う
- メソッドの引数に関数を渡すことができる
- 副作用がないプログラムを目指す
- Scalaは副作用を許容する非純粋関数型言語。
- 副作用を「なるべく」なくす・局所化して処理を書くことが推奨されている。
- 変数への代入を避けて定数を使用する
- 同一の入力値に対して、必ず同一の結果が返ってくる関数を組み合わせ、プログラムを組んでいく
- 保守性が高い
- 並列処理に強い
- JDK
- SBT (ScalaBuildTool)
- Scala標準のビルドツール
- Activatorという公式のカスタム版SBTがあったが、最近EOLになった
- IntelliJ IDEA
- 単にScalaを書くだけであれば無償版で使える。有償版だとPlayFrameworkサポートなどが使える。
- Vim・Emacsなどのテキストエディタ
- Scalaスケーラブルプログラミング第3版
- Scala逆引きレシピ
- 内容が少し古い可能性があるので注意
- ドワンゴさんの新人向け研修テキスト
- Tech to Value (がくぞ) さん
- 他にもScala導入時に有名なエンジニアさんにアドバイザーとしてはいってもらう例はよく聞きます
// 変数
// 型推論・セミコロン不要
var str1 = "再代入可能な変数です"
val str2 = "再代入不可能な定数です"
// varは極力避けて、valを利用するのが一般的
/**
* プロパティ from と to を持つクラス
*/
class Hello(val from: String, val to: String) {
/**
* 挨拶を出力するメソッド
*/
def sayHello(): Unit = {
// printlnはインポートしなくても利用できる
// String Interpolation機能により、文字列中に変数を埋め込むことが可能
println(s"$from: こんにちは, $to さん!")
}
// 処理が1行である場合、波括弧は省略できる
// (※ 2017/05/23 追記:「省略できる」という表現は語弊があるとのことです。 https://twitter.com/kmizu/status/865250818345193472)
// 引数がないメソッドは()を省略可能 ※一般的に副作用が生じるメソッドは()を省略するべきではないので、これは本当はよくない例です。
// 型推論により戻り値の型を省略可能 (書く方が無難)
def sayHello2 =
println(s"$from: こんにちは, $to さん!")
}
val hello = new Hello("きの子", "うらがみ")
hello.sayHello()
hello.sayHello2
/**
* objectキーワードでシングルトンオブジェクトとなる
* (JavaでいうところのStaticは存在しない)
*/
object Sample {
private val pi = 3.14
// 円の面積
def areaOfCircle(radius: Int): Double = {
// ifは「文」ではなく「式」なので結果を返す
val result =
if(radius > 0)
radius * radius * pi
else
0
// returnキーワードはいらない
result
}
}
// シングルトンなのでnewしなくても使える
Sample.areaOfCircle(3)
Sample.areaOfCircle(-3)
// 実は演算子もメソッド
// 「+」はIntのメソッド名
1 + 2 + 3 // 中置記法によりこのように書くことができる
// 1.+(2.+(3)) ← 間違い
(1.+(2)).+(3) // 2017/05/23 Twitterでご指摘頂いた点訂正: https://twitter.com/xuwei_k/status/865828669087928320
// 自分で演算子を作ることも可能。 (最後、時間があればご紹介します)
// 両方1から5のリスト
List(1, 2, 3, 4, 5)
// toはRange型を返却するIntのメソッド
(1 to 5).toList
// 1から5のリストに1を足しながら出力
for(num <- (1 to 5)) {
println(num + 1)
}
// map関数を利用した例
// => は関数リテラル
val list = (1 to 5).toList
list
.map(num => num + 1)
.foreach(println(_)) // foreach(num => println(num)) と同義
// 処理がブロック(複数行)になる場合、波括弧でくくる
list.map { num =>
val tmp = num + 1
tmp * 3
}
/**
* case class
*
* getter, setterやtoStringやequalsが自動生成される
* POJOクラスを作成するのに便利
*/
case class Person(name: String, age: Int)
// case classはnewキーワードが不要
val kinoko = Person("きの子", 18)
val kinoko2 = Person("きの子", 18)
if(kinoko == kinoko2) "同一人物です" else "別人"
// toStringできちんと中の値が分かる形で文字列化してくれる
println(kinoko.toString)
//
// パターンマッチ
//
//
// パターンマッチはmatch式などで使うことができる。
// match式はJavaのSwitch文の強い版みたいなやつ
//
"s" match {
case "s" => "OK"
case _ => "NG"
}
// 型でマッチさせることも可能
// (コップ本より引用)
def generalSize(x: Any) = x match {
case s: String => s.length
case m: Map[_, _] => m.size
case _ => -1
}
generalSize("abc")
generalSize(Map(1 -> 'a', 2 -> 'b'))
generalSize(5)
// case classやOption、タプルなどを分解して
// 中身を抽出することができる
case class Person(name: String, age: Int)
def introduction(x: Any) = x match {
case Person(name, age) => s"$name $age さい"
case _ => "知らない子です"
}
val kinoko = Person("きの子", 18)
introduction(kinoko)
introduction("たけのこ")
def create(
userName: UserName)(implicit s: DBSession): UserId = {
// このメソッドのシグネチャは
// def createWithAttributes(parameters: (Symbol, Any)*)(implicit s: DBSession): Id
// DBSessionは明示的に渡していないが、implicitなので暗黙的に渡されている
createWithAttributes('userName -> userName.value)
}
- PlayFrameworkやO/Rマッパーなどで、このように共通で引き回すことになるオブジェクト(Reqest, Configuration, Connection...etc)を暗黙的に渡す用途をよく目にする
- Implicitは他にも色々な機能を提供してくれるものであり、このような引数ひきまわしのための機能というわけではないので、そこは注意。
- ただ、おそらく初心者が最初に目にする用途はこれだと思うので、今日はご紹介しました。
- シンプルな文法
- よく「Scalaは難しい」と言われるが、最低限覚えるべき文法自体はさほど多くなく、シンプルだと思う。
- すっきりしたコードが書ける
- 表現力が豊か
case class Point(x: Int, y: Int) {
def add(p: Point) =
Point(this.x - p.x, this.y - p.y)
def +(p: Point) = add(p)
}
// 3行とも、Pointの和を取る処理
// res0: Point = Point(280,-200)
Point(300, 100).add(Point(20, 300))
Point(300, 100) add Point(20, 300)
Point(300, 100) + Point(20, 300)
- 最初、すんなりコードを読むことができたかといわれると正直そんなことはなかった
- ただ、ルールさえ覚えてしまえば、むしろ読みやすく感じる
- 「Scalaは書いていて気持ちいい!楽しい!!」という声はよく聞くし、私もそう感じる。
Scalaたーのしー! ₍₍⁽⁽(ી(´・ᴗ・`)ʃ)₎₎⁾⁾