Scala研修
前記事に引き続き,研修の話です.
5月の第3週からScalaの研修が始まって,初めてScalaを書いてみてました.
テキストはこれです.
https://dwango.github.io/scala_text/
ひたすら進めていきましたが,僕はメモ取る量が多めだったこともあって進むのが遅く,みんなすげーなーと思いながら話を聞いてました.
がんばってゆきたい.つよくなりたい.
つよくつよくなりたい
— る (@yue_roo) 2017年5月23日
おもしろかったことメモ
感想のお焚きあげです.
メソッドに複数の引数リストを取れる
def add(a: Int)(b: Int): Int = { a + b }
のように定義して,adder.add(2)(3)
と使う.
部分適用もおもしろい.
scala> val adder2 = adder.add(2)_ adder2: Int => Int = $$Lambda$1355/1682908357@730044d8 scala> adder2(3) res2: Int = 5
トレイト
- 複数のトレイトを1つのクラスやトレイトにミックスインできる.
- 直接インスタンス化できない
val a = new TraitA
はエラーval a = new TraitA {}
はその場でTraitA
を継承した無名のクラスを使う,ことになるためOK.- ただし型は別のものになっている.
scala> trait TraitA defined trait TraitA scala> val a = new TraitA {} a: TraitA = $anon$1@33578a24 scala> class ClassB extends TraitA defined class ClassB scala> val b = new ClassB b: ClassB = ClassB@523e2c1f
変位指定
- 非変(invariant)
型パラメータを持ったクラスGがあり,型Aがあるとき
G[A] = G[A]
という代入ができる.
scalaではclass G[A]
という定義で不変になる.(デフォルト) - 共変(covariant)
型パラメータを持ったクラスGがあり,AがBを継承している場合(に限り)
G[B] = G[A]
という代入ができる.(イメージ: 抽象に具体を代入)
scalaではclass G[+A]
という定義をすることでその型パラメータ(あるいはクラス)は共変になる.
Javaではデフォルトで共変である.
一度インスタンス化した後に変更されることのない(変更機能のない)クラスは安全に共変にできる. - 反変(contravariant)
型パラメータを持ったクラスGがあり,AがBを継承している場合(に限り)
G[A] = G[B]
という代入ができる.
scalaではclass G[-A]
という定義をすることでその型パラメータ(あるいはクラス)は反変になる.
無名関数
add
という関数を作成
apply
メソッドにしておくとadd.apply(1, 2)
をadd(1, 2)
と書ける.
val add = new Function2[Int, Int, Int]{ def apply(x: Int, y: Int): Int = x + y }
- 無名関数のオブジェクト(
FunctionN
) を作り,add
に代入
val add = (x: Int, y: Int) => x + y
カリー化
複数の引数を取る関数を,引数1つの関数のチェインとして表現すること.
(Int, Int) => Int
-> Int => Int => Int
add(1, 2)
-> add(1)(2)
中置記法の中身は見ると楽しい
1 to 10
は1.to(10)
.
,()
が略されている1 :: 2 :: 3 :: Nil
はNil.::(3).::(2).::(1)
メソッド名の最後が:
の場合,非演算子の前後を反転し,右結合する
左畳み込み
foldLeft
畳み込み(convolution)ではない.
match式
- コレクションの一部にマッチさせるようなことができる.
例:List("A", b, c, d, e)
- マッチ部分を取り出す
- マッチ対象部分のとき:
List("A", b@"B", c, d, e)
のようにする.(as構文) - マッチ対象以外の部分: 変数にしておく(上のc, d, eなど)
- マッチ対象部分のとき:
- フォールスルーではない
- 型によるパターンマッチ
case v: String => "do something"
- 型変数を使ったパターンマッチはできない.(Scalaコンパイラによる型消去が行われるため)
v: List[_] =>
のようにワイルドカードを使うとよい
S99でも楽しく使ってます.
case object / case class
sealed abstract class DayOfWeek case object Sunday extends DayOfWeek case object Monday extends DayOfWeek val x: DayOfWeek = Sunday x match { case Sunday => 1 case Monday => 2 ... }
sealed
スーパークラス/トレイトにつけると,そのサブクラス/トレイトは同じファイル内にしか定義できない.
これを利用すると,x match
でのパターン漏れがあれば指摘してくれるようになる. (このファイルにしか書いてないはずだから全部把握できてるはず,なのに全部無いから怒る,みたいな?)
二分木の例題とか(一部)やりました.
Option, Either, Try
便利.
慣れるまで挙動を把握しにくいとは思うけど.
Functor, Applicative Functor, Monad, Monoid
むずかちい.
どういう話なのかは分かった(気がする)けど,実際にどう使うのかとか,どういう時に考えないといけない話なのかとかがわかってません.
まぁテキストでも紹介という程度だったので...またいつかm(_ _)m
所感
みんなすごい.がんばりたい.(小並感組)
がんばってゆくぞ.
飲みすぎてやらかして朝も起きれず非常に反省している今,酒が家に届きました
— る (@yue_roo) 2017年5月22日