Slide 1

Slide 1 text

プログラミング言語Scalaの歴史と概要 2023/04/21(金) Nextbeat Tech Bar 水島 宏太(@kmizu)

Slide 2

Slide 2 text

最初に ● 途中で割り込んでの質問も歓迎します ○ よくわからない用語があった ○ 突っ込んだ解説が欲しいとか ● カジュアルな感じでできればという温度感

Slide 3

Slide 3 text

自己紹介 ● 水島宏太(みずしまこうた) / @kmizu(けーみず) ○ どちらでもお好きな方で ● 5月に転職します → DMG森精機株式会社 / 株式会社WALC ● SNSアカウント ○ Twitter: https://twitter.com/kmizu ○ GitHub: https://github.com/kmizu ● プログラミング言語&構文解析マニア ○ 情報処理学会プログラミング研究会編集委員……だった ■ 2023年3月で4年の任期終了 ● 最近はChatGPT (GPT-3.5 / GPT-4)と戯れる日々 ● Scala普及活動などなどやってます

Slide 4

Slide 4 text

大阪市内の風景 in 弁天町

Slide 5

Slide 5 text

それはともかくScalaの話

Slide 6

Slide 6 text

Scalaって何? ● Martin Odersky教授が開発したプログラミング言語 ○ スイス連邦工科大学ローザンヌ校(EPFL)教授 ○ 2003年生まれの比較的新しい言語 ○ javac(1.5以降)やJava Genericsの開発者でもある ● オブジェクト指向言語 ○ Javaのオブジェクト指向がベース ● 静的型付け ○ Javaより強い(厳しい)チェックが可能 ● JVM言語 ○ Java仮想マシン(Java Virtual Machine)上で処理系が動作 ● 2008年にTwitter社が採用して以降、産業界での利用が進む ○ 最近はそのTwitterも色々……はおいておく

Slide 7

Slide 7 text

Scala略式年表 ● 2003年:最初のバージョンが誕生 ● 2006年:Scala 2.0リリース ● 2008年:Twitter社が部分的に採用 ○ ブレイクのきっかけ ○ 2011年以降、本格的に利用(特にバックエンド) ■ Twitterが落ちにくくなるきっかけの一つ ● 2010年:Scala Days(初回開催)、Scala 2.8リリース ○ 初めての国際Scalaイベント ○ 以後、Scala Daysは毎年開催 ● 2013年:Scala 2.10リリース(現在のScalaの基本) ● 2014年:Scala 2.11リリース ● 2016年:Scala 2.12リリース ● 2019年:Scala 2.13リリース(Scala 2.x系列最新の安定版) ● 2021年:Scala 3.0.0リリース(Scala 3最初のリリース) ● 2021年10月:Scala 3.1.0リリース ● 2022年8月:Scala 3.2.10リリース ● 2023年1月:Scala 3.2.2リリース

Slide 8

Slide 8 text

Scalaの採用事例 ● 世界中で普通に使われている ○ C/C++/Java/C#辺りと比べれば二段階くらいユーザ数は少ない ● 海外 ○ 一番のヘビーユーザ:Twitter ■ 最近、API有料化で多少雲行きが怪しいけども ○ LinkedIn, PayPal, Morgan Stanley, Coursera, eBay, Guardian, etc. ● 日本 ○ はてな、ドワンゴ、ChatWork、ビズリーチ、サイバーエージェント、ネクストビート他多数

Slide 9

Slide 9 text

ScalaMatsuri (2020) ● 参加者500名超

Slide 10

Slide 10 text

私とScalaの関わり (あるいは国内でのScala)

Slide 11

Slide 11 text

Scalaとの出会い(2005) ● 大学4年生(2005)くらいの頃にScala 1.xを発見 ● 売り文句は、.NETとJVM両方で動作 ● 少しだけ触った→すぐ飽きた

Slide 12

Slide 12 text

