1
~ Scala 入門勉強会 ~
山中 瑞起
2013/04/27
2
自己紹介
山中 瑞起(やまなかみずき)
■ Twitter:charlesvineyard
■ facebook:山中 瑞起
■ 現在フリーランスのSE
■ MilmSearchプロジェクトリーダー
 メーリングリスト検索アプリを開発するOSP
 Scalaで開発(1年くらい)
 Playフレームワーク勉強中
僭越ながら本日の講師を
 勤めさせていただきます!
よろしくお願いします!!
3
本日のアジェンダ
■ Scala、関数型言語について
■ 開発環境設定
■ HelloWorld
■ FizzBuzz を題材に Scala を学ぶ
 値を返す if
 値を返す for
 map と高階関数
 map と無名関数
 match-case(パターンマッチ)
 map と match-case
 再帰とクロージャとコンス(分ける方)
 末尾再帰とコンス(連結する方)
4
Scala ってどんな言語?
■ オブジェクト指向言語と関数型言語の
両方の特徴を持っている
 最初は書きやすくなった Java 程度の感覚で
大丈夫
 関数型言語って難しいイメージだけど、Scala
なら段階的に関数型言語っぽく書いていける
 だから勉強しやすくてオトク
5
Scala ってどんな言語?
■ JVM上で動く
 コンパイルすると Java の class ファイル
ができるということ
 Javaの資産がそのまま使える
■ 静的型付け&型推論
 コンパイル時の型チェックで安心安全
 型推論
➔冗長な型の記述が省略可
6
関数型言語って?
■ 関数が値
 Scalaでは関数(メソッド)が1つの型で表せられ
る
 変数に関数を入れることができる
■ 副作用がないプログラム
 副作用とは
➔ある変数の状態が変更され、
処理に影響が出ること
 副作用がないと
➔コードの理解がしやすくバグが入りにくい
➔並列処理がしやい
➔マルチコア対応しやすい
7
Mutable Immutable
■ Mutable(ミュータブル)
 変更できる
 変更するためにある
 状態が変わるので関数型言語的には嫌われる
■ Immutable(イミュータブル)
 変更できない
 関数型言語では好ましい
■ 変更できないのにプログラムは可能なのか?
■ 今日はそこんとこ注目
8
環境設定
■ Eclipse インストール
 公式サイトからダウンロード(種類は
classic)、解凍
 Workspace は差し支えなければデフォルトで
起動
■ Scalaプラグインインストール
 Scala IDE 公式サイト
http://scala-ide.org/
 Eclipse のバージョンに合ったインストール
用URLをクリックしてコピーしておく
 Eclipse の ヘルプ>新規ソフトウェアインス
トール から適宜インストール
9
HelloWorld
■ HelloWorld.scala を作成

新規(new)→Scalaオブジェクト
➔
名前「HelloWorld」
➔
main メソッド定義にチェック
➔
赤字部分だけ記述
■ 実行は「実行」→「実行」
または 緑の三角ボタン
object HelloWorld {
def main(args: Array[String]): Unit = {
println("Hello World")
}
}
10
HelloWorld.scala 詳細
object HelloWorld {
def main(args: Array[String]): Unit = {
println("Hello World")
}
}
オブジェクト宣言
● シングルトンオブジェクト
● 他言語で言うところの static メソッドが
定義できるクラス
オブジェクト名
def 関数名
(メソッド名)
関数定義
引数リスト
2つのときは(変数名: 型, 変数名: 型)の形
: に続けて型を書く
戻り値の型
引数と同様 : に続けて型を書く
Unit は戻り値がない時の型(void)。省略可
戻り値ありのときは = を書く
標準出力関数
11
FizzBuzz問題文
■ 1~20までの数を1行ずつ表示する
■ ただし、3で割りきれる数の場合は数の代
わりに「Fizz」と表示する
■ 5で割りきれる数の場合は数の代わりに
「Buzz」と表示する
■ 3でも5でも割りきれる数の場合は
「FizzBuzz」と表示する
12
FizzBuzz01~基本形~
object FizzBuzz01 {
def main(args: Array[String]) {
for (i <- 1 to 20) {
if (i % 3 == 0 && i % 5 ==0) {
println("FuzzBuzz")
} else if (i % 3 == 0) {
println("Fizz")
} else if (i % 5 == 0) {
println("Buzz")
} else {
println(i)
}
}
}
}
 他の言語と同じように、
 if を使って処理を書いてみましょう。
