Scala入門 基礎編「Scalaの書き方を理解しよう」 – PHP使いからScala使いへ転身!


はじめに

みなさんこんにちは、プロダクト開発本部の亀梨です。
普段はXmediaOneというメディアプランニング・広告運用管理・トラッキング・マーケティング分析を行う
統合プラットフォームの開発を担当しています。

さて、今回はScala入門第二弾として、Scalaの書き方を紹介する基礎編をお送りします。
Scala初心者のわたくしが、言語習得のために得た知識をここにまとめていきたいと思います。
主に参考にした記事及び書籍は以下の通りでっす。

また適宜コードの実行例を記していきますので、実際に動かしてみたい方は
事前にScalaおよびsbtをインストールしておいていただければと思います。
詳しい方法は前回の記事「Scala入門 準備編」をご覧ください。

基礎

変数

変数は「val」と「var」の二種類。valは後から変更できない変数で、副作用が起きないため使用を推奨されています。

  • val = イミュータブル(変更不可)
  • var = ミュータブル(変更可)

演算子

Scalaは基本型を操作する演算子を豊富に提供しています。

算術演算子

関係演算子と論理演算子

演算子の優先順位

    (他のすべての特殊文字)

  1. * / %
  2. + –
  3. :
  4. = !
  5. < >
  6. &
  7. ^
  8. \|
  9. (すべての英字)
  10. (すべての代入演算子)

関数

関数の主な定義は以下の通りです。

  • 関数定義はdefで始まる
  • 関数名は慣例的にキャメルケースを使用(Javaと同じ)
  • 引数の定義は[変数名]: [データ型]の形式(複数可)
  • 引数のデータ型は省略不可
  • 返り値のデータ型は引数の後に: [データ型]の形式で行う
  • 返り値のデータ型は省略可能
  • 関数の定義と関数本体のブロックを=で繋ぐ必要がある
  • 関数本体が1行のみの場合は本体ブロックの中括弧{}は省略可
  • 本体ブロックで最後に実行された式が返り値となるのでreturnは不要

引数の無い関数では、括弧を省略することができます

匿名(無名)関数

他の言語同様、Scalaでも匿名(無名)関数をつくることができます

この関数はxという名前のIntに1を加えます

匿名関数を渡したり、valに保存することができます

関数が複数の式で構成されている場合は、{}を使用します

可変長引数も使えます

型推論

Scalaでは型を明示的に指定しなくても、セットされた値から自動的に型を推測、判断し設定しています。
ただ、可読性や保守性を考えると基本的に型は明示的に設定すべきです。

制御構文

他の言語と同様、while、foreach、forがあります。

whileによるループ

foreachとforによる反復実行

基本(データ)型

整数リテラル

Byte, Short, Int, Long, Charをまとめて整数値型と呼びます。
そしてFloat, Doubleを合わせて数値型と呼びます。

基本型 範囲
Byte 2の補数表現の8ビット符号付き整数(-2の7乗以上、2の7乗-1以下)
Short 2の補数表現の16ビット符号付き整数(-2の15乗以上、2の15乗-1以下)
Int 2の補数表現の32ビット符号付き整数(-2の31乗以上、2の31乗-1以下)
Long 2の補数表現の64ビット符号付き整数(-2の63乗以上、2の63乗-1以下)
Char 16ビット符号なしUnicode文字(0以上、2の16乗-1以下)
String Charのシーケンス
Float 32ビットのIEEE 754単精度浮動小数点数
Double 64ビットのIEEE 754単精度浮動小数点数
Boolean trueまたはfalse
Int

Long

整数リテラルの末尾にLまたはlが付きます

Short、Byte

Short及びByte型は、Intリテラルを代入した場合、値がそれらの型の範囲内に収まっていれば、リテラルの型はShortやByteとして扱われます

浮動小数点数リテラル

Float, Double = 小数点が含まれている、末尾にオプションのEまたはeが付いている
Float = 末尾にFまたはfが付いています
Double = Floatのオプションが付いていない、または末尾にDが付いている

文字リテラル

シングルクォートで一文字を囲んだもの

文字列リテラル

ダブルクォートで文字を囲んだもの

複数行文字列リテラル

“””で囲むことで複数上の文字を表現できます

シンボルリテラル

Scalaのシンボルは、シングルクォーテーション「’」に続く英文字で構成された認別子を使って表します。

Booleanリテラル

trueとfalseの2個のリテラル

文字列補間

Scalaは柔軟な文字列補間の仕組みを備えており、それによって文字列リテラルを加工して式に含めることができます。

S補間子

文字列の中に変数の値を呼び出すことができます

raw補間子

S補間子と違い、文字列リテラルのエスケープシーケンスを認識しません

f補間子

書式を指定して出力します

UNIT

関数が意味する値を返さない場合の結果型(returnしていない)

配列(Array)

配列は順序を保持し、重複を含むことができ、変更可能、異なる型の値を保持できる

リスト(List)

リストは順序を保持し、重複を含むことができ、不変、異なる型の値を保持できる