Scalaとの再会(2007) ● 修士2年の時 ○ Scala 2.5の頃 ● 面白い言語機能がたくさん→夢中に ○ Existential Type ○ Implicit Conversion ○ Structural Subtyping ○ Abstract Type ○ … ● LL魂(2007)でLT発表 ○ Power of Scala ● 2008年以後、本格的にScalaに関わっていくことに

Slide 13

Slide 13 text

Scalaユーザ会&scala-be(2009) ● 豆蔵の羽生田さんと私を中心として結成されたコミュニティ ○ 羽生田さんがコップ本の監修をしていて、それで縁があった記憶(曖昧) ● 約30名くらいのメンバー ● 東京ローカルなコミュニティ ● 定期的なScala関連の勉強会 in 豆蔵 ○ Scala言語仕様輪読会 by kmizu ○ 30名くらいの参加者

Slide 14

Slide 14 text

First Scala Daysへの参加&登壇(2010) ● 初の大規模Scalaイベント ● 開催地:スイスのローザンヌ ○ Scala発祥の地 ● 参加者:150名超 ● 唯一の日本人参加者として、多数の実況ツイート

Slide 15

Slide 15 text

それ以後も色々 ● Scala日本語情報サイト開設(2011) ● 日本Scalaユーザーグループ(2012~) ● Scala Conference in Japan 2013の立ち上げ ○ ScalaMatsuriとして現在は継続(運営からは引退) ● Japan Scala Association(2013~) ○ ScalaMatsuriのために作った一般社団法人 ● Scala研修テキスト(2015~)

Slide 16

Slide 16 text

Scalaの特徴

Slide 17

Slide 17 text

特徴(1):Javaの資産をフル活用出来る ● Java言語の資産は膨大 ○ 20年以上の歴史 ● ScalaコードはJavaバイトコード(クラスファイル)にコンパイルされる ○ Javaのコード資産(ライブラリ)をほぼ全て利用可能

Slide 18

Slide 18 text

特徴(2):Javaと同じ速度 ● Javaと同じように書けば同じようにコンパイルされる ● 速度が要求される場面でも普通使える ○ Javaは諸言語の中でもかなり高速 ● ScalaフォロワーのKotlinも同じ利点あり

Slide 19

Slide 19 text

特徴(3):短いコードで多くのことを表現可能 ● 昔のJavaと比べるとコード量は1/4~½ ○ Java 17と比較しても半分くらいにはなる感覚 ● ラムダ、型クラス、ジェネリクス、などなど ● Python比でも典型的なプログラムは短くなる

Slide 20

Slide 20 text

Java VS. Scala (1) ~ データ保持用クラス Java Scala public class Person { private final String name; private final int age; public Person(String name, int age) { this.name = name; this.age = age; } public String getName() { return name; } public int getAge() { return age; } } case class Person(name: String, age: Int)

Slide 22

Slide 22 text

Java VS. Scala (3) ~ データ構造の走査 Java Scala // (1 - 2) + (3 * 4) の式のつもり var exp = Add( Sub(1, 2), Mul(3, 4) ); int eval(Exp node) { if(node instanceof Add x) { return eval(x.lhs()) + eval(x.rhs()); } else if(node instanceof Sub x) { return eval(x.lhs()) - eval(x.rhs()); } else if(node instanceof Mul x) { return eval(x.lhs()) * eval(x.rhs()); } else if(node instanceof Div x) { return eval(x.lhs()) / eval(x.rhs()); } else { return ((Num)node).value(); } } System.out.println(eval(exp)); // 6 // (1 - 2) + (3 * 4) の式のつもり val exp = Add( Sub(1, 2), Mul(3, 4) ) def eval(node: Exp): Int = exp match { case Add(x, y) => eval(x) + eval(y) case Sub(x, y) => eval(x) - eval(y) case Mul(x, y) => eval(x) * eval(y) case Div(x, y) => eval(x) / eval(y) case Num(v) => v } println(eval(exp)) // 6

Slide 23

Slide 23 text

Python VS. Scala (1) ~ データ保持用クラス Python Scala import dataclasses # From Python 3.7 @dataclasses.dataclass class Person: name: str age: int case class Person(name: String, age: Int)