13
FizzBuzz01~基本形~
object FizzBuzz01 {
def main(args: Array[String]) {
for (i <- 1 to 20) {
if (i % 3 == 0 && i % 5 ==0) {
println("FuzzBuzz")
} else if (i % 3 == 0) {
println("Fizz")
} else if (i % 5 == 0) {
println("Buzz")
} else {
println(i)
}
}
}
}
14
FizzBuzz02 ~ifは値を返す~ の前説
// Good if
val valMsg = if (date.getDate % 2 == 0) {
"今日は偶数日です。"
} else {
"今日は奇数日です。"
}
println(valMsg)
// Bad if
var varMsg: String = null
if (date.getDate % 2 == 0) {
varMsg = "今日は偶数日です。"
} else {
varMsg = "今日は奇数日です。"
}
println(varMsg)
15
FizzBuzz02 ~ifは値を返す~
object FizzBuzz01 {
def main(args: Array[String]) {
for (i <- 1 to 20) {
if (i % 3 == 0 && i % 5 ==0) {
println("FuzzBuzz")
} else if (i % 3 == 0) {
println("Fizz")
} else if (i % 5 == 0) {
println("Buzz")
} else {
println(i)
}
}
}
}
object FizzBuzz02 {
def main(args: Array[String]) {
for (i <- 1 to 20) {
val line = if (i % 3 == 0 && i % 5 ==0) {
"FuzzBuzz"
} else if (i % 3 == 0) {
"Fizz"
} else if (i % 5 == 0) {
"Buzz"
} else {
i
}
println(line)
}
}
}
 val、値を返すifを使い、println が1つになるよう
 処理を書いてみましょう。
16
FizzBuzz02 ~ifは値を返す~
object FizzBuzz01 {
def main(args: Array[String]) {
for (i <- 1 to 20) {
if (i % 3 == 0 && i % 5 ==0) {
println("FuzzBuzz")
} else if (i % 3 == 0) {
println("Fizz")
} else if (i % 5 == 0) {
println("Buzz")
} else {
println(i)
}
}
}
}
object FizzBuzz02 {
def main(args: Array[String]) {
for (i <- 1 to 20) {
val line = if (i % 3 == 0 && i % 5 ==0) {
"FuzzBuzz"
} else if (i % 3 == 0) {
"Fizz"
} else if (i % 5 == 0) {
"Buzz"
} else {
i
}
println(line)
}
}
}
17
FizzBuzz03 ~for は yield で値を返す~ の
前説
val lines = for (i <- 1 to 5) yield
if (i == 1)
"壱"
else if (i == 2)
"弐"
else
"参以上"
lines foreach println
// 実行結果
壱
弐
参以上
参以上
参以上
18
FizzBuzz03 ~for は yield で値を返す~
object FizzBuzz03 {
def main(args: Array[String]) {
val lines = for (i <- 1 to 20) yield
if (i % 3 == 0 && i % 5 ==0) {
"FuzzBuzz"
} else if (i % 3 == 0) {
"Fizz"
} else if (i % 5 == 0) {
"Buzz"
} else {
i
}
lines foreach println
}
}
 値を返す for , foreach を使い
 処理を書いてみましょう。
