exits

勉強記録

エンジニア研修(2) - Scala研修

Scala研修

前記事に引き続き,研修の話です.

5月の第3週からScalaの研修が始まって,初めてScalaを書いてみてました. テキストはこれです. https://dwango.github.io/scala_text/
ひたすら進めていきましたが,僕はメモ取る量が多めだったこともあって進むのが遅く,みんなすげーなーと思いながら話を聞いてました.
がんばってゆきたい.つよくなりたい.

おもしろかったことメモ

感想のお焚きあげです.

メソッドに複数の引数リストを取れる

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 101.to(10)
    .()が略されている
  • 1 :: 2 :: 3 :: NilNil.::(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

所感

みんなすごい.がんばりたい.(小並感組)
がんばってゆくぞ.