SlideShare a Scribd company logo
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プログラミング入門
デイビッド・ポラック、羽生田栄一、 大塚庸史

More Related Content

What's hot

x86x64 SSE4.2 POPCNT
x86x64 SSE4.2 POPCNTx86x64 SSE4.2 POPCNT
x86x64 SSE4.2 POPCNT
takesako
 
CG2013 05
CG2013 05CG2013 05
CG2013 05
shiozawa_h
 
RでGISハンズオンセッション
RでGISハンズオンセッションRでGISハンズオンセッション
RでGISハンズオンセッションarctic_tern265
 
Goをカンストさせる話
Goをカンストさせる話Goをカンストさせる話
Goをカンストさせる話
Moriyoshi Koizumi
 
KMC JavaScriptから始めるプログラミング2016 第一回
KMC JavaScriptから始めるプログラミング2016 第一回KMC JavaScriptから始めるプログラミング2016 第一回
KMC JavaScriptから始めるプログラミング2016 第一回
kyoto university
 
brainfuckを吐く自作言語bf-reusable
brainfuckを吐く自作言語bf-reusablebrainfuckを吐く自作言語bf-reusable
brainfuckを吐く自作言語bf-reusable
roodni
 
実用Brainf*ckプログラミング
実用Brainf*ckプログラミング実用Brainf*ckプログラミング
実用Brainf*ckプログラミング
京大 マイコンクラブ
 
CG2013 03
CG2013 03CG2013 03
CG2013 03
shiozawa_h
 
機械学習
機械学習機械学習
機械学習
ssusere8ae711
 
C++11概要 ライブラリ編
C++11概要 ライブラリ編C++11概要 ライブラリ編
C++11概要 ライブラリ編egtra
 
Gnuplotあれこれ
GnuplotあれこれGnuplotあれこれ
Gnuplotあれこれ
Maruyama Tetsutaro
 
何もないところから数を作る
何もないところから数を作る何もないところから数を作る
何もないところから数を作る
Taketo Sano
 
関数型プログラミング入門 with OCaml
関数型プログラミング入門 with OCaml関数型プログラミング入門 with OCaml
関数型プログラミング入門 with OCaml
Haruka Oikawa
 
ベクトル空間と表現行列
ベクトル空間と表現行列ベクトル空間と表現行列
ベクトル空間と表現行列
政孝 鍋島
 
ベクトル空間と表現行列
ベクトル空間と表現行列ベクトル空間と表現行列
ベクトル空間と表現行列
nabeshimamasataka
 
Real World OCamlを読んでLispと協調してみた
Real World OCamlを読んでLispと協調してみたReal World OCamlを読んでLispと協調してみた
Real World OCamlを読んでLispと協調してみたblackenedgold
 
何もないところから数を作る
何もないところから数を作る何もないところから数を作る
何もないところから数を作る
Taketo Sano
 

What's hot (20)

x86x64 SSE4.2 POPCNT
x86x64 SSE4.2 POPCNTx86x64 SSE4.2 POPCNT
x86x64 SSE4.2 POPCNT
 
CG2013 05
CG2013 05CG2013 05
CG2013 05
 
RでGISハンズオンセッション
RでGISハンズオンセッションRでGISハンズオンセッション
RでGISハンズオンセッション
 
Goをカンストさせる話
Goをカンストさせる話Goをカンストさせる話
Goをカンストさせる話
 
KMC JavaScriptから始めるプログラミング2016 第一回
KMC JavaScriptから始めるプログラミング2016 第一回KMC JavaScriptから始めるプログラミング2016 第一回
KMC JavaScriptから始めるプログラミング2016 第一回
 
brainfuckを吐く自作言語bf-reusable
brainfuckを吐く自作言語bf-reusablebrainfuckを吐く自作言語bf-reusable
brainfuckを吐く自作言語bf-reusable
 
実用Brainf*ckプログラミング
実用Brainf*ckプログラミング実用Brainf*ckプログラミング
実用Brainf*ckプログラミング
 
RでGIS
RでGISRでGIS
RでGIS
 
CG2013 03
CG2013 03CG2013 03
CG2013 03
 
