Contenu connexe Similaire à 15分でざっくり分かるScala入門 (20) 15分でざっくり分かるScala入門4. Scala早見表 リテラル
4
Scala Java
Int int
Long long
Double double
Boolean boolean
String String
Tuple
Elem(xml)
その他Javaにあるものはある
val x : Int = 1
var str : String = “hoge”
val tuple = (1, “hoge”)
val xml = <xml><body>text</body></xml>
val 再代入不可
できるだけこっちを使う
var 再代入できる
できるだけ使わない
5. Scala早見表 制御構文
5
Scala Java
if (i < 10) { … } else { … } if (i < 10) { … } else { … }
while(i < 10){ … } while(i < 10) { … }
for(o : Object <- list) { … } for(Object o : list) { … }
n match {
case 1 => …
case 2 => …
case _ => …
}
switch(n) {
case 1 : … break;
case 2 : … break;
default : … break;
}
if文(式)は値を返す
val x = 1 + (if (true) 3 else 4)
->x : Int = 4
for文(式)も値を返せる
val list = for(i <- 1 to 10; if i % 3 == 0) yield i
->list = Vector(3,6,9)
6. Scala早見表 関数
6
Scala Java
def public
private def private
Unit void
return(省略可) return
コンパニオンオブジェクトで代用 static
override @Override
(arg0 : Type0, arg1 :Type1) => { … } (Type0 arg0, Type1 arg1) -> { … }
tlist : Type* Type… tlist
def inc(x : Int): Int = x + 1
private def positive(ls : List[Int]):List[Int] = {
ls foreach { print(_) }
ls filter (i => 0 < i)
}
7. Scala早見表 オブジェクト指向
7
Scala Java
class class
abstract abstract
trait(ただし実装を持てる!) interface
final final
extends extends
with implements
[A] <A>
[A <: B] A extends B
[A >: B] A super B
package package
import import
これくらい分かれば、ざっくりScalaは書ける
8. フィボナッチ数列
8
0, 1, 1, 2, 3, 5, 8, 13, …
0と1から始まって、あとは前の2つを足してできる数列
関数型プログラミングの入門でおなじみ
ヒマワリの種のつきかたとかが
フィボナッチ数列らしい
9. Javaっぽい実装
9
def fib(n : Int): BigInt = {
if (n <= 0) return 0
if (n == 1) return 1
var n1 = BigInt(0)
var result = BigInt(1)
for(i <- 2 to n) {
val tmp = result
result += n1
n1 = tmp
}
return result
}
これはn-1番目
これを
n番目
とすると
これはn-2番目
可読性 ?、 実行速度 ○
実行すると
for(i <- 0 to 100) print(fib(i)+",")
->0,1,1,2,3,5,8,13,21,34,55,…
10. 関数型っぽい実装
10
def fib(n : Int): BigInt =
n match {
case n if n <= 0 => 0
case 1 => 1
case _ => fib(n - 1) + fib(n - 2)
}
fib(100) -> 終わらない
可読性 ◎、 実行速度 ×
nが0以下の場合ここにマッチ
nが0以下でも1でもないなら、前2つを足したもの
数学的な定義そのまま!
11. 末尾再帰
11
def fib(n : Int): BigInt = {
if (n <= 0) return 0
def rec(i : Int, n1 : BigInt, result : BigInt):BigInt =
i match {
case i if n <= i => result
case _ => rec(i + 1, result, result + n1)
}
rec(1, 0, 1)
}
可読性 ○、 実行速度 ○
関数内で再帰関数を定義
カウンタ
ループを回りきったら即
計算結果を返す
関数に渡す前に計算しておく
varとかvalとかなくてもプログラムは書ける
12. オブジェクトプログラミング1
12
case class Person(val first_name : String,
middle_name : Option[String], last_name : String) {
def fullName: String =
middle_name match {
case Some(md : String) =>
first_name +" "+md+" "+last_name
case None => first_name+" "+last_name
}
def marryWith(person : Person): Person =
new Person(first_name, person.middle_name,
person.last_name)
}
Option型:nullの可能性がある値を包むモナド
caseクラス:equals()やhashCode()などを自動で作ってくれる
13. オブジェクトプログラミング2
13
object Person {
def apply(first_name : String, last_name : String): Person =
new Person(first_name, None, last_name)
def sasakiFamily(first_name : String): Person =
new Person(first_name, None, “Sasaki”)
}
val mika = Person.sasakiFamily(“Mika”)
コンパニオンオブジェクト:ここに定義された関数はstatic
ファクトリーみたいなもの
14. オブジェクトプログラミング3
14
val taro = Person.sasakiFamily("Taro")
val hana = Person("Hana", "Tanaka")
println(hana.fullName)
val sasaki_hana = hana marryWith taro
println(sasaki_hana.fullName)
->”Hana Tanaka”
“Hana Sasaki”
. とか () とか省略できる
17. クロージャ
17
def labelMaker(str : String): Unit => String = {
var i = 0
Unit => {
i += 1
str + i }}
val argMaker = labelMaker("arg")
for(i <- 1 to 3) print(argMaker()+",")
->arg1,arg2,arg3,
戻り値の型が関数
引数で与えられた文字列
クロージャ内に保存されている変数この
関数が
帰る
18. クロージャでフィボナッチ
18
def fib(n : Int): BigInt = {
val memo ={
var n1 = BigInt(1)
(x : BigInt) => {
var tmp = n1
n1 = x
tmp }}
var result = BigInt(0)
for(i <- 1 to n) result += memo(result)
result
}
引数で与えられた数を保存し、
前回保存した数を返す関数
19. 関数の部分適用
19
def sandwich
(header : String)(fooder : String)(body : String): String =
header + body + fooder
def htmlMaker(tag : String)(body : String): String =
sandwich("<" + tag + ">")("</" + tag + ">")(body)
val commentout = sandwich("<!-- ")(" -->")_
val ptag = htmlMaker("p")_
println(commentout(“here is a text "))
List("hoge","goo","foo") map ptag foreach print
-><!– here is a text -->
<p>hoge</p><p>goo</p><p>foo</p>
3つ目の引数はまだ与えない
後から3つ目の引数を与える
何度でも使える
引数のカッコを区切る
20. 部分適用でフィボナッチ
20
def fib(n : Int): BigInt = {
def add(n1 : BigInt)(n2 : BigInt): BigInt = n1 + n2
def rec(i : Int, add_memo : BigInt => BigInt,
result : BigInt): BigInt =
i match {
case i if n <= i => result
case _ => rec(i+1, add(result), add_memo(result))
}
rec(0, add(BigInt(1)), BigInt(0))
}
個人的にはこれが一番かな?
数をとってresultを足す関数
覚えていた数にresultを足す
21. 暗黙の型変換
21
class ExtString(val str: String) {
def -(str2 : ExtString): ExtString = new ExtString(str.replace(str2.str, ""))
def *(str2 : String): List[String] =
for(s <- this.allSubstring; t <- new ExtString(str2).allSubstring)
yield s + t
def allSubstring: List[String] = { … }
override def toString(): String = str
}
object ExtString {
implicit def string2ExtString(str : String) = new ExtString(str)
}
import ExtString._
println("hoge" - "og")
"wnzk" * "a" filter(_.length == 2) foreach {print(_)}
->”he”
“ka””na””za””wa”
リテラルを自由に拡張できる!
Stringには – や * など無い
ExtStringにはあるから、
StringからExtStringへ変換する
変換規則を定義しておけばいい
文字列の全通りの組
22. 無限リストでフィボナッチ
22
lazy val fib: Stream[BigInt] =
Stream.cons(0,
Stream.cons(1, fib.zip(fib.tail).map(p => p._1 + p._2)))
(0,1,1,2,3,5,8,…
無限リスト
(1,1,2,3,5,8,…
((0,1),(1,1),(1,2),(2,3),(3,5),(5,8),…
zip
タプルの要素を足す
(1,2,3,5,8,13… フィボナッチ数列
23. ちなみに ベンチマーク
23
1,000 10,000 100,000 500,000
Javaっぽい 5 20 223 4415
末尾再帰 3 4 182 4501
クロージャ 4 8 186 4401
部分適用 2 6 187 4703
無限リスト 28 69 OutOfMemoryError OutOfMemoryError
-Xmx 1024 -Xms 1024 でfib(n)を計算するのにかかる時間(ミリ秒)