19
FizzBuzz03 ~for は yield で値を返す~
object FizzBuzz03 {
def main(args: Array[String]) {
val lines = for (i <- 1 to 20) yield
if (i % 3 == 0 && i % 5 ==0) {
"FuzzBuzz"
} else if (i % 3 == 0) {
"Fizz"
} else if (i % 5 == 0) {
"Buzz"
} else {
i
}
lines foreach println
}
}
20
FizzBuzz04 ~ map と高階関数~ の前説
// map と高階関数を使った例
def twice(x: Int) = x * 2
(1 to 5) map { x => twice(x) } foreach println
// 省略形
(1 to 5) map { twice(_) } foreach println
(1 to 5) map { twice } foreach println
(1 to 5) map twice foreach println // やりすぎ?
// 実行結果
2
4
6
8
10
21
FizzBuzz04 ~ map と高階関数~
object FizzBuzz04 {
def main(args: Array[String]) {
def fizzbuzz(i: Int): String =
if (i % 3 == 0 && i % 5 == 0)
"FizzBuzz"
else if (i % 3 == 0)
"Fizz"
else if (i % 5 == 0)
"Buzz"
else
i.toString()
1 to 20 map { fizzbuzz } foreach println
}
}
 引数がInt型1つで、String型を返す
 fizzbuzz という名前の関数を定義し、
 map を使って処理を書いてみましょう。
 
22
FizzBuzz04 ~ map と高階関数~
object FizzBuzz04 {
def main(args: Array[String]) {
def fizzbuzz(i: Int): String =
if (i % 3 == 0 && i % 5 == 0)
"FizzBuzz"
else if (i % 3 == 0)
"Fizz"
else if (i % 5 == 0)
"Buzz"
else
i.toString()
1 to 20 map { fizzbuzz } foreach println
}
}
23
FizzBuzz04 ~ map と高階関数~ の後説
// foreach println も同じ形でした
(1 to 5) foreach { x => println(x) }
(1 to 5) foreach { println(_) }
(1 to 5) foreach println
24
FizzBuzz05 ~ map と無名関数~ の前説
(1 to 5) map { (x: Int) => x * 2 } foreach println
// 省略形
(1 to 5) map { x => x * 2 } foreach println
(1 to 5) map { _ * 2 } foreach println
// 実行結果
2
4
6
8
10
25
FizzBuzz05 ~ map と無名関数~
object FizzBuzz05 {
def main(args: Array[String]) {
(1 to 20) map { x =>
if (x % 3 == 0 && x % 5 == 0)
"FizzBuzz"
else if (x % 3 == 0)
"Fizz"
else if (x % 5 == 0)
"Buzz"
else
x.toString
} foreach println
}
}
 map と無名関数を使って
 処理を書いてみましょう。
 
26
FizzBuzz05 ~ map と無名関数~
object FizzBuzz05 {
def main(args: Array[String]) {
(1 to 20) map { x =>
if (x % 3 == 0 && x % 5 == 0)
"FizzBuzz"
else if (x % 3 == 0)
"Fizz"
else if (x % 5 == 0)
"Buzz"
else
x.toString
} foreach println
}
}
27
FizzBuzz06 ~ match-case ~ の前説 1/2
// 例1
val num = 1
val daiji = num match {
case 1 => "壱"
case 2 => "弐"
case _ => "参以上"
}
println(daiji)
// 実行結果
壱
28
FizzBuzz06 ~ match-case ~ の前説 2/2
// 例2
val date = new Date
val msg = date.getDate match {
case d if (d % 2 == 0) => "今日は偶数日です。"
case _ => "今日は奇数日です。"
}
println(msg)
// 実行結果(27日の場合)
今日は奇数日です。
29
FizzBuzz06 ~ match-case ~
object FizzBuzz06 {
def main(args: Array[String]) {
(1 to 20) map { num =>
num match {
case x if (x % 3 == 0 && x % 5 == 0) => "FizzBuzz"
case x if (x % 3 == 0) => "Fizz"
case x if (x % 5 == 0) => "Buzz"
case x => x.toString()
}
} foreach println
}
}
 match-case を使って
 処理を書いてみましょう。
 
