【Scala】勉強ログ(更新一時停止)

追記(2020/04/10)

sbtを操作すると頻繁にPCが落ちるようになった(なんで?)ので一旦やめ。

まえがき

ただの個人用勉強ログです。
COVID-19 の おかげ せいで N 予備校の講座が無料で見れるのでやっていく。

Scala とは?

環境

  • WSL1
  • Open JDK 11.0.3(?) for Linux (以前入れたっぽい)
  • sbt 1.3.8 (Scala Build Tool?)
  • VSCode
  • Scala (Metals) : VSCode の拡張。これだけで補完と format が効くっぽい。2020?年から ENSIME から Metals へ移行したよう。

REPL 立ち上がらない

sbt console
>>> [warn] No sbt.version set in project/build.properties, base directory: /$CURRENT_DIRCTORY/Go-Tutorial
>>> [error] java.nio.file.AccessDeniedException: /$HOME/.cache/coursier
>>> [error] Use 'last' for the full log.
>>> Project loading failed: (r)etry, (q)uit, (l)ast, or (i)gnore? r

なぜか ~/.cache の所有者が root だったので自分に変更。

sudo chown [username]:[groupname] ~/.cache

数値表現

値型 範囲 記述例
Byte 1 Byte 符号付き整数 1.toByte
Short 2 Byte 符号付き整数 1.toShort
Int 4 Byte 符号付き整数(-214748368 ~ 2147483647) 1
Long 8 Byte 符号付き整数 1L
Float 4 Byte 浮動小数点数 1.0F
Double 8 Byte 浮動小数点数(-1.7976931348623157E308 ~ 1.7976931348623157E308) 1.0

Map()(連想配列) の更新

今までのイメージ

// JavaScript
aaa = { a: 1, b: 2 };
aaa["a"] = 3;
console.log(aaa) >>> { a: 3, b: 2 };

Scala

// 更新というか新規作成
val aaa = Map(2->1, 3->2)
val aaa2 = aaa + (3 -> (aaa.getOrElse(3, 0) + 1))  // 二重かっこにするのを忘れないように。
println(aaa2)
>>> Map(2 -> 1, 3 -> 3)

文字列検索

索引型検索

  • 文章のなかから予め単語の文字列を抜き出して、その単語ごとに索引を作っておく
  • 単語ごとに、対象の文章の中の頻度や場所に応じてスコアが計算される
  • 例)検索エンジンなど

非索引型検索

  • 与えられた文字の情報のみで検索
  • 検索のたびに、対象の文章データを全て走査

文字列String

  • Scala の String 型は、Java の String 型を踏襲。APIJava 11 String を参考。
  • 基本的にダブルクォーテーションを使う。シングルクォーテーションは Char 型。

ビット演算

計算 演算子 記述例 結果 補足
ビット単位 AND & -1 & 2 2
ビット単位 OR | -1 | 2 -1
ビット単位 XOR ^ -1 ^ 2 3
ビット単位補数 ~ ~0 -1 全ビットを反転させる
右ビットシフト(MSB 埋め) >> -1 >> 31 -1
右ビットシフト(0 埋め) >>> -1 >> 31 1
左ビットシフト(0 埋め) << 1 << 1 2 2 のべき乗

ビット演算を使ってアルゴリズムを考えられるようになりたい

用語

用語 説明
構文(Syntax) class, val, if プログラムが構造を持つための規則
式(Expression) 1, 1+1, "hoge" 評価することで値となるもの
評価 Scala の式をコンパイルすること
文(Statement) val i = 1 評価しても値にならないもの。

Unit

ifwhile といった式は()を返す。これはUnit と言われる型のオブジェクトの値である。

C 言語や Java でいうところの void にあたる。

クラスとオブジェクト

クラス

簡単に言うと、「複数のオブジェクトを作るためのひな形」。

クラスから作られるオブジェクトを「インスタンス」、状態を「フィールド」、振る舞いを「メソッド」と言う。またフィールドとメソッドを合わせて「メンバー」という。

ケースクラス

ふつうのクラスとほぼ一緒。
ケースクラスは不変なデータを作るのに適しており、パターンマッチングで有用である。

例えば変数宣言におけるパターンマッチは、タプルによる分割代入のような値の取り出しのことを指す。

case class CPoint(x: Int, y: Int)

val cp1 = CPoint(5,6)
val CPoint(a, b) = cp1

>>> a: Int = 5
>>> b: Int = 6

一瞬、val CPoint() って何やと思うけど、ここで大事なのはa, bの方。

その他、sealed classを用いることで enum を実装できる。逆に Java にはあるのになんで Scala はこれなんだろうか…

なお上記で「ほぼ一緒」と言ったが、通常のクラスと「同値性」が異なる。

簡単に言えば、ケースクラスではインスタンスが異なる場合であっても持っているフィールドが同じであれば同値と見なされる。値っぽい挙動。

ちなみに hashCodeequalsというメソッドをオーバーライドすれば通常のクラスにおいてもこの同値性を変更することが出来る。

オブジェクト

数あるオブジェクトの中でも、object キーワードを使って作成したオブジェクトは、他と異なりたったひとつのインスタンス(これを「シングルトンオブジェクト」という)しか持たない。Scala では「オブジェクト」という単語が、一般的なオブジェクト全般を指す場合と、シングルトンオブジェクトを指す場合とがあるので注意。

ユースケースとしては

  • グローバルな状態やユーティリティメソッドを表現するため
  • オブジェクトを作り出すためのメソッドを提供するため
  • アプリケーションなどのシングルトンオブジェクトをつくるため

があげられる。

コンパニオンオブジェクト

コンパニオンオブジェクトとは、クラス名と同じ名前を持つオブジェクトのこと。 applyメソッドを定義することで、new演算子を利用せずにインスタンスを作ること(これを「ファクトリメソッド」という)ができる。

なんでコンパニオンオブジェクトがあるの?(めっちゃ重要)

なんでclassだけじゃなくてobjectでコンパニオンオブジェクトを書かなきゃいけないのか全く分からなかったが、以下の記事を読んで納得できた。

https://qiita.com/geshi/items/0a789724b2419bd56204

意識しなければいけないのは、Scala は静的型付け言語であること。
先のブログの文章を引用すると、

しかし、静的型付き言語ではクラスに型を定義する必要があるので(Ruby と違うところ)、 型を定義されたクラスと、クラスを生成するものが必要となります。

ということになる。なので Scala で書くクラスには大概 object が必要となる(多分)。そしてその機能としては initialize メソッドとほぼ同じと考えていてよさそう。

ちなみにクラスに対して定義するものはコンパニオンオブジェクト、インスタンスに対して定義するものはクラスに書く。