重要なListメソッドとその使い方

コード 意味
List() または Nil 空リスト
List(“Cool”, “tools”, “rule”) “Cool”, “tools”, “rule” の3個の値を持つ新しいList[String]を作る
val thrill = “Will” :: “fill” :: “until” :: Nil “Will”, “fill”, “until” の3個の値を持つ新しいList[String]を作る
List(“a”, “b”) ::: List(“c”, “d”) 2個のリストを連結する(“a”, “b”, “c”, “d”の4個の値を持つ新しいList[String]を返す)
thrill(2) thrillリストの添字2(先頭は0)の要素を返す(”until”が返される)
thrill.count(s => s.length == 4) thrillの中で長さが4の要素の数を返す(2が返される)
thrill.drop(2) 先頭の2要素を取り除いたthrillリストを返す(List(“until”)が返される
thrill.dropRight(2) 末尾の2要素を取り除いたThrillリストを返す(List(“Will”)が返される)
thrill.exists(s => S == “until”) thrillの中に値が”until”の要素があるかどうかを返す(trueを返す)
thrill.filter(s => s.length == 4) thrillに含まれる長さが4のすべての要素を順に並べたリストを返す(List(“Will”, “fill”)が返される)
thrill.forall(s => s.endsWith(“l”) thrillリストのすべての要素について、末尾の文字が”l”になっているかどうかを返す(trueを返す)
thrill.foreach(s => print(s)) thrillリストに含まれる1つ1つの文字列を対象としてprint文を実行する(”Willfilluntil”と表示される)
thrill.foreach(print) 上の省略版
thrill.head thrillリストの戦闘要素を返す(”Will”が返される)
thrill.init thrillリストから末尾の要素を除いた残りのリストを返す(List(“Will”, “fill”)が返される)
thrill.isEmpty thrillリストが空かどうかを返す(falseが返される)
thrill.last thrillリストの最後の要素を返す(”until”が返される)
thrill.map(s => s + “y”) thrillリストの各要素に”y”を追加したものから構成されるリストを返す(List(“Willy”, “filly”, “untily”)が返される
thrill.mkString(“, “) 引数に渡した区切り文字でリストの要素を結合した文字列を作る(”Will, fill, until”が返される)
thrill.filterNot(s => s.length == 4) thrillリストに含まれる長さが4以外のすべての要素を順に並べたリストを返す(List(“until”)が返される)
thrill.reverse thrillリストのすべての要素を逆に並べたリストを返す(List(“until”, “fill”, “Will”)が返される)
thrill.sortWith((s, t) => s.charAt(0).toLower < t.charAt(0).toLower) thrillリストのすべての要素から、先頭文字を小文字にしてアルファベット順を決めて、その順序に従ったリストを作って返す(List(“fill”, “until”, “Will”)が返される)
thrill.tail thrillリストから戦闘要素を取り除いたものを返す(List(“fill”, “until”)が返される)

Set(集合)

Setは順序を保持せず、重複を持たない

Tuple(タプル)

リストと同様にイミュータブルだが、リストとは異なり、違う型の要素を持つことができる

ケースクラスとは異なり、名前付きアクセサーはない。
代わりに、位置に基づいて名前が付けられ、0ベースではなく1ベースのアクセサーがある。

タプルはパターンマッチングにうまく収まります。

Map(マップ)

クラスとオブジェクト

概要をまとめると以下の通りです。

    • クラス定義の中には、フィールド(field)とメソッド(method)を配置する
    • フィールドはオブジェクトを参照する変数で、valまたはvarで定義する

<liメソッドは実行可能なコードを格納するもので、defを使って定義する。

アクセス修飾子

Scalaでは明示的にアクセス修飾子を指定しなければ、メンバーは公開(public)となる。つまりデフォルトが公開なので明示的に書かなくて良いです。
また、フィールドの前に「private」というアクセス修飾子を挿入すると非公開となります。
privateを宣言した非公開フィールドにアクセスできるのは、同じクラス内で定義されたコードだけになります。

メソッド

メソッドに渡されるパラメーターはvarではなくvalなので、再代入ができません。

コーディングスタイル

基本形
  • 文末のセミコロンはオプションのため記述不要

省略形
  • returnを明示しない
  • 中括弧を省略
  • 結果型を省略

推奨形
  • returnを明示しない
  • 型は省略せず(型推論を使わず)書く

コンストラクタ

コンストラクタはクラス内のメンバーフィールドを初期化するのに使います

シングルトンオブジェクト

Scalaはクラスが静的メンバー(static member)を持てない代わりに、シングルトンオブジェクト(singleton objects)を持ちます。
特徴は以下の通りです。

  • シングルトンオブジェクトの定義は、classキーワードの代わりにobjectキーワードを使う
  • シングルトンオブジェクトがクラスと同じ名前を持つとき、そのクラスの「コンパニオンオブジェクト」と呼ばれる
  • クラスとコンパニオンオブジェクトは互いの非公開メンバーにアクセスできる

オブジェクト

オブジェクトは、クラスの単一のインスタンスを保持するために使用されます。

継承

他の言語と同様、継承が使えます

メソッドの上書きも可能です

抽象クラス

抽象クラスは、いくつかのメソッドを定義して実装していないクラスを定義することができます。
代わりに、抽象クラスを継承するサブクラスがこれらのメソッドを定義します。
抽象クラスのインスタンスを作成することはできません。

トレイト

Scalaのトレイトはクラスに比べて以下のような特徴があります。

  • 1つのクラスでは、withキーワードを使用して複数のトレイトを継承することができます
  • 直接インスタンスすることができない
  • コンストラクタの引数を取ることができない

パッケージ

パッケージ内でコードを整理することができます。
ファイルの先頭に、そのパッケージ内にあるすべてのファイルが宣言されます。

値と関数は、クラスやオブジェクトの外に置くことはできません。
オブジェクトは、静的関数を編成するのに便利なツールです。

パッケージ内のメンバーに直接アクセスできます。

パターンマッチング

Scalaでは便利なパーツに match があります

様々なタイプのマッチング

さまざまな型の値を別々に扱うためにmatchを使うことができます。

以上

というわけで、ズラッとScalaの書き方についてまとめてみました。
ただのまとめっぽくなってしまいましたが、Scalaの雰囲気を感じ取ってもらえればと思います。

次回は、実際にScalaで何か作っていく内容にして、より実践的にしていこうかと思います。
それではまた次回!


DACエンジニア採用情報

  関連記事

【未経験からのRuby on Rails – 第3回】変数と定数

こんにちは。新卒1年目のmatsuariです。 今回はRubyに限らずプログラミングを学ぶ上で非常に重要となる「変数と定数」について、ご紹介していきます。 変数とは・・・ オブジェクトを一時的に格納しておく箱で、オブジェクトを識別するために利用します。 言葉だけでは理解が難しいかと思いますので、まず …

Railsたった14行でアドサーバーAPIができた話

こんにちは。駆け出しエンジニアの近江です。 最近Railsにハマっているので、私が2年間担当しているアドサーバの、簡易版をRailsで作ってみました。 広告やキャンペーンを登録する管理画面はある前提で、ここからたった14行追加するだけでアドサーバーのHTTP APIを作りたいと思います。ついでに配信 …

【未経験からのRuby on Rails – 第4回】Railsアプリケーション開発をしよう! 〜開発の準備編〜

こんにちは。新卒のmatsuariです。 Rubyについてまだまだ知るべきことはたくさんありますが、とにかく早くアプリを作りたい! ということで、今回はアプリ開発の準備に取り掛かっていきます。 Rubyはアプリを作成しながら、同時に学んでいきたいと思います。 Railsアプリケーション開発の準備《 …

no image
gulp.jsで広告タグの開発環境を整える

SEOの観点から、サイト表示速度の高速化のためJavaScriptファイルから不用な空白や改行、 コメントを除去したりやローカル変数名を短縮するminifyが奨励されていますが、 これはタスクランナーのgulp.jsとプラグインを使って自動化する事が可能です。 ※gulpの基本的な使い方については下 …

no image
Angular.jsのvalueとfactoryの違いを考える

次のようなHTMLがあったとする。 [code language=”html”] <!doctype html> <html lang="jp" ng-app="App"> <head> <me …

Qiita Team API と Google Spread Sheet でチーム日報を生成する

チーム日報を活用する MarketOne 開発チームでは複数拠点に分かれての開発を行っています。リモート開発が中心となると口頭でのコミュニケーションに限界があるため、テキストベースのコミュニケーションの比重が高い状態にあります。 チケットシステムやソースコード管理ツール上の議論はもちろんおこなってい …

PyStanによるはじめてのマルコフ連鎖モンテカルロ法

はじめに こんにちは。システム開発部の中村です。 社内で行っている『データ解析のための統計モデリング入門』(所謂緑本)の輪読会に参加した所、 大変わかりやすい本だったものの、Macユーザには悲しい事に実装サンプルがWinBUGSだったため、 9章の一般化線形モデルのベイズ推定によるアプローチをPyt …

no image
Polymer core-ajax の使い方

Polymerのcore-ajaxの使い方。 まずは、index.html [code language=”html” title=”index.html”] <!doctype html> <html> <head&gt …

読み方がわからない技術用語 2015

英語圏での読み方を基本的には参考にしています。英語圏でも複数の読み方をしているケースもあるようなので、あくまでも参考程度。2015と書きながら、古い言葉も混じってますが。 async – えーしんく Alt – おると ASUS – えいすーす bower &#8 …

no image
Polymer on Rails

Web Componentsをご存知だろうか。これが普及すればWebの開発は画期的に変わるだろう。 説明すると長くなるので、LIGさんのにその辺はお任せして。(この記事読んでください。) 簡単に言えば、下記にあるような新たに提案されたブラウザ向けAPIの総称。 Custom Elements, 説明 …