Scala
https://gyazo.com/08603a8e27f3055e4e612c297e0cc338
良いところ
関数型
関数がファーストクラス
処理を抽象化
強力な型システム
Javaの資産を使える
ライブラリー
JVM
安定
実績
超高速
並行処理
イミュータブル
並行処理は可変な状態を共有するから問題になる
イミュータブルと並行処理は相性がいい
Futureを使えば可読性も高くできます
コレクション
強力な操作性
データ処理に向いてます
パターンマッチ
式であること
分岐のロジックを可読性良く書けること
変数へのバインディングも一緒に行うこと
①値の分解②値の取り出し③条件の分岐
を一気に行うことができること→簡潔に記述できる→可読性
境界
上限境界
下限境界
コンテキスト境界
型クラスパターン
code:scala
def funT(implicit a: AT) = ??? 型クラス、アドホック多相を実現
可視境界(View Bounds)
これを使うよりはコンテキスト境界を使った型クラスパターンを使う
code:scala
def funT(implicit f: T=>A) = ??? T→Aへの暗黙の型変換がある場合に成功
上限境界+暗黙の型変換
経路依存型
Scalaではオブジェクトがメンバーとして型を持てる
object.IdealType型のような型をパス依存型という
同じ経路で生成された内部クラスのインスタンス同士でないと同じ型にならない→/icons/point.icon生成経路が重要である
ここでいうパスとはオブジェクトの参照のこと
生成経路の違う内部クラスを同じクラスとして扱いたい場合は
Outer#Innerで扱えば良い→内部クラス
内部クラス
経路依存型のスーパークラスになっている
code:scala
class Outer {
class Inner
}
//参照するときは
Outer#Inner
η expansion
メソッドから無名関数への変換処理
_を使ってメソッドを関数に変換する
printlnはメソッドだがprintln _は関数
List(1,2,3).foreach(println _)
が成り立っているのが証拠
PartialFunction
部分関数
コレクションのcollectメソッドと一緒に使われたりする
特定の引数で呼び出した時に呼び出しが成功するかを関数本体を実行せずに確認できる
PartialFunction<A,B>
code:scala
val f: PartialFunctionInt, Int = {case n if n>=0 => n *2 } f.isDefinedAt(1) //true
f.isDefinedAt(-1) //false
f(2) //4
コンパニオンオブジェクト
code:scala
class Person private(name: String, age: Int)
object Person {
def apply(name: String, age: Int): Person = new Person(name, age)
}
hiroki.icon 当然の話だけどclassのコンストラクターにprivateつけられることに気づいた
アクセス修飾子
table:一覧
修飾子 範囲
public デフォルト。どこからでもアクセスできる
private 宣言されたクラスとそのオブジェクトからのみ
private<this> そのオブジェクトからのみ。privateよりも狭い
protected 宣言した場所とそれを継承した場所
private<X> Xはパッケージ、クラス、シングルトンなど。細かく範囲を指定可能
Nothing型
クラス階層の最底辺の型。Nothingの値は存在しない
値が得られない→式の評価が成功しない→型がNothingの式は必ず評価に失敗する→値が存在しないから
code:scala
def error(message: String): Nothing =
throw new RuntimeException(message)
def devide(x: Int, y: Int) : Int =
if(y != 0) x/y
else error("ゼロ徐算")
errorメソッドはNothing型を返すので、型の上ではIntとの整合性成り立っている
???メソッド
Predefに定義
code:scala
def ??? : Nothing = throw new NotImplementedError
実装中のメソッドとかに使えばとりあえずコンパイル通せるよ
NilはList<Nothing>を継承
こうすることでNilは共変で全てのList<Hoge>のサブタイピングが成り立つ
Null型
ただ一つの値null値を持つ
全ての参照型のサブタイプになっている
code:scala
scala> val x: String = null
x: String = null
scala> val y: Null = "hoge"
^
error: type mismatch;
found : String("hoge")
required: Null
Unit型
唯一の値()を持つ
「唯一の値しか持たない」ということは「意味のある値を返さない」と同義
unary_ 前置演算子
+
-
!
~
の四種類のみ前置演算子として定義できる
unary_+
unary_-
unary_!
unary_~
例
code:scala
class Hoge(val s: String) {
def unary_! : String = "!" + s
}
val h: Hoge = new Hoge("sample")
!h
Scalaのコンパイラー
scalaのコンパイラーもそれ自身がscala-compiler.jarというjar→JVMで動作する
/icons/point.iconコンパイル時のScalaの言語バージョンの切り替えはscala-compiler.jarの切り替えにすぎない
scalac
JVM上でJavaプログラムであるところのScalaコンパイラを実行するためのスクリプト
→極論すればScalaコンパイラをJVM上で実行する仕組みがあればScalaソースコードをコンパイルすることができる
名前渡し
呼び出される度に評価される→呼び出されなければ評価されない
遅延評価は呼び出されると一度だけ評価されて値が確定する→2回目以降再評価されることはない
catsのEvalは評価戦略を自在にコントロールする 名前渡し
code:scala
def sample(x: => Int): Int = x + x
code:scala
def sample(x: => Int): Int {
lazy val y = x //遅延評価
y + y
}
浮動小数点数リテラル
code:scala
val a = 1.2345
val b = 1.2345e1 // 12.345
val c = 123e-3 // 0.123
val d = 123D //double
val e = 123F //Float
exponentialを指定する形式は忘れやすい
文字列の補間
s, f, raw の3つの補間子を提供する
s補間子
文字リテラルの中で変数が使えるようになる。変数には$変数名でアクセス可能
code:scala
val name = "James"
println(s"Hello, $name")
s"Hello $name"
は
StringContext("Hello, ", "").s(name)
と展開される
任意の式も使用可能
code:scala
prinln(s"1 + 1 = ${1+1}")
まとめ
$で変数にアクセス可能
${式}で任意の式を埋め込める
f補完子
printfのような書式付き文字列を作れる
code:scala
val height = 1.9d
val name = "hiroki"
println("f"$name%s is $height%2.2f meters tail")
raw補間子
s補間子とほぼ同じ事ができるが、リテラル内でエスケープを実行しない。
s補間子だと\nは改行文字に置換する。
code:scala
val regex = raw"\d{2}\w{4}".r
カスタム補間子
StringContextの拡張をすることで自由に補間子を定義できる。
①メソッド名が補間子名になる
②返り値はString以外でも可能
code:scala
//StringContextには普通の文字列群がorigialのargsには特殊文字がわたる
implicit class MyInterpolation(val sc: StringContext) extends AnyVal {
def original(args: Any*): String = ....
}
例
code:scala
//scalikejdbc
sql"select * form Table"