初めてのSTL
初めてのSTL初めてのSTL
初めてのSTL
 
機械学習
機械学習機械学習
機械学習
 
C++11概要 ライブラリ編
C++11概要 ライブラリ編C++11概要 ライブラリ編
C++11概要 ライブラリ編
 
Gnuplotあれこれ
GnuplotあれこれGnuplotあれこれ
Gnuplotあれこれ
 
何もないところから数を作る
何もないところから数を作る何もないところから数を作る
何もないところから数を作る
 
関数型プログラミング入門 with OCaml
関数型プログラミング入門 with OCaml関数型プログラミング入門 with OCaml
関数型プログラミング入門 with OCaml
 
python-geohex
python-geohexpython-geohex
python-geohex
 
ベクトル空間と表現行列
ベクトル空間と表現行列ベクトル空間と表現行列
ベクトル空間と表現行列
 
ベクトル空間と表現行列
ベクトル空間と表現行列ベクトル空間と表現行列
ベクトル空間と表現行列
 
Real World OCamlを読んでLispと協調してみた
Real World OCamlを読んでLispと協調してみたReal World OCamlを読んでLispと協調してみた
Real World OCamlを読んでLispと協調してみた
 
何もないところから数を作る
何もないところから数を作る何もないところから数を作る
何もないところから数を作る
 

Viewers also liked

Mizukiryu refactering-20110821
Mizukiryu refactering-20110821Mizukiryu refactering-20110821
Mizukiryu refactering-20110821
Mizuki Yamanaka
 
バージョン管理の断捨離
バージョン管理の断捨離バージョン管理の断捨離
バージョン管理の断捨離Kazushi Kamegawa
 
【勉強会】パターンによるソフトウェア構成管理
【勉強会】パターンによるソフトウェア構成管理【勉強会】パターンによるソフトウェア構成管理
【勉強会】パターンによるソフトウェア構成管理zuisener .
 
構成管理のアンチパターン
構成管理のアンチパターン構成管理のアンチパターン
構成管理のアンチパターン
akipii Oga
 
Jenkinsを利用したCI、弊社導入事例
Jenkinsを利用したCI、弊社導入事例Jenkinsを利用したCI、弊社導入事例
Jenkinsを利用したCI、弊社導入事例
Ryoichi Obara
 
Jenkinsのある生活
Jenkinsのある生活Jenkinsのある生活
Jenkinsのある生活
Takaya Funabiki
 
Startup jenkins!
Startup jenkins!Startup jenkins!
Startup jenkins!
Kanu orz
 

Viewers also liked (7)

Mizukiryu refactering-20110821
Mizukiryu refactering-20110821Mizukiryu refactering-20110821
Mizukiryu refactering-20110821
 
バージョン管理の断捨離
バージョン管理の断捨離バージョン管理の断捨離
バージョン管理の断捨離
 
【勉強会】パターンによるソフトウェア構成管理
【勉強会】パターンによるソフトウェア構成管理【勉強会】パターンによるソフトウェア構成管理
【勉強会】パターンによるソフトウェア構成管理
 
構成管理のアンチパターン
構成管理のアンチパターン構成管理のアンチパターン
構成管理のアンチパターン
 
Jenkinsを利用したCI、弊社導入事例
Jenkinsを利用したCI、弊社導入事例Jenkinsを利用したCI、弊社導入事例
Jenkinsを利用したCI、弊社導入事例
 
Jenkinsのある生活
Jenkinsのある生活Jenkinsのある生活
Jenkinsのある生活
 
Startup jenkins!
Startup jenkins!Startup jenkins!
Startup jenkins!
 

Recently uploaded

MPAなWebフレームワーク、Astroの紹介 (その2) 2024/05/24の勉強会で発表されたものです。
MPAなWebフレームワーク、Astroの紹介 (その2) 2024/05/24の勉強会で発表されたものです。MPAなWebフレームワーク、Astroの紹介 (その2) 2024/05/24の勉強会で発表されたものです。
MPAなWebフレームワーク、Astroの紹介 (その2) 2024/05/24の勉強会で発表されたものです。
iPride Co., Ltd.
 
