36
1 Scala 入門勉強会 ~ 山中 瑞起 2013/04/27

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

Embed Size (px)

DESCRIPTION

2013/04/27 wakuwaku Scala ~Scala入門勉強会~ 資料 資料中のソースコードは Github にリポジトリがあります。 https://github.com/charlesvineyard/wakuwaku-scala1

Citation preview

Page 1: wakuwaku Scala ~Scala入門勉強会~ 資料

1

~ Scala 入門勉強会 ~

山中 瑞起2013/04/27

Page 2: wakuwaku Scala ~Scala入門勉強会~ 資料

2

自己紹介

山中 瑞起(やまなかみずき)

■ Twitter:charlesvineyard■ facebook:山中 瑞起

■ 現在フリーランスのSE■ MilmSearchプロジェクトリーダー

メーリングリスト検索アプリを開発するOSP Scalaで開発(1年くらい) Playフレームワーク勉強中

僭越ながら本日の講師を 勤めさせていただきます!

よろしくお願いします!!

Page 3: wakuwaku Scala ~Scala入門勉強会~ 資料

3

本日のアジェンダ

■Scala、関数型言語について■開発環境設定■HelloWorld■FizzBuzz を題材に Scala を学ぶ

値を返す if 値を返す for map と高階関数 map と無名関数 match-case(パターンマッチ) map と match-case 再帰とクロージャとコンス(分ける方) 末尾再帰とコンス(連結する方)

Page 4: wakuwaku Scala ~Scala入門勉強会~ 資料

4

Scala ってどんな言語?

■オブジェクト指向言語と関数型言語の両方の特徴を持っている

最初は書きやすくなった Java 程度の感覚で大丈夫

関数型言語って難しいイメージだけど、Scala なら段階的に関数型言語っぽく書いていける

だから勉強しやすくてオトク

Page 5: wakuwaku Scala ~Scala入門勉強会~ 資料

5

Scala ってどんな言語?

■JVM上で動く コンパイルすると Java の class ファイルができるということ

Javaの資産がそのまま使える

■静的型付け&型推論 コンパイル時の型チェックで安心安全 型推論

➔冗長な型の記述が省略可

Page 6: wakuwaku Scala ~Scala入門勉強会~ 資料

6

関数型言語って?

■関数が値 Scalaでは関数(メソッド)が1つの型で表せられる

変数に関数を入れることができる

■副作用がないプログラム 副作用とは

➔ある変数の状態が変更され、処理に影響が出ること

副作用がないと➔コードの理解がしやすくバグが入りにくい➔並列処理がしやい➔マルチコア対応しやすい

Page 7: wakuwaku Scala ~Scala入門勉強会~ 資料

7

Mutable Immutable

■Mutable(ミュータブル) 変更できる 変更するためにある 状態が変わるので関数型言語的には嫌われる

■Immutable(イミュータブル) 変更できない 関数型言語では好ましい

■変更できないのにプログラムは可能なのか?■今日はそこんとこ注目

Page 8: wakuwaku Scala ~Scala入門勉強会~ 資料

8

環境設定

■ Eclipse インストール 公式サイトからダウンロード(種類はclassic)、解凍

Workspace は差し支えなければデフォルトで起動

■ Scalaプラグインインストール Scala IDE 公式サイト http://scala-ide.org/

Eclipse のバージョンに合ったインストール用URLをクリックしてコピーしておく

Eclipse の ヘルプ>新規ソフトウェアインストール から適宜インストール

Page 9: wakuwaku Scala ~Scala入門勉強会~ 資料

9

HelloWorld

■HelloWorld.scala を作成 新規(new)→Scalaオブジェクト

➔名前「HelloWorld」➔ main メソッド定義にチェック➔赤字部分だけ記述

■実行は「実行」→「実行」 または 緑の三角ボタン

object HelloWorld { def main(args: Array[String]): Unit = { println("Hello World") }}

Page 10: wakuwaku Scala ~Scala入門勉強会~ 資料

10

HelloWorld.scala 詳細

object HelloWorld { def main(args: Array[String]): Unit = { println("Hello World") }}

オブジェクト宣言● シングルトンオブジェクト● 他言語で言うところの static メソッドが

定義できるクラス

オブジェクト名

def 関数名(メソッド名)

関数定義

引数リスト

2つのときは(変数名: 型, 変数名: 型)の形: に続けて型を書く

戻り値の型

引数と同様 : に続けて型を書くUnit は戻り値がない時の型(void)。省略可戻り値ありのときは = を書く

