人気言語Scalaの大まかな入門編|基本や特徴について分かりやすく解説!

- システム
エンジニア - 現在話題になっているプログラミング言語のScalaについて詳しく教えてください。
- プロジェクト
マネージャー - 分かりました。プログラミング言語Scalaについてご紹介いたしましょう。
Scalaとは?
ScalaとはJavaをベースにしたプログラミング言語で、オブジェクト指向はもちろんのこと、関数型プログラミングも両方扱える現在注目のプログラミング言語です。
オブジェクト指向とは、プログラムを手順ではなくオブジェクト(モノ)の作成と操作とみる考え方のことです。代表的なものにJavaがあります。
関数型プログラミングとは、関数の組み合わせでプログラムを作成していく形式のものを指します。
Scalaのインストールの方法
ここではWindows10での話を進めます。参考サイトURLのページの通りにダウンロードし、それぞれをインストールして行きます。まず、ScalaではJavaのライブラリがそのまま使えます。そのためにJava 8 JDKかJava 11 JDKをインストールし、パスを通します。
そして、ビギナーにお勧めのScalaのIDE(総合開発環境)、IntelliJをインストールするかScala Build toolのsbtをインストールします。最後にScalaをインストール後、binフォルダのbatファイルをそれぞれダブルクリックすればScalaがインストール完了です。
ScalaでHello, World!
それでは、お決まりのHello, World!をPowerShellで表示してみましょう。ソースコードは下記の通りです。
1
2
3
4
5
6
7
|
object HelloWorld {
def main(args: Array[String]): Unit = {
println("Hello, world!")
}
}
|
これをobjectの名を冠にしたHelloWorld.scalaとして保存します。コンパイルは下記の通りです。
1
|
PS>scalac HelloWorld.scala
|
そして、
1
2
|
PS>scala -classthpath . HelloWorld
Hello, World!
|
と表示されます。
Javaとの関係
ScalaではJavaのパケージのクラスがそのままインポートできます。
1
2
3
4
5
6
7
8
9
10
11
12
|
import java.util.{Date, Locale}
import java.text.DateFormat._
object JapaneseDate {
def main(args: Array[String]): Unit = {
val now = new Date
val df = getDateInstance(LONG, Locale.JAPAN)
println(df format now)
}
}
|
Scalaではワイルドカード*は_となります。また、四則演算子の+や*などはスペースを空けなければなりません。
上記のソースコードは次のように表示されます。
1
|
2021年2月13日(コンパイル時点が2021年2月13日)
|
全てがオブジェクト
Scalaでは数値はもちろんのこと、予約語以外全てがオブジェクトとして扱われます。当然、関数もオブジェクトです。次に1秒ごとに「time flies like an arrow…」と表示するプログラムを作ります。ソースコードは次の通りです。
1
2
3
4
5
6
7
8
9
10
11
12
13
|
object Timer {
def oncePerSecond(callback: () => Unit): Unit = {
while (true) { callback(); Thread sleep 1000 }
}
def timeFlies(): Unit = {
println("time flies like an arrow...")
}
def main(args: Array[String]): Unit = {
oncePerSecond(timeFlies)
}
}
|
ここで関数の部分は次の箇所です。
1
2
3
4
5
|
def timeFlies(): Unit = {
println("time flies like an arrow...")
}
|
匿名関数
先のプログラムで関数はtimeFiles()だけです。それも1度きりしか使用しません。このような場合は匿名関数を使ってプログラムを簡略できます。ソースコードは以下の通りです。
1
2
3
4
5
6
7
8
9
10
11
|
object TimerAnonymous {
def oncePerSecond(callback: () => Unit): Unit = {
while (true) { callback(); Thread sleep 1000 }
}
def main(args: Array[String]): Unit = {
oncePerSecond(() =>
println("time flies like an arrow..."))
}
}
|
Scalaでは匿名関数は=>で表します。
クラス
Scalaはオブジェクト指向言語ですので、クラスという概念を持っています。Javaの構文と似ていますが、Scalaのクラスではパラメーターを持つことができます。以下の複素数を表すソースコードを見てください。
1
2
3
4
5
6
7
8
9
10
11
12
13
|
class Complex(real: Double, imaginary: Double) {
def re() = real
def im() = imaginary
}
object ComplexNumbers {
def main(args: Array[String]): Unit = {
val c = new Complex(1.2, 3.4)
println("imaginary part: " + c.im())
}
}
|
これをコンパイルすると
1
|
imaginary part: 3.4
|
と表示されます。
しかし、実部と虚部のreとimのメソッドは、それらを呼ぶとき()をつけなければなりません。Scalaでは、それがフィールドのようにアクセスできるのです。引数なしのre、imとだけのメソッドがあるのです。
1
2
3
4
5
6
|
class Complex(real: Double, imaginary: Double) {
def re = real
def im = imaginary
}
|
継承とオーバーライド
Scalaにおいては、全てのクラスはスーパークラスを継承します。先の複素数のプログラムのように、スーパークラスが指定されていないときには、暗黙的にscala.AnyRefが使用されます。
Scalaでは、スーパークラスから継承されたメソッドはオーバーライドできます。その時に想定外のオーバーライドを防ぐために、override修飾子を明示的に書き込んで指定することが必須です。
先の複素数のプログラムを使ってオーバーライドを見てみましょう。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
|
class Complex(real: Double, imaginary: Double) {
def re = real
def im = imaginary
override def toString() =
"" + re + (if (im >= 0) "+" else "") + im + "i"
}
object ComplexNumbers {
def main(args: Array[String]): Unit = {
val c = new Complex(1.2, 3.4)
println("imaginary part: " + c.im)
println("Overridden toString(): " + c.toString)
}
}
|
これが、
1
2
|
imaginary part: 3.4
Overridden toString(): 1.2+3.4i
|
と出力されれば、toStringがoverrideされたことになります。
case classとパターンマッチ
Scalaでの木(ツリー)がどのように表現され、操作されるのか見てみましょう。Javaでは木は具象クラスで表現され、関数型プログラミングでは代数的に表現されますが、Scalaではcase classというもので表現されます。
1
2
3
4
5
6
|
abstract class Tree
case class Sum(l: Tree, r: Tree) extends Tree
case class Var(n: String) extends Tree
case class Const(v: Int) extends Tree
|
case classと通常のクラスの違いは、次の通りです。
●new演算子が必要ない
●ゲッター関数は自動的に定義される
●メソッドequalsとhashCodeのデフォルト定義が提供される
●case classのインスタンスはパターンマッチで分解できる
環境の型
データ型を定義できたので、ある環境における式を評価する関数から始めます。環境の目的は変数に値を与えることです。
1
2
3
|
type Environment = String => Int
|
これで評価関数を定義できます。
評価関数eval
1
2
3
4
5
6
7
|
def eval(t: Tree, env: Environment): Int = t match {
case Sum(l, r) => eval(l, env) + eval(r, env)
case Var(n) => env(n)
case Const(v) => v
}
|
●tがSumかどうか評価します。もしそうならば左部分木をl、右部分木をrとします。そして、矢印に続く式を評価します。
●もし最初の評価が違うのであれば、つまり、木がSumでなければtがVarであるか評価します。評価が正ならばVarノードに含まれる変数をnにし、右側の式に進みます。
●もし2つめも違うのであれば、つまり、tがSumでもVarでもなければConstであるかどうかを評価します。そうであるならばConstノードの含まれる値を変数vとします。そして、右側に進みます。
●最後に全ての評価にマッチしなければ、例外が発生します。
パターンマッチとは、連続する値のパターンにマッチさせてみて、マッチすれば値に名をつけ抽出し、最終的にそれらの名のついた値を何らかのコードで評価することをいいます。
評価関数derive
次に数式微分を定義します。ソースコードは次の通りです。
1
2
3
4
5
6
7
|
def derive(t: Tree, v: String): Tree = t match {
case Sum(l, r) => Sum(derive(l, v), derive(r, v))
case Var(n) if (v == n) => Const(1)
case _ => Const(0)
}
|
●Sumの微分係数は微分係数の和です。
●ある変数vの微分係数は、変数vで微分されれば1、そうでなければ0です。
●定数の微分係数は0です。
main関数の定義
簡単なmain関数を定義します。ソースコードは次の通りです。
1
2
3
4
5
6
7
8
9
10
|
def main(args: Array[String]): Unit = {
val exp: Tree = Sum(Sum(Var("x"),Var("x")),Sum(Const(7),Var("y")))
val env: Environment = { case "x" => 5 case "y" => 7 }
println("Expression: " + exp)
println("Evaluation with x=5, y=7: " + eval(exp, env))
println("Derivative relative to x:\n " + derive(exp, "x"))
println("Derivative relative to y:\n " + derive(exp, "y"))
}
|
まず、環境における{x -> 5, y -> 7}を計算し、次にxとyの微分係数を求めます。
整理すると
全てのプログラムを整理し、object Calcで囲むと次のようになります。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
|
abstract class Tree
case class Sum(l: Tree, r: Tree) extends Tree
case class Var(n: String) extends Tree
case class Const(v: Int) extends Tree
object Calc{
type Environment = String => Int
def eval(t: Tree, env: Environment): Int = t match {
case Sum(l, r) => eval(l, env) + eval(r, env)
case Var(n) => env(n)
case Const(v) => v
}
def derive(t: Tree, v: String): Tree = t match {
case Sum(l, r) => Sum(derive(l, v), derive(r, v))
case Var(n) if (v == n) => Const(1)
case _ => Const(0)
}
def main(args: Array[String]): Unit = {
val exp: Tree = Sum(Sum(Var("x"),Var("x")),Sum(Const(7),Var("y")))
val env: Environment = { case "x" => 5 case "y" => 7 }
println("Expression: " + exp)
println("Evaluation with x=5, y=7: " + eval(exp, env))
println("Derivative relative to x:\n " + derive(exp, "x"))
println("Derivative relative to y:\n " + derive(exp, "y"))
}
}
|
このソースコードをCalc.scalaとして保存し、コンパイルします。次のように出力されれば成功です。
1
2
3
4
5
6
|
Expression: Sum(Sum(Var(x),Var(x)),Sum(Const(7),Var(y)))
Evaluation with x=5, y=7: 24
Derivative relative to x:
Sum(Sum(Const(1),Const(1)),Sum(Const(0),Const(0)))
Derivative relative to y:
Sum(Sum(Const(0),Const(0)),Sum(Const(0),Const(1)))
|
- システム
エンジニア - ありがとうございます。わたしもScalaを習得してみようと思います。
- プロジェクト
マネージャー - そうですね。ScalaはJavaをベースにしたプログラミング言語ですので、理解しやすいと思います。
Scalaを学ぼう
Scalaの入門編として解説しましたがいかがでしたでしょうか。ここではトレイトとジェネリクスには言及しませんでしたが、Scalaの理解を深めたい方はぜひ調べてみてください。
Scalaは人気のプログラミング言語ですので、基本を学んだならば、どんどん自分でコードを書いて挑戦してみましょう。
FEnet.NETナビ・.NETコラムは株式会社オープンアップシステムが運営しています。
株式会社オープンアップシステムはこんな会社です
秋葉原オフィスには株式会社オープンアップシステムをはじめグループのIT企業が集結!
数多くのエンジニアが集まります。