Slide 24

Slide 24 text

Python VS. Scala (2) ~ 二分木の表現 Python Scala class BinTree: def __init(self, value): self.value = value class Node(BinTree): def __init__(self, value, lhs, rhs): super().__init(value) self.lhs = lhs self.rhs = rhs class Leaf(BinTree): def __init__(self, value): super().__init(value) sealed trait BinTree[A] { val value: A; } case class Node[A]( val value: A, lhs: BinTree[A], rhs: BinTree[A]) extends BinTree[A] case class Leaf(val value: A) extend BinTree[A]

Slide 25

Slide 25 text

Python VS. Scala (3) ~ データ構造の走査 Python Scala # Python < 3.10 # (1 - 2) + (3 * 4) のつもり exp = Add( Sub(1, 2), Mul(3, 4) ) def eval(node): if isinstance(node, Add): return eval(node.lhs) + eval(node.rhs) elif isinstance(node, Sub): return eval(node.lhs) - eval(node.rhs) elif isinstance(node, Mul): return eval(node.lhs) * eval(node.rhs) elif isinstance(node, Div): return eval(node.lhs) / eval(node.rhs) else: return node.value print(eval(exp)) # 6 // (1 - 2) + (3 * 4) の式のつもり val exp = Add( Sub(1, 2), Mul(3, 4) ) def eval(node: Exp): Int = exp match { case Add(x, y) => eval(x) + eval(y) case Sub(x, y) => eval(x) - eval(y) case Mul(x, y) => eval(x) * eval(y) case Div(x, y) => eval(x) / eval(y) case Num(v) => v } println(eval(exp)) // 6

Slide 26

Slide 26 text

特徴(4):関数型プログラミング(FP)のサポート ● 関数型プログラミング(FP)≒副作用をできるだけ使わないスタイル ○ 副作用:可変な状態(変数)や入出力など ● いわゆる関数型プログラミング言語 ○ Haskell, OCaml, Erlang, Elixir, Scala ● Scalaは関数型プログラミングを積極的にサポート ○ ケースクラス:不変なデータクラスの作成が容易 ○ 標準ライブラリのコレクションはデフォルトで不変 ○ 文化的に副作用を使わないことを奨励

Slide 27

Slide 27 text

手続き型プログラミングと関数型プログラミング ● 手続き型プログラミング(Imperative Programming) <-> 関数型プログラミン グ(Functional Programming) ● 手続き型:(入力データ、現在の状態)→ (出力データ、未来の状態) ○ 利点:現実に存在する可変な状態をそのままモデル化しやすい、比較的省メモリ ○ 欠点:デバッグやテストがより困難 ■ 入力データが同じでも出力が変わるため(可変状態や入出力を扱うため) ● 関数型:入力データを→出力データ ○ 利点:デバッグやテストが(比較的容易) ■ 入力が同じなら出力も同じ(状態の依存しない) ○ 欠点:リソースをより消費する ■ 状態に相当するものもデータとして表現するため ● 特にメモリを消費する傾向

Slide 28

Slide 28 text

手続き型と関数型 in Python 手続き型 関数型 def remove_if(list, condition): i = 0 while i < len(list): if condition(list[i]): del list[i] else: i += 1 xs = [1, 2, 3, 4, 5] remove_if(xs, lambda x: x % 2 == 0) print(xs) # [1, 3, 5] def removed_list_if(list, condition): return [x for x in list if not condition(x)] xs = [1, 2, 3, 4, 5] ys = removed_list_if(xs, lambda x: x % 2 == 0) print(xs) # [1, 2, 3, 4, 5] print(ys) # [1, 3, 5]

Slide 29

Slide 29 text