標準出力関数

Page 11: wakuwaku Scala ~Scala入門勉強会~ 資料

11

FizzBuzz問題文

■1~20までの数を1行ずつ表示する■ただし、3で割りきれる数の場合は数の代わりに「Fizz」と表示する

■5で割りきれる数の場合は数の代わりに「Buzz」と表示する

■3でも5でも割りきれる数の場合は「FizzBuzz」と表示する

Page 12: wakuwaku Scala ~Scala入門勉強会~ 資料

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 を使って処理を書いてみましょう。

Page 13: wakuwaku Scala ~Scala入門勉強会~ 資料

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) } } }}

Page 14: wakuwaku Scala ~Scala入門勉強会~ 資料

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)

Page 15: wakuwaku Scala ~Scala入門勉強会~ 資料

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つになるよう 処理を書いてみましょう。

Page 16: wakuwaku Scala ~Scala入門勉強会~ 資料

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) } }}

Page 17: wakuwaku Scala ~Scala入門勉強会~ 資料

17

FizzBuzz03 ~for は yield で値を返す~ の前説

val lines = for (i <- 1 to 5) yield if (i == 1) "壱" else if (i == 2) "弐" else "参以上"

lines foreach println

// 実行結果壱弐参以上参以上参以上

Page 18: wakuwaku Scala ~Scala入門勉強会~ 資料

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 を使い 処理を書いてみましょう。

Page 19: wakuwaku Scala ~Scala入門勉強会~ 資料

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 }}

Page 20: wakuwaku Scala ~Scala入門勉強会~ 資料

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 // やりすぎ?

// 実行結果246810

Page 21: wakuwaku Scala ~Scala入門勉強会~ 資料

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 を使って処理を書いてみましょう。 

Page 22: wakuwaku Scala ~Scala入門勉強会~ 資料

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 }}

Page 23: wakuwaku Scala ~Scala入門勉強会~ 資料

23

FizzBuzz04 ~ map と高階関数~ の後説

// foreach println も同じ形でした

(1 to 5) foreach { x => println(x) } (1 to 5) foreach { println(_) } (1 to 5) foreach println

Page 24: wakuwaku Scala ~Scala入門勉強会~ 資料

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

// 実行結果246810

Page 25: wakuwaku Scala ~Scala入門勉強会~ 資料

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 と無名関数を使って 処理を書いてみましょう。 

Page 26: wakuwaku Scala ~Scala入門勉強会~ 資料

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 }}

Page 27: wakuwaku Scala ~Scala入門勉強会~ 資料

27

FizzBuzz06 ~ match-case ~ の前説 1/2

// 例1 val num = 1

val daiji = num match { case 1 => "壱" case 2 => "弐" case _ => "参以上" }

println(daiji)

// 実行結果壱

Page 28: wakuwaku Scala ~Scala入門勉強会~ 資料

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日の場合)今日は奇数日です。

Page 29: wakuwaku Scala ~Scala入門勉強会~ 資料

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 を使って 処理を書いてみましょう。 

Page 30: wakuwaku Scala ~Scala入門勉強会~ 資料

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 }}

Page 31: wakuwaku Scala ~Scala入門勉強会~ 資料

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 _ => "参以上" }

Page 32: wakuwaku Scala ~Scala入門勉強会~ 資料

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 を省略した 処理を書いてみましょう。 

Page 33: wakuwaku Scala ~Scala入門勉強会~ 資料

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 }}

Page 34: wakuwaku Scala ~Scala入門勉強会~ 資料

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 }}

Page 35: wakuwaku Scala ~Scala入門勉強会~ 資料

35

FizzBuzz09 ~ 末尾再帰、コンス(連結) ~

import scala.collection.mutable.ListBufferimport scala.annotation.tailrecobject 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 }}

Page 36: wakuwaku Scala ~Scala入門勉強会~ 資料

36

おすすめ書籍

■ オブジェクト指向プログラマが次に読む本-Scalaで学ぶ関数脳入門 株式会社テクノロジックアート、長瀬 嘉秀、 町田 修一

■ Scalaスケーラブルプログラミング第2版Martin Odersky、Lex Spoon、Bill Venners、 羽生田 栄一

■ Scala実践プログラミング―オープンソース徹底活用小笠原 啓、尾崎 智仁、関 隆、 水島 宏太

■ Scalaプログラミング入門 デイビッド・ポラック、羽生田栄一、 大塚庸史