LoginSignup
1
1

Scala School/Basics 学習メモ

Last updated at Posted at 2020-03-16

はじめに

おそらくネット上にあるもっとも優れたScala教材の一つであろうScala Schoolについて、
気になったことや試したことなどを部分的に忘備録としてメモしておこうと思います。
Scala Schoolは説明が非常にさっぱりしているのでその補足になればいいかなと思います。
Lessonsごとに記事は分けます。まずは最初のlessonであるbasicsから。

本編

Functions

まずは関数定義の基本の形。

リスト1
def addOne(m: Int): Int = m + 1

戻り値の型(ふたつめの: Intの部分)は省略して書けるらしい。(リスト3など)

Anonymous functions

リスト2
val a = (x: Int) => x + 1
a(5) //結果は6

val b = (x: Int, y: Int) => x + y //複数の引数ももちろんOK
b(5,6) //結果は11

val c = (x: Int)(y: Int) => x + y //NG. 匿名関数で引数を2つのかっこに分ける形はできない

val d = (x: Int) => (y: Int) => x + y //どうしても匿名でcurriedの形で書きたい場合はこうする
d(3)(7) //結果は10

scalaではパターンcのような引数を複数のかっこに分けて書く形をcurried functionとしています(後述)が、本来的にはdの書き方のほうがクロージャを利用した正統なcurried functionなのかもしれません。
匿名でないcurried functionについては後述。

Partial applicaiton

リスト3
def adder(m: Int, n: Int) = m + n //まず定義(戻り値の型を省略しています)

val addTwoA = adder(2, _:Int) //これで部分適用できる
val addTwoB = adder(2, _)     //型指定を省略してもOK
val addTwoC = adder(_, 2)     //最後の引数だけでなくどの引数でもワイルドカードにできる

addTwoA(3) //結果は5

Curried functions

リスト4
def multiply(m:Int)(n:Int): Int = m * n //関数を定義

multiply(2)(3) //もちろん同時に両方のパラメーターを入力してもOK. 結果は6

val timesTwoA = multiply(2) _      //OK
val timesTwoB = multiply(2)(_)     //OK
val timesTwoC = multiply _(2)      //これはエラー
val timewTwoD = multiply(_)(2)     //これもエラー
val timesTwoE = multiply(_:Int)(2) //型指定を入れればOK

timesTwoA(3) //結果は6

パターンDはmissing parameter typeというエラーになりますが理由がよくわかりません。
stackoverflowで聞いてみてはいますが、まだ回答なし。(わかる方いたらお願いします:bow_tone1:)

Variable length arguments

リスト5
def capitalizeAll(args: String*) = {
  args.map { arg =>
    arg.capitalize
  }
}

個人的に少しひっかかったこのコード。実は引数は{}でも入力することができるようです。
実際

println{"asdf"}

これでも動きます。
式そのものも、オブジェクト・値としてあつかうのでこのようになっているのかもしれませんね。javaの習性であれ?と思いました。

Classes

基本的なクラス定義の書き方。

class Calculator {
    val brand: String = "HP"
    def add(m: Int, n: Int): Int = m + n
}

val calc = new Calculator //Javaと同様にnewでインスタンスを作る
calc.add(1, 2) //メソッドの呼び出しも同じ感じ
calc.brand //フィールドへのアクセス. 文字列HPが返ってくる

Constructor

クラス内のインスタンスメソッド定義の外側に書いたコードがコンストラクタとみなされるようです。

Abstract Classes

Javaと同じような感じで抽象クラスもあります。extendsするのも同じ感じ。

abstract class Shape {
    def getArea(): Int
}

class Circle(r: Int) extends Shape {
    def getArea(): Int = {r * r * 3}
}

Traits

フィールドと振る舞いをまとめたインターフェース的なもの。
トレイトは複数extendsできるので、抽象クラスよりこっちを使うほうが基本的にはよいとのこと。

trait Car {
  val brand: String
}

trait Shiny {
  val shineRefraction: Int
}

class BMW extends Car with Shiny {
  val brand = "BMW"
  val shineRefraction = 12
}

scala schoolは残念ながらscala3には対応していないようですが、
scala3では以下のようにwithを使わずシンプルにカンマつなぎで複数extendsができる!

class BMW extends Car, Shiny {
  val brand = "BMW"
  val shineRefraction = 12
}

Types

型パラメーターは[]で囲むらしい。

1
1
4

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
1