30
FizzBuzz06 ~ match-case ~
object FizzBuzz06 {
def main(args: Array[String]) {
(1 to 20) map { num =>
num match {
case x if (x % 3 == 0 && x % 5 == 0) => "FizzBuzz"
case x if (x % 3 == 0) => "Fizz"
case x if (x % 5 == 0) => "Buzz"
case x => x.toString()
}
} foreach println
}
}
31
FizzBuzz07 ~ map と match の省略 ~ の前説
val daijis = (1 to 5) map { num =>
num match {
case 1 => "壱"
case 2 => "弐"
case _ => "参以上"
}
}
// 省略形
val daijis2 = (1 to 5) map {
case 1 => "壱"
case 2 => "弐"
case _ => "参以上"
}
32
FizzBuzz07 ~ map と match の省略 ~
object FizzBuzz07 {
def main(args: Array[String]) {
1 to 20 map {
case x if (x % 3 == 0 && x % 5 == 0) => "FizzBuzz"
case x if (x % 3 == 0) => "Fizz"
case x if (x % 5 == 0) => "Buzz"
case x => x.toString()
} foreach println
}
}
 match を省略した
 処理を書いてみましょう。
 
33
FizzBuzz07 ~ map と match の省略 ~
object FizzBuzz07 {
def main(args: Array[String]) {
1 to 20 map {
case x if (x % 3 == 0 && x % 5 == 0) => "FizzBuzz"
case x if (x % 3 == 0) => "Fizz"
case x if (x % 5 == 0) => "Buzz"
case x => x.toString()
} foreach println
}
}
34
FizzBuzz08 ~ 再帰、クロージャ、コンス(分ける) ~
import scala.collection.mutable.ListBuffer
object FizzBuzz08 {
def main(args: Array[String]) {
val lines = new ListBuffer[String]
def fizzbuzzRec(numbers: List[Int]) {
numbers match {
case Nil =>
case number :: tail => {
lines.append(number match {
case x if (x % 3 == 0 && x % 5 == 0) => "FizzBuzz"
case x if (x % 3 == 0) => "Fizz"
case x if (x % 5 == 0) => "Buzz"
case x => x.toString
})
fizzbuzzRec(tail)
}
}
}
fizzbuzzRec(1 to 20 toList)
lines foreach println
}
}
35
FizzBuzz09 ~ 末尾再帰、コンス(連結) ~
import scala.collection.mutable.ListBuffer
import scala.annotation.tailrec
object FizzBuzz09 {
def main(args: Array[String]) {
def fizzbuzzRec(numbers: List[Int]): List[String] = {
@tailrec
def fizzbuzzRecLocal(accumulator: List[String],
numbers: List[Int]): List[String] = {
numbers match {
case Nil => accumulator
case number :: tail => fizzbuzzRecLocal(
accumulator ::: List(
number match {
case x if (x % 3 == 0 && x % 5 == 0) => "FizzBuzz"
case x if (x % 3 == 0) => "Fizz"
case x if (x % 5 == 0) => "Buzz"
case x => x.toString
}
), tail
)
}
}
fizzbuzzRecLocal(Nil, numbers)
}
fizzbuzzRec(1 to 20 toList) foreach println
}
}
36
おすすめ書籍
■ オブジェクト指向プログラマが次に読む本
-Scalaで学ぶ関数脳入門
株式会社テクノロジックアート、
長瀬 嘉秀、 町田 修一
■ Scalaスケーラブルプログラミング第2版
Martin Odersky、Lex Spoon、Bill Venners、
羽生田 栄一
■ Scala実践プログラミング
―オープンソース徹底活用
小笠原 啓、尾崎 智仁、関 隆、 水島 宏太
■ Scalaプログラミング入門
デイビッド・ポラック、羽生田栄一、 大塚庸史

