Upgrade to Pro — share decks privately, control downloads, hide ads and more …

プログラミング言語Scalaの歴史と概要/NextbeatTechBar-20230421-3

 プログラミング言語Scalaの歴史と概要/NextbeatTechBar-20230421-3

2023年4月21日に開催された「Nextbeat Tech Bar:Scala今昔物語」にて発表した資料です。

nextbeat-engineer

April 24, 2023
Tweet

More Decks by nextbeat-engineer

Other Decks in Technology

Transcript

  1. 自己紹介 • 水島宏太(みずしまこうた) / @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普及活動などなどやってます
  2. Scalaって何? • Martin Odersky教授が開発したプログラミング言語 ◦ スイス連邦工科大学ローザンヌ校(EPFL)教授 ◦ 2003年生まれの比較的新しい言語 ◦ javac(1.5以降)やJava

    Genericsの開発者でもある • オブジェクト指向言語 ◦ Javaのオブジェクト指向がベース • 静的型付け ◦ Javaより強い(厳しい)チェックが可能 • JVM言語 ◦ Java仮想マシン(Java Virtual Machine)上で処理系が動作 • 2008年にTwitter社が採用して以降、産業界での利用が進む ◦ 最近はそのTwitterも色々……はおいておく
  3. 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リリース
  4. Scalaの採用事例 • 世界中で普通に使われている ◦ C/C++/Java/C#辺りと比べれば二段階くらいユーザ数は少ない • 海外 ◦ 一番のヘビーユーザ:Twitter ▪

    最近、API有料化で多少雲行きが怪しいけども ◦ LinkedIn, PayPal, Morgan Stanley, Coursera, eBay, Guardian, etc. • 日本 ◦ はてな、ドワンゴ、ChatWork、ビズリーチ、サイバーエージェント、ネクストビート他多数
  5. Scalaとの再会(2007) • 修士2年の時 ◦ Scala 2.5の頃 • 面白い言語機能がたくさん→夢中に ◦ Existential

    Type ◦ Implicit Conversion ◦ Structural Subtyping ◦ Abstract Type ◦ … • LL魂(2007)でLT発表 ◦ Power of Scala • 2008年以後、本格的にScalaに関わっていくことに
  6. それ以後も色々 • Scala日本語情報サイト開設(2011) • 日本Scalaユーザーグループ(2012~) • Scala Conference in Japan

    2013の立ち上げ ◦ ScalaMatsuriとして現在は継続(運営からは引退) • Japan Scala Association(2013~) ◦ ScalaMatsuriのために作った一般社団法人 • Scala研修テキスト(2015~)
  7. 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)
  8. Java VS. Scala (2) ~ 二分木の表現 Java Scala interface BinTree<A>

    { A getValue(); } class Node<A> implements BinTree<A> { private final A value; private final BinTree<A> lhs, rhs; public Node(A value, BinTree<A> lhs, BinTree<A> rhs) { this.value = value; this.lhs = lhs; this.rhs = rhs; } public A getValue() { return value; } public BinTree<A> getLhs() { return lhs; } public BinTree<A> getRhs() { return rhs; } } class Leaf<A> implements BinTree<A> { private final A value; public Leaf(A value) { this.value = value; } public A getValue() { return 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]
  9. 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
  10. 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)
  11. 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]
  12. 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
  13. 特徴(4):関数型プログラミング(FP)のサポート • 関数型プログラミング(FP)≒副作用をできるだけ使わないスタイル ◦ 副作用:可変な状態(変数)や入出力など • いわゆる関数型プログラミング言語 ◦ Haskell, OCaml,

    Erlang, Elixir, Scala • Scalaは関数型プログラミングを積極的にサポート ◦ ケースクラス:不変なデータクラスの作成が容易 ◦ 標準ライブラリのコレクションはデフォルトで不変 ◦ 文化的に副作用を使わないことを奨励
  14. 手続き型プログラミングと関数型プログラミング • 手続き型プログラミング(Imperative Programming) <-> 関数型プログラミン グ(Functional Programming) • 手続き型:(入力データ、現在の状態)→

    (出力データ、未来の状態) ◦ 利点:現実に存在する可変な状態をそのままモデル化しやすい、比較的省メモリ ◦ 欠点:デバッグやテストがより困難 ▪ 入力データが同じでも出力が変わるため(可変状態や入出力を扱うため) • 関数型:入力データを→出力データ ◦ 利点:デバッグやテストが(比較的容易) ▪ 入力が同じなら出力も同じ(状態の依存しない) ◦ 欠点:リソースをより消費する ▪ 状態に相当するものもデータとして表現するため • 特にメモリを消費する傾向
  15. 手続き型と関数型 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]
  16. 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(", "))
  17. 特徴(5):先端的な機能を搭載 • 型クラス ◦ Haskellなど一部の関数型プログラミング言語に存在する機能 • 変位指定 ◦ 静的型を持つ言語の中でも、一部の言語にのみ存在 ◦

    ジェネリックなデータを扱う上で重要 • 高機能なマクロ(コンパイル時プログラミング) ◦ C/C++のものでなく、Lisp系列の木構造操作型 ◦ 強力過ぎるので要注意な機能でもある
  18. 型クラスを使ったコード例 // 複素数型を定義 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)
  19. 競合言語の台頭(Kotlin) • 2012年、JetBrainsによって開発が開始された言語 ◦ Scalaを強烈に意識した仕様(公式ページにも昔はScalaとの比較があった) ◦ Scalaの欠点を改善(バイナリ互換性、小難しく見える機能の削除) ◦ 充実したドキュメントやIDEのサポート •

    Androidアプリ開発ではデファクトスタンダードの地位を確立 ◦ JavaよりもKotlin使うのが普通という風潮も • サーバーサイドでも少しずつ台頭 ◦ 感覚的には既に同等くらい(?) • Scala 3.0で良い方向に差別化できるか
  20. 競合言語の台頭(Go) • 2009年、Google発の言語 • 新しい言語の中では特異な設計思想と実装 ◦ メジャーな機能でも意図的に削除 ▪ ジェネリクス(最近やっぱり入った) ▪

    オブジェクト指向サポート ▪ 例外処理 ◦ GCあり言語の中では最速の部類、ランタイムも小さい • 仕様が小さいので開発者を雇用しやすい ◦ Scala -> Goな事例もたまに聞く • Kotlinほどパイを奪い合うことはなさそう
  21. Akka問題 • Akka:Scalaを採用している企業がかなりの割合で使っているミドルウェア ◦ Scala開発元のLightbend製 • そんなAkkaが最近非オープンソース化 ◦ 商用で大きな利益得てるところはライセンス料払ってねみたいな話 •

    背景: ◦ LightbendとしてはAkkaのサポートビジネスやりたいのに、無償で使われまくってサポートの 要求も(予想外に)少なかった?改修部分は完全にLightbendの持ち出し • AkkaをforkしたPekkoを作る動きも開始 ◦ https://cwiki.apache.org/confluence/display/INCUBATOR/PekkoProposal • OSS作者ただ働き問題 ◦ だけなら良いのだけど、無償でサポートせよみたいな話が増えた ◦ 関連:Log4j問題