TaketoFujikawa_物語のコンセプトに基づく情報アクセス手法の基礎検討_JSAI2024
TaketoFujikawa_物語のコンセプトに基づく情報アクセス手法の基礎検討_JSAI2024TaketoFujikawa_物語のコンセプトに基づく情報アクセス手法の基礎検討_JSAI2024
TaketoFujikawa_物語のコンセプトに基づく情報アクセス手法の基礎検討_JSAI2024
Matsushita Laboratory
 
単腕マニピュレータによる 複数物体の同時組み立ての 基礎的考察 / Basic Approach to Robotic Assembly of Multi...
単腕マニピュレータによる 複数物体の同時組み立ての 基礎的考察 / Basic Approach to Robotic Assembly of Multi...単腕マニピュレータによる 複数物体の同時組み立ての 基礎的考察 / Basic Approach to Robotic Assembly of Multi...
単腕マニピュレータによる 複数物体の同時組み立ての 基礎的考察 / Basic Approach to Robotic Assembly of Multi...
Fukuoka Institute of Technology
 
FIDO Alliance Osaka Seminar: LY-DOCOMO-KDDI-Mercari Panel.pdf
FIDO Alliance Osaka Seminar: LY-DOCOMO-KDDI-Mercari Panel.pdfFIDO Alliance Osaka Seminar: LY-DOCOMO-KDDI-Mercari Panel.pdf
FIDO Alliance Osaka Seminar: LY-DOCOMO-KDDI-Mercari Panel.pdf
FIDO Alliance
 
FIDO Alliance Osaka Seminar: PlayStation Passkey Deployment Case Study.pdf
FIDO Alliance Osaka Seminar: PlayStation Passkey Deployment Case Study.pdfFIDO Alliance Osaka Seminar: PlayStation Passkey Deployment Case Study.pdf
FIDO Alliance Osaka Seminar: PlayStation Passkey Deployment Case Study.pdf
FIDO Alliance
 
論文紹介:When Visual Prompt Tuning Meets Source-Free Domain Adaptive Semantic Seg...
論文紹介:When Visual Prompt Tuning Meets Source-Free Domain Adaptive Semantic Seg...論文紹介:When Visual Prompt Tuning Meets Source-Free Domain Adaptive Semantic Seg...
論文紹介:When Visual Prompt Tuning Meets Source-Free Domain Adaptive Semantic Seg...
Toru Tamaki
 
論文紹介: Offline Q-Learning on diverse Multi-Task data both scales and generalizes
論文紹介: Offline Q-Learning on diverse Multi-Task data both scales and generalizes論文紹介: Offline Q-Learning on diverse Multi-Task data both scales and generalizes
論文紹介: Offline Q-Learning on diverse Multi-Task data both scales and generalizes
atsushi061452
 
FIDO Alliance Osaka Seminar: CloudGate.pdf
FIDO Alliance Osaka Seminar: CloudGate.pdfFIDO Alliance Osaka Seminar: CloudGate.pdf
FIDO Alliance Osaka Seminar: CloudGate.pdf
FIDO Alliance
 
LoRaWAN 4チャンネル電流センサー・コンバーター CS01-LB 日本語マニュアル
LoRaWAN 4チャンネル電流センサー・コンバーター CS01-LB 日本語マニュアルLoRaWAN 4チャンネル電流センサー・コンバーター CS01-LB 日本語マニュアル
LoRaWAN 4チャンネル電流センサー・コンバーター CS01-LB 日本語マニュアル
CRI Japan, Inc.
 
【DLゼミ】XFeat: Accelerated Features for Lightweight Image Matching
【DLゼミ】XFeat: Accelerated Features for Lightweight Image Matching【DLゼミ】XFeat: Accelerated Features for Lightweight Image Matching
【DLゼミ】XFeat: Accelerated Features for Lightweight Image Matching
harmonylab
 
【AI論文解説】Consistency ModelとRectified Flow
【AI論文解説】Consistency ModelとRectified Flow【AI論文解説】Consistency ModelとRectified Flow
【AI論文解説】Consistency ModelとRectified Flow
Sony - Neural Network Libraries
 