wakuwaku Scala ~Scala入門勉強会~ 資料

  • 1.
    1 ~ Scala 入門勉強会~ 山中 瑞起 2013/04/27
  • 2.
    2 自己紹介 山中 瑞起(やまなかみずき) ■ Twitter:charlesvineyard ■facebook:山中 瑞起 ■ 現在フリーランスのSE ■ MilmSearchプロジェクトリーダー  メーリングリスト検索アプリを開発するOSP  Scalaで開発(1年くらい)  Playフレームワーク勉強中 僭越ながら本日の講師を  勤めさせていただきます! よろしくお願いします!!
  • 3.
    3 本日のアジェンダ ■ Scala、関数型言語について ■ 開発環境設定 ■HelloWorld ■ FizzBuzz を題材に Scala を学ぶ  値を返す if  値を返す for  map と高階関数  map と無名関数  match-case(パターンマッチ)  map と match-case  再帰とクロージャとコンス(分ける方)  末尾再帰とコンス(連結する方)
  • 4.
    4 Scala ってどんな言語? ■ オブジェクト指向言語と関数型言語の 両方の特徴を持っている 最初は書きやすくなった Java 程度の感覚で 大丈夫  関数型言語って難しいイメージだけど、Scala なら段階的に関数型言語っぽく書いていける  だから勉強しやすくてオトク
  • 5.
    5 Scala ってどんな言語? ■ JVM上で動く コンパイルすると Java の class ファイル ができるということ  Javaの資産がそのまま使える ■ 静的型付け&型推論  コンパイル時の型チェックで安心安全  型推論 ➔冗長な型の記述が省略可
  • 6.
    6 関数型言語って? ■ 関数が値  Scalaでは関数(メソッド)が1つの型で表せられ る 変数に関数を入れることができる ■ 副作用がないプログラム  副作用とは ➔ある変数の状態が変更され、 処理に影響が出ること  副作用がないと ➔コードの理解がしやすくバグが入りにくい ➔並列処理がしやい ➔マルチコア対応しやすい
  • 7.
    7 Mutable Immutable ■ Mutable(ミュータブル) 変更できる  変更するためにある  状態が変わるので関数型言語的には嫌われる ■ Immutable(イミュータブル)  変更できない  関数型言語では好ましい ■ 変更できないのにプログラムは可能なのか? ■ 今日はそこんとこ注目
  • 8.
    8 環境設定 ■ Eclipse インストール 公式サイトからダウンロード(種類は classic)、解凍  Workspace は差し支えなければデフォルトで 起動 ■ Scalaプラグインインストール  Scala IDE 公式サイト http://scala-ide.org/  Eclipse のバージョンに合ったインストール 用URLをクリックしてコピーしておく  Eclipse の ヘルプ>新規ソフトウェアインス トール から適宜インストール
  • 9.
    9 HelloWorld ■ HelloWorld.scala を作成  新規(new)→Scalaオブジェクト ➔ 名前「HelloWorld」 ➔ mainメソッド定義にチェック ➔ 赤字部分だけ記述 ■ 実行は「実行」→「実行」 または 緑の三角ボタン object HelloWorld { def main(args: Array[String]): Unit = { println("Hello World") } }
  • 10.
    10 HelloWorld.scala 詳細 object HelloWorld{ def main(args: Array[String]): Unit = { println("Hello World") } } オブジェクト宣言 ● シングルトンオブジェクト ● 他言語で言うところの static メソッドが 定義できるクラス オブジェクト名 def 関数名 (メソッド名) 関数定義 引数リスト 2つのときは(変数名: 型, 変数名: 型)の形 : に続けて型を書く 戻り値の型 引数と同様 : に続けて型を書く Unit は戻り値がない時の型(void)。省略可 戻り値ありのときは = を書く 標準出力関数
  • 11.
    11 FizzBuzz問題文 ■ 1~20までの数を1行ずつ表示する ■ ただし、3で割りきれる数の場合は数の代 わりに「Fizz」と表示する ■5で割りきれる数の場合は数の代わりに 「Buzz」と表示する ■ 3でも5でも割りきれる数の場合は 「FizzBuzz」と表示する
  • 12.
    12 FizzBuzz01~基本形~ object FizzBuzz01 { defmain(args: Array[String]) { for (i <- 1 to 20) { if (i % 3 == 0 && i % 5 ==0) { println("FuzzBuzz") } else if (i % 3 == 0) { println("Fizz") } else if (i % 5 == 0) { println("Buzz") } else { println(i) } } } }  他の言語と同じように、  if を使って処理を書いてみましょう。
  • 13.
    13 FizzBuzz01~基本形~ object FizzBuzz01 { defmain(args: Array[String]) { for (i <- 1 to 20) { if (i % 3 == 0 && i % 5 ==0) { println("FuzzBuzz") } else if (i % 3 == 0) { println("Fizz") } else if (i % 5 == 0) { println("Buzz") } else { println(i) } } } }
  • 14.
    14 FizzBuzz02 ~ifは値を返す~ の前説 //Good if val valMsg = if (date.getDate % 2 == 0) { "今日は偶数日です。" } else { "今日は奇数日です。" } println(valMsg) // Bad if var varMsg: String = null if (date.getDate % 2 == 0) { varMsg = "今日は偶数日です。" } else { varMsg = "今日は奇数日です。" } println(varMsg)
  • 15.
    15 FizzBuzz02 ~ifは値を返す~ object FizzBuzz01{ def main(args: Array[String]) { for (i <- 1 to 20) { if (i % 3 == 0 && i % 5 ==0) { println("FuzzBuzz") } else if (i % 3 == 0) { println("Fizz") } else if (i % 5 == 0) { println("Buzz") } else { println(i) } } } } object FizzBuzz02 { def main(args: Array[String]) { for (i <- 1 to 20) { val line = if (i % 3 == 0 && i % 5 ==0) { "FuzzBuzz" } else if (i % 3 == 0) { "Fizz" } else if (i % 5 == 0) { "Buzz" } else { i } println(line) } } }  val、値を返すifを使い、println が1つになるよう  処理を書いてみましょう。
  • 16.
    16 FizzBuzz02 ~ifは値を返す~ object FizzBuzz01{ def main(args: Array[String]) { for (i <- 1 to 20) { if (i % 3 == 0 && i % 5 ==0) { println("FuzzBuzz") } else if (i % 3 == 0) { println("Fizz") } else if (i % 5 == 0) { println("Buzz") } else { println(i) } } } } object FizzBuzz02 { def main(args: Array[String]) { for (i <- 1 to 20) { val line = if (i % 3 == 0 && i % 5 ==0) { "FuzzBuzz" } else if (i % 3 == 0) { "Fizz" } else if (i % 5 == 0) { "Buzz" } else { i } println(line) } } }
  • 17.
    17 FizzBuzz03 ~for はyield で値を返す~ の 前説 val lines = for (i <- 1 to 5) yield if (i == 1) "壱" else if (i == 2) "弐" else "参以上" lines foreach println // 実行結果 壱 弐 参以上 参以上 参以上
  • 18.
    18 FizzBuzz03 ~for はyield で値を返す~ object FizzBuzz03 { def main(args: Array[String]) { val lines = for (i <- 1 to 20) yield if (i % 3 == 0 && i % 5 ==0) { "FuzzBuzz" } else if (i % 3 == 0) { "Fizz" } else if (i % 5 == 0) { "Buzz" } else { i } lines foreach println } }  値を返す for , foreach を使い  処理を書いてみましょう。
  • 19.
    19 FizzBuzz03 ~for はyield で値を返す~ object FizzBuzz03 { def main(args: Array[String]) { val lines = for (i <- 1 to 20) yield if (i % 3 == 0 && i % 5 ==0) { "FuzzBuzz" } else if (i % 3 == 0) { "Fizz" } else if (i % 5 == 0) { "Buzz" } else { i } lines foreach println } }
  • 20.
    20 FizzBuzz04 ~ mapと高階関数~ の前説 // map と高階関数を使った例 def twice(x: Int) = x * 2 (1 to 5) map { x => twice(x) } foreach println // 省略形 (1 to 5) map { twice(_) } foreach println (1 to 5) map { twice } foreach println (1 to 5) map twice foreach println // やりすぎ? // 実行結果 2 4 6 8 10
  • 21.
    21 FizzBuzz04 ~ mapと高階関数~ object FizzBuzz04 { def main(args: Array[String]) { def fizzbuzz(i: Int): String = if (i % 3 == 0 && i % 5 == 0) "FizzBuzz" else if (i % 3 == 0) "Fizz" else if (i % 5 == 0) "Buzz" else i.toString() 1 to 20 map { fizzbuzz } foreach println } }  引数がInt型1つで、String型を返す  fizzbuzz という名前の関数を定義し、  map を使って処理を書いてみましょう。  
  • 22.
    22 FizzBuzz04 ~ mapと高階関数~ object FizzBuzz04 { def main(args: Array[String]) { def fizzbuzz(i: Int): String = if (i % 3 == 0 && i % 5 == 0) "FizzBuzz" else if (i % 3 == 0) "Fizz" else if (i % 5 == 0) "Buzz" else i.toString() 1 to 20 map { fizzbuzz } foreach println } }
  • 23.
    23 FizzBuzz04 ~ mapと高階関数~ の後説 // foreach println も同じ形でした (1 to 5) foreach { x => println(x) } (1 to 5) foreach { println(_) } (1 to 5) foreach println
  • 24.
    24 FizzBuzz05 ~ mapと無名関数~ の前説 (1 to 5) map { (x: Int) => x * 2 } foreach println // 省略形 (1 to 5) map { x => x * 2 } foreach println (1 to 5) map { _ * 2 } foreach println // 実行結果 2 4 6 8 10
  • 25.
    25 FizzBuzz05 ~ mapと無名関数~ object FizzBuzz05 { def main(args: Array[String]) { (1 to 20) map { x => if (x % 3 == 0 && x % 5 == 0) "FizzBuzz" else if (x % 3 == 0) "Fizz" else if (x % 5 == 0) "Buzz" else x.toString } foreach println } }  map と無名関数を使って  処理を書いてみましょう。  
  • 26.
    26 FizzBuzz05 ~ mapと無名関数~ object FizzBuzz05 { def main(args: Array[String]) { (1 to 20) map { x => if (x % 3 == 0 && x % 5 == 0) "FizzBuzz" else if (x % 3 == 0) "Fizz" else if (x % 5 == 0) "Buzz" else x.toString } foreach println } }
  • 27.
    27 FizzBuzz06 ~ match-case~ の前説 1/2 // 例1 val num = 1 val daiji = num match { case 1 => "壱" case 2 => "弐" case _ => "参以上" } println(daiji) // 実行結果 壱
  • 28.
    28 FizzBuzz06 ~ match-case~ の前説 2/2 // 例2 val date = new Date val msg = date.getDate match { case d if (d % 2 == 0) => "今日は偶数日です。" case _ => "今日は奇数日です。" } println(msg) // 実行結果(27日の場合) 今日は奇数日です。
  • 29.
    29 FizzBuzz06 ~ match-case~ object FizzBuzz06 { def main(args: Array[String]) { (1 to 20) map { num => num match { case x if (x % 3 == 0 && x % 5 == 0) => "FizzBuzz" case x if (x % 3 == 0) => "Fizz" case x if (x % 5 == 0) => "Buzz" case x => x.toString() } } foreach println } }  match-case を使って  処理を書いてみましょう。  
  • 30.
    30 FizzBuzz06 ~ match-case~ object FizzBuzz06 { def main(args: Array[String]) { (1 to 20) map { num => num match { case x if (x % 3 == 0 && x % 5 == 0) => "FizzBuzz" case x if (x % 3 == 0) => "Fizz" case x if (x % 5 == 0) => "Buzz" case x => x.toString() } } foreach println } }
  • 31.
    31 FizzBuzz07 ~ mapと match の省略 ~ の前説 val daijis = (1 to 5) map { num => num match { case 1 => "壱" case 2 => "弐" case _ => "参以上" } } // 省略形 val daijis2 = (1 to 5) map { case 1 => "壱" case 2 => "弐" case _ => "参以上" }
  • 32.
    32 FizzBuzz07 ~ mapと match の省略 ~ object FizzBuzz07 { def main(args: Array[String]) { 1 to 20 map { case x if (x % 3 == 0 && x % 5 == 0) => "FizzBuzz" case x if (x % 3 == 0) => "Fizz" case x if (x % 5 == 0) => "Buzz" case x => x.toString() } foreach println } }  match を省略した  処理を書いてみましょう。  
  • 33.
    33 FizzBuzz07 ~ mapと match の省略 ~ object FizzBuzz07 { def main(args: Array[String]) { 1 to 20 map { case x if (x % 3 == 0 && x % 5 == 0) => "FizzBuzz" case x if (x % 3 == 0) => "Fizz" case x if (x % 5 == 0) => "Buzz" case x => x.toString() } foreach println } }
  • 34.
    34 FizzBuzz08 ~ 再帰、クロージャ、コンス(分ける)~ import scala.collection.mutable.ListBuffer object FizzBuzz08 { def main(args: Array[String]) { val lines = new ListBuffer[String] def fizzbuzzRec(numbers: List[Int]) { numbers match { case Nil => case number :: tail => { lines.append(number match { case x if (x % 3 == 0 && x % 5 == 0) => "FizzBuzz" case x if (x % 3 == 0) => "Fizz" case x if (x % 5 == 0) => "Buzz" case x => x.toString }) fizzbuzzRec(tail) } } } fizzbuzzRec(1 to 20 toList) lines foreach println } }
  • 35.
    35 FizzBuzz09 ~ 末尾再帰、コンス(連結)~ import scala.collection.mutable.ListBuffer import scala.annotation.tailrec object FizzBuzz09 { def main(args: Array[String]) { def fizzbuzzRec(numbers: List[Int]): List[String] = { @tailrec def fizzbuzzRecLocal(accumulator: List[String], numbers: List[Int]): List[String] = { numbers match { case Nil => accumulator case number :: tail => fizzbuzzRecLocal( accumulator ::: List( number match { case x if (x % 3 == 0 && x % 5 == 0) => "FizzBuzz" case x if (x % 3 == 0) => "Fizz" case x if (x % 5 == 0) => "Buzz" case x => x.toString } ), tail ) } } fizzbuzzRecLocal(Nil, numbers) } fizzbuzzRec(1 to 20 toList) foreach println } }
  • 36.
    36 おすすめ書籍 ■ オブジェクト指向プログラマが次に読む本 -Scalaで学ぶ関数脳入門 株式会社テクノロジックアート、 長瀬 嘉秀、町田 修一 ■ Scalaスケーラブルプログラミング第2版 Martin Odersky、Lex Spoon、Bill Venners、 羽生田 栄一 ■ Scala実践プログラミング ―オープンソース徹底活用 小笠原 啓、尾崎 智仁、関 隆、 水島 宏太 ■ Scalaプログラミング入門 デイビッド・ポラック、羽生田栄一、 大塚庸史

Editor's Notes

  • #10 次ページのサンプルプログラムで、次の項目をマスターします クラス宣言とオブジェクト宣言 変数宣言 変更できる変数 変更できない変数 メソッド宣言 省略記法 Sample1.scala ファイルで説明した後、 Sample2.scala で省略記法バージョンを書いてみます
  • #11 class Person { def getMessage(): String = { return &quot;Hello world!&quot; } def printMessage(): Unit = { println(&quot;wakuwaku Scala!&quot;) } } object Main { def main(args: Array[String]): Unit = { val person1 = new Person() println(person1.getMessage()) var person2 = new Person() person2.printMessage() person2 = new Person() person2.printMessage() } } class Person2 { def getMessage = &quot;Hello world!&quot; def printMessage { println(&quot;wakuwaku Scala!&quot;) } } object Main2 { def main(args: Array[String]) { val person1 = new Person println(person1.getMessage) var person2 = new Person person2.printMessage person2 = new Person person2.printMessage } }