Python ● Scala Scala VS. Python in 関数型 @dataclass class Plant: name: string kind: string plants = [ Plant("ソメイヨシノ", "tree"), Plant("キャベツ", "grass"), Plant("リンゴ", "tree"), Plant("ネギ", "tree") ] names = [p.name for p in plants if p.kind == "tree"] //ソメイヨシノ, リンゴ print(", ".join(names)) case class Plant(name: String, kind: String) val plants = List( Plant("ソメイヨシノ", "tree"), Plant("キャベツ", "grass"), Plant("リンゴ", "tree"), Plant("ネギ", "tree") ) val names = plants.filter(_.kind == "tree).map(_.name) //ソメイヨシノ, リンゴ println(names.mkString(", "))

Slide 30

Slide 30 text

特徴(5):先端的な機能を搭載 ● 型クラス ○ Haskellなど一部の関数型プログラミング言語に存在する機能 ● 変位指定 ○ 静的型を持つ言語の中でも、一部の言語にのみ存在 ○ ジェネリックなデータを扱う上で重要 ● 高機能なマクロ(コンパイル時プログラミング) ○ C/C++のものでなく、Lisp系列の木構造操作型 ○ 強力過ぎるので要注意な機能でもある

Slide 31

Slide 31 text

型クラスを使ったコード例 // 複素数型を定義 case class Complex(real: Double, imagine: Double) implicit val numericComplex = new Numeric[Complex] { def plus(x: Complex, y: Complex): Complex = { Complex(x.real + y.real, x.imagine + y.imagine) } ... } val cs = List(Complex(1.0, 2.0), Complex(2.0, 3.0)) // 複素数の総和を求める方法が自動的に求められる println(cs.sum) // Complex(3.0, 5.0) val empty: List[Complex] = numericComplex // 空の複素数リストでもOK(PythonやRubyでは無理) println(empty.sum) // Complex(0.0, 0.0)

Slide 32

Slide 32 text

Scalaの課題

Slide 33

Slide 33 text

競合言語の台頭(Kotlin) ● 2012年、JetBrainsによって開発が開始された言語 ○ Scalaを強烈に意識した仕様(公式ページにも昔はScalaとの比較があった) ○ Scalaの欠点を改善(バイナリ互換性、小難しく見える機能の削除) ○ 充実したドキュメントやIDEのサポート ● Androidアプリ開発ではデファクトスタンダードの地位を確立 ○ JavaよりもKotlin使うのが普通という風潮も ● サーバーサイドでも少しずつ台頭 ○ 感覚的には既に同等くらい(?) ● Scala 3.0で良い方向に差別化できるか

Slide 34

Slide 34 text

競合言語の台頭(Go) ● 2009年、Google発の言語 ● 新しい言語の中では特異な設計思想と実装 ○ メジャーな機能でも意図的に削除 ■ ジェネリクス(最近やっぱり入った) ■ オブジェクト指向サポート ■ 例外処理 ○ GCあり言語の中では最速の部類、ランタイムも小さい ● 仕様が小さいので開発者を雇用しやすい ○ Scala -> Goな事例もたまに聞く ● Kotlinほどパイを奪い合うことはなさそう

Slide 35

Slide 35 text

Akka問題 ● Akka:Scalaを採用している企業がかなりの割合で使っているミドルウェア ○ Scala開発元のLightbend製 ● そんなAkkaが最近非オープンソース化 ○ 商用で大きな利益得てるところはライセンス料払ってねみたいな話 ● 背景: ○ LightbendとしてはAkkaのサポートビジネスやりたいのに、無償で使われまくってサポートの 要求も(予想外に)少なかった?改修部分は完全にLightbendの持ち出し ● AkkaをforkしたPekkoを作る動きも開始 ○ https://cwiki.apache.org/confluence/display/INCUBATOR/PekkoProposal ● OSS作者ただ働き問題 ○ だけなら良いのだけど、無償でサポートせよみたいな話が増えた ○ 関連:Log4j問題

Slide 36

Slide 36 text

まとめ

Slide 37

Slide 37 text

Scalaについて語ってみた ● 歴史と概要 ● 採用事例 ● 私とScalaの関わり ● Scalaの特徴 ● オブジェクト指向と関数型の比較 ● Scalaの課題

Slide 38

Slide 38 text

Any questions ?