「Scala」の版間の差分
ナビゲーションに移動
検索に移動
(ページの作成:「==Scala== {{amazon|4798119873}} ==セットアップ== ===ランタイム=== ====Javaランタイム==== *http://www.oracle.com/technetwork/jp/java/javase/download…」) |
|||
16行目: | 16行目: | ||
[[File:1104_scala02.jpg]] | [[File:1104_scala02.jpg]] | ||
==チュートリアル== | ==チュートリアル== | ||
− | [[Scala Javaプログラマ向けチュートリアル]] | + | [[[Scala Javaプログラマ向けチュートリアル]]] |
==コマンド== | ==コマンド== | ||
===実行=== | ===実行=== | ||
28行目: | 28行目: | ||
*ソースコードを指定すると、Javaクラスファイルにコンパイルしてから実行する | *ソースコードを指定すると、Javaクラスファイルにコンパイルしてから実行する | ||
− | + | >scala HelloScala.scala | |
hello Scala | hello Scala | ||
*指定しないと対話型シェル(REPL)が起動する | *指定しないと対話型シェル(REPL)が起動する | ||
**:quit で終了 | **:quit で終了 | ||
− | + | >scala | |
Welcome to Scala version 2.10.2 (Java HotSpot(TM) Client VM, Java 1.7.0_04). | Welcome to Scala version 2.10.2 (Java HotSpot(TM) Client VM, Java 1.7.0_04). | ||
Type in expressions to have them evaluated. | Type in expressions to have them evaluated. | ||
Type :help for more information. | Type :help for more information. | ||
− | scala | + | scala> println("hello") |
hello | hello | ||
− | scala | + | scala> :quit |
=====タブキーを押すと、補完される===== | =====タブキーを押すと、補完される===== | ||
− | scala | + | scala> import java.io.Buffered |
BufferedInputStream BufferedOutputStream BufferedReader BufferedWriter | BufferedInputStream BufferedOutputStream BufferedReader BufferedWriter | ||
===コンパイル=== | ===コンパイル=== | ||
====scalac==== | ====scalac==== | ||
*Java VMで動作するクラスファイルが生成される | *Java VMで動作するクラスファイルが生成される | ||
− | + | >scala HelloScala.scala | |
[[File:1105_scala03.jpg]] | [[File:1105_scala03.jpg]] | ||
==変数== | ==変数== | ||
===val=== | ===val=== | ||
*valで宣言した変数は、再代入不可 | *valで宣言した変数は、再代入不可 | ||
− | scala | + | scala> val i = 1 |
i: Int = 1 | i: Int = 1 | ||
− | scala | + | scala> i=2 |
− | + | <console>:8: error: reassignment to val | |
i=2 | i=2 | ||
− | + | <blockquote>Scalaで関数型スタイルのプログラミングを行う場合の助けとなる。変数をどのタイミングで参照しても同じ値であることが保証される(参照透過性)。同様にイミュータブル(変更不可)のコレクションも提供</blockquote> | |
===var=== | ===var=== | ||
*varで宣言した変数は再代入可能 | *varで宣言した変数は再代入可能 | ||
− | scala | + | scala> var i = 1 |
i: Int = 1 | i: Int = 1 | ||
− | scala | + | scala> i =2 |
i: Int = 2 | i: Int = 2 | ||
====lazy var (遅延評価)==== | ====lazy var (遅延評価)==== | ||
*実際に必要になるまで、計算を遅延させる | *実際に必要になるまで、計算を遅延させる | ||
− | scala | + | scala> val x = 2 |
x: Int = 2 | x: Int = 2 | ||
− | scala | + | scala> lazy val y = x * 2 |
− | y: Int = | + | y: Int = <lazy> |
− | scala | + | scala> print(y) // ここで計算される |
4 | 4 | ||
==型== | ==型== | ||
98行目: | 98行目: | ||
*メソッドの戻り値の型も省略できるが、すべての型を同じにしないと、戻り値の型は、Anyになってしまう | *メソッドの戻り値の型も省略できるが、すべての型を同じにしないと、戻り値の型は、Anyになってしまう | ||
=====すべての型を合わせた場合===== | =====すべての型を合わせた場合===== | ||
− | scala | + | scala> def test(p:Int) = if(p==0) { 0 } else { 1 } |
test: (p: Int)Int | test: (p: Int)Int | ||
=====戻り値の型が異なる場合、戻り値がAnyと判断される===== | =====戻り値の型が異なる場合、戻り値がAnyと判断される===== | ||
− | scala | + | scala> def test2(p:Int) = if(p==0) { "zero" } else { 1 } |
test2: (p: Int)Any | test2: (p: Int)Any | ||
114行目: | 114行目: | ||
=====java.util.DateをCalendarに自動変換する例===== | =====java.util.DateをCalendarに自動変換する例===== | ||
− | scala | + | scala> import java.util.{Date,Calendar} |
import java.util.{Date, Calendar} | import java.util.{Date, Calendar} | ||
− | scala | + | scala> implicit def date2calendar(date:Date):Calendar = |
| { | | { | ||
| val cal = Calendar.getInstance() | | val cal = Calendar.getInstance() | ||
124行目: | 124行目: | ||
| } | | } | ||
− | scala | + | scala> val cal:Calendar = new Date() |
cal: java.util.Calendar = java.util.GregorianCalendar[time=1382275606352,areFieldsSet=true,areAllFie | cal: java.util.Calendar = java.util.GregorianCalendar[time=1382275606352,areFieldsSet=true,areAllFie | ||
ldsSet=true,lenient=true,zone=sun.util.calendar.ZoneInfo[id="Asia/Tokyo",offset=32400000,dstSavings= | ldsSet=true,lenient=true,zone=sun.util.calendar.ZoneInfo[id="Asia/Tokyo",offset=32400000,dstSavings= | ||
131行目: | 131行目: | ||
_WEEK_IN_MONTH=3,AM_PM=1,HOUR=10,HOUR_OF_DAY=22,MINUTE=26,SECOND=46,MILLISECOND=352,ZONE_OFFSET=3240 | _WEEK_IN_MONTH=3,AM_PM=1,HOUR=10,HOUR_OF_DAY=22,MINUTE=26,SECOND=46,MILLISECOND=352,ZONE_OFFSET=3240 | ||
0000,DST_OFFSET=0] | 0000,DST_OFFSET=0] | ||
− | + | <blockquote>暗黙の型変換を行うことで、継承を行わずに型を拡張できる(finalクラスも拡張できる)が、該当部分のソースを見ただけでは処理がわかりにくくなるので、濫用は避ける</blockquote> | |
====Predef==== | ====Predef==== | ||
138行目: | 138行目: | ||
*ただし、縮小変換は未定義 | *ただし、縮小変換は未定義 | ||
*明示的に変換する | *明示的に変換する | ||
− | scala | + | scala> val l:Long = 123 |
l: Long = 123 | l: Long = 123 | ||
− | scala | + | scala> val i:Int = l |
− | + | <console>:12: error: type mismatch; | |
found : Long | found : Long | ||
required: Int | required: Int | ||
val i:Int = l | val i:Int = l | ||
− | scala | + | scala> val i:Int = l.toInt |
i: Int = 123 | i: Int = 123 | ||
154行目: | 154行目: | ||
===if=== | ===if=== | ||
*式なので値を返す | *式なので値を返す | ||
− | + | <blockquote>ブロック内で最後に評価された値が、ifの戻り値となる</blockquote> | |
− | scala | + | scala> val i = 1 |
i: Int = 1 | i: Int = 1 | ||
− | scala | + | scala> val s = if(i==0){"zero"} else if(i==1){"one"} else {"other"} |
s: String = one | s: String = one | ||
*値を返さないブロックが有る場合、戻り値はAnyとなり、そのブロックが呼ばれた場合、Unitが返される | *値を返さないブロックが有る場合、戻り値はAnyとなり、そのブロックが呼ばれた場合、Unitが返される | ||
− | scala | + | scala> def test(p:Int) = if(p==0){"zero"} |
test: (p: Int)Any | test: (p: Int)Any | ||
− | scala | + | scala> test(1) |
res7: Any = () | res7: Any = () | ||
===for=== | ===for=== | ||
− | for (変数名 | + | for (変数名 <- コレクション) |
=====指定した範囲の例===== | =====指定した範囲の例===== | ||
− | scala | + | scala> for (i <- 1 to 10) { |
| println(i) | | println(i) | ||
| } | | } | ||
185行目: | 185行目: | ||
10 | 10 | ||
=====scala.collection.immutable.Range の例===== | =====scala.collection.immutable.Range の例===== | ||
− | scala | + | scala> for (i <- Range(1,3)) |
| println(i) | | println(i) | ||
1 | 1 | ||
2 | 2 | ||
=====Listの例===== | =====Listの例===== | ||
− | scala | + | scala> val l = List("a","b","c") |
l: List[String] = List(a, b, c) | l: List[String] = List(a, b, c) | ||
− | scala | + | scala> for (e <-l) { |
| println(e) | | println(e) | ||
| } | | } | ||
200行目: | 200行目: | ||
c | c | ||
====フィルタ==== | ====フィルタ==== | ||
− | for (変数名 | + | for (変数名 <- コレクション if 条件) |
=====例===== | =====例===== | ||
− | scala | + | scala> for (o <- Range(1,10) if o % 2 == 0) { |
| println(o) | | println(o) | ||
| } | | } | ||
210行目: | 210行目: | ||
8 | 8 | ||
====コレクションを返す==== | ====コレクションを返す==== | ||
− | var 変数=for(変数名 | + | var 変数=for(変数名<-コレクション)yield { |
処理 | 処理 | ||
} | } | ||
=====例===== | =====例===== | ||
− | scala | + | scala> for (o <- Range(1,10) if o % 2 == 0) yield { |
| o | | o | ||
| } | | } | ||
res4: scala.collection.immutable.IndexedSeq[Int] = Vector(2, 4, 6, 8) | res4: scala.collection.immutable.IndexedSeq[Int] = Vector(2, 4, 6, 8) | ||
====ネスト==== | ====ネスト==== | ||
− | for (変数名 | + | for (変数名 <- コレクション; 変数名 <- コレクション ) |
===match 式=== | ===match 式=== | ||
=====他言語のswitchにあたる===== | =====他言語のswitchにあたる===== | ||
式 match { | 式 match { | ||
− | case パターン= | + | case パターン=>{処理} |
− | case _ = | + | case _ =>{処理} |
} | } | ||
*_ はワイルドカード | *_ はワイルドカード | ||
239行目: | 239行目: | ||
def matchCodeAndValue(cv:CodeAndValue) = { | def matchCodeAndValue(cv:CodeAndValue) = { | ||
cv match { | cv match { | ||
− | case CodeAndValue(_,"Test1") = | + | case CodeAndValue(_,"Test1") => { |
println("this is test1") | println("this is test1") | ||
} | } | ||
− | case CodeAndValue(2,_) = | + | case CodeAndValue(2,_) => { |
println("this code is two") | println("this code is two") | ||
} | } | ||
− | case CodeAndValue(code, value) = | + | case CodeAndValue(code, value) => { |
println(cv.code + " " + cv.value) | println(cv.code + " " + cv.value) | ||
} | } | ||
251行目: | 251行目: | ||
} | } | ||
− | scala | + | scala> matchCodeAndValue(CodeAndValue(1,"Test1")) |
this is test1 | this is test1 | ||
− | scala | + | scala> matchCodeAndValue(CodeAndValue(2,"Test2")) |
this code is two | this code is two | ||
− | scala | + | scala> matchCodeAndValue(CodeAndValue(3,"Test3")) |
3 Test3 | 3 Test3 | ||
266行目: | 266行目: | ||
=====XMLのパターンマッチ===== | =====XMLのパターンマッチ===== | ||
=====パターンマッチに条件===== | =====パターンマッチに条件===== | ||
− | case (x,y) if x == y = | + | case (x,y) if x == y =>{ |
}!エラー処理 | }!エラー処理 | ||
=====scala.Option===== | =====scala.Option===== | ||
310行目: | 310行目: | ||
====定義==== | ====定義==== | ||
=====無名関数===== | =====無名関数===== | ||
− | *引数と本体を= | + | *引数と本体を=>(関数矢印)で結ぶ |
− | (引数名:型,...)= | + | (引数名:型,...)=>{ |
}*戻り値は最後の式の値 | }*戻り値は最後の式の値 | ||
*省略 | *省略 | ||
326行目: | 326行目: | ||
====高階関数==== | ====高階関数==== | ||
=====引数に関数を渡す===== | =====引数に関数を渡す===== | ||
− | *def メソッド名(引数関数名(関数の引数型)= | + | *def メソッド名(引数関数名(関数の引数型)=>引数関数戻り値) |
− | *def execute(f:(Int)= | + | *def execute(f:(Int)=>Boolean)=f(10) |
**引数fには、「引数がIntでBooleanを返す関数」を渡すことができる | **引数fには、「引数がIntでBooleanを返す関数」を渡すことができる | ||
=====関数を生成して返す===== | =====関数を生成して返す===== | ||
− | def hoge:Int = | + | def hoge:Int => Int = { |
− | }**戻り値がInt= | + | }**戻り値がInt=>Intの関数 |
**戻り値を生成して返す | **戻り値を生成して返す | ||
・関数リテラルなど | ・関数リテラルなど | ||
342行目: | 342行目: | ||
=====関数の生成時に外部の変数を取り込んで動作する===== | =====関数の生成時に外部の変数を取り込んで動作する===== | ||
=====取り込む変数を自由変数という===== | =====取り込む変数を自由変数という===== | ||
− | =====def multi(times:Int) = (i:Int) = | + | =====def multi(times:Int) = (i:Int) => i * times===== |
*Int引数の無名関数部分がクロージャ | *Int引数の無名関数部分がクロージャ | ||
var tenTimes = multi(10) | var tenTimes = multi(10) | ||
355行目: | 355行目: | ||
*"3つで囲む | *"3つで囲む | ||
*|でインデントをあわせられる | *|でインデントをあわせられる | ||
− | scala | + | scala> val sql = """select |
| * | | * | ||
| from | | from |
2020年2月15日 (土) 08:05時点における版
目次
Scala
セットアップ
ランタイム
Javaランタイム
Scalaランタイム
Eclipse
Scala IDE for Eclipse
アップデートサイトのURLをコピー
Help - Install New Software に上記URLを指定してインストール
チュートリアル
[[[Scala Javaプログラマ向けチュートリアル]]]
コマンド
実行
scala
HelloScala.scala
object HelloScala { def main(args:Array[String]):Unit = { println("hello Scala") } }
- ソースコードを指定すると、Javaクラスファイルにコンパイルしてから実行する
>scala HelloScala.scala hello Scala
- 指定しないと対話型シェル(REPL)が起動する
- quit で終了
>scala Welcome to Scala version 2.10.2 (Java HotSpot(TM) Client VM, Java 1.7.0_04). Type in expressions to have them evaluated. Type :help for more information. scala> println("hello") hello scala> :quit
タブキーを押すと、補完される
scala> import java.io.Buffered BufferedInputStream BufferedOutputStream BufferedReader BufferedWriter
コンパイル
scalac
- Java VMで動作するクラスファイルが生成される
>scala HelloScala.scala
変数
val
- valで宣言した変数は、再代入不可
scala> val i = 1 i: Int = 1 scala> i=2 <console>:8: error: reassignment to val i=2
<blockquote>Scalaで関数型スタイルのプログラミングを行う場合の助けとなる。変数をどのタイミングで参照しても同じ値であることが保証される(参照透過性)。同様にイミュータブル(変更不可)のコレクションも提供</blockquote>
var
- varで宣言した変数は再代入可能
scala> var i = 1 i: Int = 1 scala> i =2 i: Int = 2
lazy var (遅延評価)
- 実際に必要になるまで、計算を遅延させる
scala> val x = 2 x: Int = 2 scala> lazy val y = x * 2 y: Int = <lazy> scala> print(y) // ここで計算される 4
型
種類
Any
- 全ての型の基底クラス
AnyRef
- 参照型の基底クラス
AnyVal
- 値型の基底クラス
- プリミティブ型ラッパークラスの基底クラス
Unit型
- Java のvoidに対応
Null
- 参照型に適合
Nothing
- 全ての型に適合
型推論
- Scalaでは、変数やフィールド、メソッド定義において型の記述を省略できるケースがある
- メソッドの戻り値の型も省略できるが、すべての型を同じにしないと、戻り値の型は、Anyになってしまう
すべての型を合わせた場合
scala> def test(p:Int) = if(p==0) { 0 } else { 1 } test: (p: Int)Int
戻り値の型が異なる場合、戻り値がAnyと判断される
scala> def test2(p:Int) = if(p==0) { "zero" } else { 1 } test2: (p: Int)Any
暗黙の型変換
変換メソッドを用意
- implicit def メソッド名を定義しておくと、自動的に型変換を行うことができる
- 必要に応じ自動変換される
implicit def メソッド名(引き数名:変換前の型):変換後の型 { 変換処理 }
java.util.DateをCalendarに自動変換する例
scala> import java.util.{Date,Calendar} import java.util.{Date, Calendar} scala> implicit def date2calendar(date:Date):Calendar = | { | val cal = Calendar.getInstance() | cal.setTime(date) | cal | } scala> val cal:Calendar = new Date() cal: java.util.Calendar = java.util.GregorianCalendar[time=1382275606352,areFieldsSet=true,areAllFie ldsSet=true,lenient=true,zone=sun.util.calendar.ZoneInfo[id="Asia/Tokyo",offset=32400000,dstSavings= 0,useDaylight=false,transitions=10,lastRule=null],firstDayOfWeek=1,minimalDaysInFirstWeek=1,ERA=1,YE AR=2013,MONTH=9,WEEK_OF_YEAR=43,WEEK_OF_MONTH=4,DAY_OF_MONTH=20,DAY_OF_YEAR=293,DAY_OF_WEEK=1,DAY_OF _WEEK_IN_MONTH=3,AM_PM=1,HOUR=10,HOUR_OF_DAY=22,MINUTE=26,SECOND=46,MILLISECOND=352,ZONE_OFFSET=3240 0000,DST_OFFSET=0]
<blockquote>暗黙の型変換を行うことで、継承を行わずに型を拡張できる(finalクラスも拡張できる)が、該当部分のソースを見ただけでは処理がわかりにくくなるので、濫用は避ける</blockquote>
Predef
- Predefでは、以下の様な暗黙の型変換が事前定義されている
数値同士
- ただし、縮小変換は未定義
- 明示的に変換する
scala> val l:Long = 123 l: Long = 123 scala> val i:Int = l <console>:12: error: type mismatch; found : Long required: Int val i:Int = l scala> val i:Int = l.toInt i: Int = 123
Javaラッパー型とScala型
制御
if
- 式なので値を返す
<blockquote>ブロック内で最後に評価された値が、ifの戻り値となる</blockquote>
scala> val i = 1 i: Int = 1 scala> val s = if(i==0){"zero"} else if(i==1){"one"} else {"other"} s: String = one
- 値を返さないブロックが有る場合、戻り値はAnyとなり、そのブロックが呼ばれた場合、Unitが返される
scala> def test(p:Int) = if(p==0){"zero"} test: (p: Int)Any scala> test(1) res7: Any = ()
for
for (変数名 <- コレクション)
指定した範囲の例
scala> for (i <- 1 to 10) { | println(i) | } 1 2 3 4 5 6 7 8 9 10
scala.collection.immutable.Range の例
scala> for (i <- Range(1,3)) | println(i) 1 2
Listの例
scala> val l = List("a","b","c") l: List[String] = List(a, b, c)
scala> for (e <-l) { | println(e) | } a b c
フィルタ
for (変数名 <- コレクション if 条件)
例
scala> for (o <- Range(1,10) if o % 2 == 0) { | println(o) | } 2 4 6 8
コレクションを返す
var 変数=for(変数名<-コレクション)yield { 処理 }
例
scala> for (o <- Range(1,10) if o % 2 == 0) yield { | o | } res4: scala.collection.immutable.IndexedSeq[Int] = Vector(2, 4, 6, 8)
ネスト
for (変数名 <- コレクション; 変数名 <- コレクション )
match 式
他言語のswitchにあたる
式 match { case パターン=>{処理} case _ =>{処理} }
- _ はワイルドカード
マッチしない場合
- scala.MatchError
型でのマッチ
- case 変数:型
case x:String case _:Array[String]
ケースクラスのパターンマッチ
ケースクラスは、case classキーワードで定義する、主にパターンマッチに利用するクラス
case class CodeAndValue(code:Int, value:String); def matchCodeAndValue(cv:CodeAndValue) = { cv match { case CodeAndValue(_,"Test1") => { println("this is test1") } case CodeAndValue(2,_) => { println("this code is two") } case CodeAndValue(code, value) => { println(cv.code + " " + cv.value) } } }
scala> matchCodeAndValue(CodeAndValue(1,"Test1")) this is test1 scala> matchCodeAndValue(CodeAndValue(2,"Test2")) this code is two scala> matchCodeAndValue(CodeAndValue(3,"Test3")) 3 Test3
Listや配列のパターンマッチ
タプルのパターンマッチ
正規表現のパターンマッチ
XMLのパターンマッチ
パターンマッチに条件
case (x,y) if x == y =>{ }!エラー処理
scala.Option
- 値があるかないかわからない状態を表すための型
- nullを使わずに表現
- 値を取得(nullでない)
・option.get
- 値もしくはnull取得
・option.orNull
- 値がない場合デフォルトを返す
・option.getOrElse
- サブクラス
- Some
- None
- Option(x)
- 値がnull
・None
- 値がnull以外
・Some
例外処理
- Java 同様
- try - catch - finally
・式なので値を返せる
- catchブロックはmatch式で型毎の処理
- 例外処理を強制する仕組みはない
scala.Either
- メソッドの戻り値に使う
- コンテナ
- 型パラメータで指定したいずれかを保持
・正常終了 ・・期待した戻り値 ・異常終了 ・・例外
def readFile(fileName:String):Either[Throwable,String] = { }
・呼び出し元ではパターンマッチで結果を取り出せる
var ret:Either[Throwable,Srting] = readFile("test".txt) ret match { case }
関数
定義
無名関数
- 引数と本体を=>(関数矢印)で結ぶ
(引数名:型,...)=>{ }*戻り値は最後の式の値
- 省略
- 式が一つの場合、中括弧
- 引数の型が推論できる場合、型
・引数が一つの場合、丸括弧
実体
トレイト
- 引数の数に応じ、Function0 - 22
- 引数23以上でエラー
- 関数の実体はトレイトのインスタンス
ファーストクラスオブジェクト
- 値として扱うことができる
高階関数
引数に関数を渡す
- def メソッド名(引数関数名(関数の引数型)=>引数関数戻り値)
- def execute(f:(Int)=>Boolean)=f(10)
- 引数fには、「引数がIntでBooleanを返す関数」を渡すことができる
関数を生成して返す
def hoge:Int => Int = { }**戻り値がInt=>Intの関数
- 戻り値を生成して返す
・関数リテラルなど
ネストした関数
ローカル関数
def foo(a:Srting) = { def bar(b:String) = {} }::外側の関数からしかアクセスできない
クロージャ
関数の生成時に外部の変数を取り込んで動作する
取り込む変数を自由変数という
def multi(times:Int) = (i:Int) => i * times
- Int引数の無名関数部分がクロージャ
var tenTimes = multi(10) tenTimes(3) // 30 multi(100)(3) // 300!!正規表現
scala.util.matching.Regex
生成
var r = """\d{3}""".r
文字列
raw文字列
- "3つで囲む
- |でインデントをあわせられる
scala> val sql = """select | * | from | test""" sql: String = select * from test
1行ずつ処理
lines,linesWithSeparatos
連結
+
StringBuilder
比較
==,!=,equals
- 値の比較
eq,ne
- 参照の比較
構成
1ソースファイル
複数パッケージ
- 宣言に中括弧
リファレンス
Api
http://www.scala-lang.org/api/current/index.html
コンソール
入力
- readLine,readf,readXxx
出力
- print,printf,println
- Xxxは、Intなどの型
パッケージ
複数行に分けられる
中括弧で名前空間
インポート
パッケージ
クラス
別名をつけて
パッケージメンバー
シングルトンクラスメンバー
Predef
scala.Predef
- 暗黙的にインポートされる
© 2006 矢木浩人