-
スマホアプリから業務系システムまで
スマホアプリから業務系システムまで開発案件多数。システムエンジニア・プログラマーとしての多彩なキャリアパスがあります。
-
充実した研修制度
毎年、IT技術のトレンドや社員の要望に合わせて、カリキュラムを刷新し展開しています。社内講師の丁寧なサポートを受けながら、自分のペースで学ぶことができます。
-
資格取得を応援
スキルアップしたい社員を応援するために資格取得一時金制度を設けています。受験料(実費)と合わせて資格レベルに合わせた最大10万円の一時金も支給しています。
-
東証プライム上場企業グループ
オープンアップシステムは東証プライム上場「株式会社オープンアップグループ」のグループ企業です。
安定した経営基盤とグループ間のスムーズな連携でコロナ禍でも安定した雇用を実現させています。
株式会社オープンアップシステムに興味を持った方へ
株式会社オープンアップシステムでは、開発系エンジニア・プログラマを募集しています。
年収をアップしたい!スキルアップしたい!大手の上流案件にチャレンジしたい!
まずは話だけでも聞いてみたい場合もOK。お気軽にご登録ください。


Java新着案件New Job
-
設計情報のビューアシステムマイグレーション/東京都品川区/【WEB面談可/C#経験者/20代後半~40代の方活躍中/経験年数不問】
月給41万~43万円東京都品川区(大崎駅) -
設計情報のビューアシステムマイグレーション/東京都品川区/【WEB面談可/C#経験者/20代前半の方活躍中/経験1年以上の方活躍中】
月給29万~31万円東京都品川区(大崎駅) -
大手製造会社販売物流システム再構築<アプリ設計>/神奈川県茅ヶ崎市/【WEB面談可/C#経験者/20代後半~40代の方活躍中/経験年数不問】
月給41万~50万円神奈川県茅ヶ崎市(-駅) -
大手製造会社販売物流システム再構築<アプリ設計>/神奈川県茅ヶ崎市/【WEB面談可/C#経験者/20代前半の方活躍中/経験1年以上の方活躍中】
月給29万~34万円神奈川県茅ヶ崎市(-駅) -
医療向けWebアプリケーションのカスタマイズ対応/東京都品川区/【WEB面談可/C#経験者/20代後半~40代の方活躍中/経験年数不問】
月給48万~50万円東京都品川区(大崎駅) -
医療向けWebアプリケーションのカスタマイズ対応/東京都品川区/【WEB面談可/C#経験者/20代前半の方活躍中/経験1年以上の方活躍中】
月給32万~34万円東京都品川区(大崎駅)