CS集会#13_なるほどわからん通信技術 発表資料
CS集会#13_なるほどわからん通信技術 発表資料CS集会#13_なるほどわからん通信技術 発表資料
CS集会#13_なるほどわからん通信技術 発表資料
Yuuitirou528 default
 
FIDO Alliance Osaka Seminar: Welcome Slides.pdf
FIDO Alliance Osaka Seminar: Welcome Slides.pdfFIDO Alliance Osaka Seminar: Welcome Slides.pdf
FIDO Alliance Osaka Seminar: Welcome Slides.pdf
FIDO Alliance
 
2024年度_サイバーエージェント_新卒研修「データベースの歴史」.pptx
2024年度_サイバーエージェント_新卒研修「データベースの歴史」.pptx2024年度_サイバーエージェント_新卒研修「データベースの歴史」.pptx
2024年度_サイバーエージェント_新卒研修「データベースの歴史」.pptx
yassun7010
 
YugabyteDB適用に向けた取り組みと隠れた魅力 (DSS Asia 2024 発表資料)
YugabyteDB適用に向けた取り組みと隠れた魅力 (DSS Asia 2024 発表資料)YugabyteDB適用に向けた取り組みと隠れた魅力 (DSS Asia 2024 発表資料)
YugabyteDB適用に向けた取り組みと隠れた魅力 (DSS Asia 2024 発表資料)
NTT DATA Technology & Innovation
 
FIDO Alliance Osaka Seminar: NEC & Yubico Panel.pdf
FIDO Alliance Osaka Seminar: NEC & Yubico Panel.pdfFIDO Alliance Osaka Seminar: NEC & Yubico Panel.pdf
FIDO Alliance Osaka Seminar: NEC & Yubico Panel.pdf
FIDO Alliance
 

Recently uploaded (16)

MPAなWebフレームワーク、Astroの紹介 (その2) 2024/05/24の勉強会で発表されたものです。
MPAなWebフレームワーク、Astroの紹介 (その2) 2024/05/24の勉強会で発表されたものです。MPAなWebフレームワーク、Astroの紹介 (その2) 2024/05/24の勉強会で発表されたものです。
MPAなWebフレームワーク、Astroの紹介 (その2) 2024/05/24の勉強会で発表されたものです。
 
TaketoFujikawa_物語のコンセプトに基づく情報アクセス手法の基礎検討_JSAI2024
TaketoFujikawa_物語のコンセプトに基づく情報アクセス手法の基礎検討_JSAI2024TaketoFujikawa_物語のコンセプトに基づく情報アクセス手法の基礎検討_JSAI2024
TaketoFujikawa_物語のコンセプトに基づく情報アクセス手法の基礎検討_JSAI2024
 
単腕マニピュレータによる 複数物体の同時組み立ての 基礎的考察 / Basic Approach to Robotic Assembly of Multi...
単腕マニピュレータによる 複数物体の同時組み立ての 基礎的考察 / Basic Approach to Robotic Assembly of Multi...単腕マニピュレータによる 複数物体の同時組み立ての 基礎的考察 / Basic Approach to Robotic Assembly of Multi...
単腕マニピュレータによる 複数物体の同時組み立ての 基礎的考察 / Basic Approach to Robotic Assembly of Multi...
 
FIDO Alliance Osaka Seminar: LY-DOCOMO-KDDI-Mercari Panel.pdf
FIDO Alliance Osaka Seminar: LY-DOCOMO-KDDI-Mercari Panel.pdfFIDO Alliance Osaka Seminar: LY-DOCOMO-KDDI-Mercari Panel.pdf
FIDO Alliance Osaka Seminar: LY-DOCOMO-KDDI-Mercari Panel.pdf
 
FIDO Alliance Osaka Seminar: PlayStation Passkey Deployment Case Study.pdf
FIDO Alliance Osaka Seminar: PlayStation Passkey Deployment Case Study.pdfFIDO Alliance Osaka Seminar: PlayStation Passkey Deployment Case Study.pdf
FIDO Alliance Osaka Seminar: PlayStation Passkey Deployment Case Study.pdf
 
