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エンジニア採用情報

  関連記事

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

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

GoogleスプレッドシートからTreasureDataへデータを取り込む

AudienceOneの開発を担当しています。skryoです。 またまたTreasureDataネタですが、今回はGoogleスプレッドシートからGoogleAppsScriptを使ってTreasureDataへデータを取り込む手順を紹介したいと思います。 なぜ? Googleスプレッドシート上でマ …

Scala入門 準備編「開発環境構築」 – PHP使いからScala使いへ転身!

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

no image
Polymer on Rails

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

ディープラーニングで「顔が似ているAKB48のメンバーを教えてくれるbot」を構築

概要 こんにちは、システム開発部の中村です。 今回は、Facebook Messenger APIを利用して、 画像をアップロードすると、似ているAKB48のメンバーを教えてくれるbotを実装しました。 尚、ディープラーニングやTensorFlowそのものの解説というより、 「エンジンとしてディープ …

D3.jsとその活用事例について

D3.jsとは? D3とは「Data Driven Document」の略で、データに基づいてドキュメントを操作するための JavaScript ライブラリです。 ご存知の方も多いと思いますが、ちょっとだけD3.jsの基本的な使い方、そして弊社プラットフォームでの利用についてご紹介したいと思います。 …

SDKってどうやって作ってるの?【Android編】

こんにちは。4度目の投稿です。 現在私はAndroidのSDKを開発しています。 javaにもAndroidにもSDKにも手を出したのは初めてなので、最初はそもそもSDKのイメージが湧かず、ふわふわした状態で始めました。 SDKと調べても「あるソフトウェアを開発するために必要なプログラムや文書などを …

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

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

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

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

no image
【未経験からのRuby on Rails – 第1回】楽しく書けるプログラミング言語 “Ruby” とは

こんにちは、はじめまして。新卒1年目のmatsuari(女子)です。 この度、Rubyの勉強を始めることになりまして、 まずはたくさんあるプログラミング言語の中で、なぜ自分がRubyを学ぶのか? しっかりと把握した上で学習に取り組んでいきたいと考え、『Rubyとは何か?』調べました。 超基礎的なこと …