論文紹介:When Visual Prompt Tuning Meets Source-Free Domain Adaptive Semantic Seg...
論文紹介:When Visual Prompt Tuning Meets Source-Free Domain Adaptive Semantic Seg...論文紹介:When Visual Prompt Tuning Meets Source-Free Domain Adaptive Semantic Seg...
論文紹介:When Visual Prompt Tuning Meets Source-Free Domain Adaptive Semantic Seg...
 
論文紹介: Offline Q-Learning on diverse Multi-Task data both scales and generalizes
論文紹介: Offline Q-Learning on diverse Multi-Task data both scales and generalizes論文紹介: Offline Q-Learning on diverse Multi-Task data both scales and generalizes
論文紹介: Offline Q-Learning on diverse Multi-Task data both scales and generalizes
 
FIDO Alliance Osaka Seminar: CloudGate.pdf
FIDO Alliance Osaka Seminar: CloudGate.pdfFIDO Alliance Osaka Seminar: CloudGate.pdf
FIDO Alliance Osaka Seminar: CloudGate.pdf
 
LoRaWAN 4チャンネル電流センサー・コンバーター CS01-LB 日本語マニュアル
LoRaWAN 4チャンネル電流センサー・コンバーター CS01-LB 日本語マニュアルLoRaWAN 4チャンネル電流センサー・コンバーター CS01-LB 日本語マニュアル
LoRaWAN 4チャンネル電流センサー・コンバーター CS01-LB 日本語マニュアル
 
【DLゼミ】XFeat: Accelerated Features for Lightweight Image Matching
【DLゼミ】XFeat: Accelerated Features for Lightweight Image Matching【DLゼミ】XFeat: Accelerated Features for Lightweight Image Matching
【DLゼミ】XFeat: Accelerated Features for Lightweight Image Matching
 
【AI論文解説】Consistency ModelとRectified Flow
【AI論文解説】Consistency ModelとRectified Flow【AI論文解説】Consistency ModelとRectified Flow
【AI論文解説】Consistency ModelとRectified Flow
 
CS集会#13_なるほどわからん通信技術 発表資料
CS集会#13_なるほどわからん通信技術 発表資料CS集会#13_なるほどわからん通信技術 発表資料
CS集会#13_なるほどわからん通信技術 発表資料
 
FIDO Alliance Osaka Seminar: Welcome Slides.pdf
FIDO Alliance Osaka Seminar: Welcome Slides.pdfFIDO Alliance Osaka Seminar: Welcome Slides.pdf
FIDO Alliance Osaka Seminar: Welcome Slides.pdf
 
2024年度_サイバーエージェント_新卒研修「データベースの歴史」.pptx
2024年度_サイバーエージェント_新卒研修「データベースの歴史」.pptx2024年度_サイバーエージェント_新卒研修「データベースの歴史」.pptx
2024年度_サイバーエージェント_新卒研修「データベースの歴史」.pptx
 
YugabyteDB適用に向けた取り組みと隠れた魅力 (DSS Asia 2024 発表資料)
YugabyteDB適用に向けた取り組みと隠れた魅力 (DSS Asia 2024 発表資料)YugabyteDB適用に向けた取り組みと隠れた魅力 (DSS Asia 2024 発表資料)
YugabyteDB適用に向けた取り組みと隠れた魅力 (DSS Asia 2024 発表資料)
 
FIDO Alliance Osaka Seminar: NEC & Yubico Panel.pdf
FIDO Alliance Osaka Seminar: NEC & Yubico Panel.pdfFIDO Alliance Osaka Seminar: NEC & Yubico Panel.pdf
FIDO Alliance Osaka Seminar: NEC & Yubico Panel.pdf
 

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 { 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. 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. 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

  1. 次ページのサンプルプログラムで、次の項目をマスターします クラス宣言とオブジェクト宣言 変数宣言 変更できる変数 変更できない変数 メソッド宣言 省略記法 Sample1.scala ファイルで説明した後、 Sample2.scala で省略記法バージョンを書いてみます
  2. 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 } }