...

新世代オブジェクト指向言語Scalaの魅力

by user

on
Category: Documents
6

views

Report

Comments

Transcript

新世代オブジェクト指向言語Scalaの魅力
新世代オブジェクト指向言語Scalaの魅力
Scala コミュニティ 水島 宏太
2011/12/01
0
自己紹介
※所属会社の業務とScalaに関係はありません
 氏名:水島宏太
 株式会社イーフロー所属の1エンジニア
 Scala関連の記事・書籍執筆・勉強会発表等
 余暇の時間で
 刺激を求める技術者に捧げるScala講座(第6回・第17回担当、第23回・24回(執筆中))
 日経BP ITProの連載コーナー
 http://itpro.nikkeibp.co.jp/article/COLUMN/20080613/308019/
 オライリージャパン 『プログラミングScala』 (レビュー)
 秀和システム 『Scala実践プログラミング―オープンソース徹底活用』(共著)
 インプレス・ジャパン 『Scalaスケーラブルプログラミング第2版』
 Scala 2.9解説記事執筆
 プログラミングの魔道書 vol.2. 『プログラミング言語Scalaの歴史とこれから 』 寄稿
 Scala Days 2010(スイス), Scala Days 2011(アメリカ) 参加・発表
 その他多数
 プログラミング言語・構文解析好き
 自作のプログラミング言語Onion等をgithubで公開
1
Scalaの概要
 Java VM上で動作するプログラミング言語
 Javaの資産はほぼ完全に利用可能
 Glue Code不要
 静的型を持ったオブジェクト指向言語
 クラス、オブジェクトと言ったJavaの概念はそのまま利用可能
 高速な処理系
 「Javaらしい」コードはJavaとほぼ同じ速度
 「Scalaらしい」コードも十分に高速
 型推論による冗長な記述の排除
 静的型による安全性はそのままに
 不変オブジェクトを中心とした安全で強力なコレクションライブラリ
 XMLリテラルの言語・標準ライブラリによるサポート
 簡潔なXML処理
 標準ライブラリでActorをサポート
 明示的なロック不要の並行処理記述ライブラリ
 標準ライブラリにパーザライブラリ同梱
 カスタムDSLや設定ファイルのパーザを尐ない工数で書ける
2
Scala年表
 2002: スイス連邦工科大学ローザンヌ校(EPFL)で開発開始
 主要開発者:Martin Odersky
 javac (Java 5以降)オリジナル開発者 && Java Generics提案者の一人





2003:
2005:
2006:
2007:
2008:
最初の公開版リリース
~Scala 1.X
Scala 2.0リリース~Scala 2.5リリース
Scala 2.6リリース
Scala 2.7リリース
 Java Genericsと互換に




2008:
2010:
2011:
2011:
TwitterによるScalaの採用(バックエンド処理の置き換え)
Scala 2.8リリース
Scala 2.9リリース
Typesafe社設立
 CEO: Martin Odersky, CTO: Jonas Bonér(Scala製ミドルウェアAkkaの開発者)
 Scalaの商用サポート、コンサルティング、IDEプラグイン開発等
 "Typesafe Stack"の提供
 2011: Typesafe社、Play 2.0 Frameworkの商用サポート発表
3
Scala採用事例(海外)
※
















公開されている事例のみ紹介
Twitter
LinkedIn
Foursquare
Amazon.com
VMWare
Novell
Xerox
NASA
Bank of America
UBS
Remember the Milk
Siemens
GridGain
OPOWER
The Guardian
その他多数
4
Scala採用事例(国内)
※ 公開されている事例のみ紹介
 株式会社パテントビューロ
 Webサービス開発などの主力言語としてScalaを採用
 知財判例データベース、astamuse(特許情報閲覧・検索サービス)等
 有限会社ITプランニング
 Scalaによるシステム構築事例
 GMOメディア株式会社
 リワード広告システム等
 株式会社ドワンゴ
 導入予定
 参考: ドワンゴ社内 scala勉強会(ニコニコ生放送)
 http://live.nicovideo.jp/watch/lv71111927
 等
5
国内のScalaコミュニティ・勉強会
 Scala勉強会 in 渋谷 (rpscala)
 渋谷・秋葉原などで毎週勉強会を開催
 Akasaka.scala
 赤坂を中心に勉強会を開催
 天領倉敷Scala
 岡山付近のScalaコミュニティ
 大阪Scala勉強会
 Scala勉強会@東北
 オンライン上の勉強会をほぼ毎週開催
 東日本大震災の影響で休止中
 名古屋Scala勉強会
 名古屋を中心に活動
 Scala@福岡
 福岡を中心に活動
6
Hello, Scala
object Hello {
def main(args: Array[String]): Unit = {
println("Hello, World!")
}
}
Hello, Worldプログラム (Scala)
class Hello {
public static void main(String[] args){
System.out.println("Hello, World!")
}
}
Hello, Worldプログラム (Java)
さようなら, null. こんにちは, Option[T].
 「null参照の概念は10億ドル単位の過ち 」 by アントニー・ホーア
 Option型によって、「nullを取り得る型」を区別
// 「失敗する」可能性が型から判別できる
val x: Option[String] = map.get("key")
// val y: String = x // コンパイルエラー
val y: String = x.getOrElse("default")
Optionを使ったプログラム断片 (Scala)
// nullを取りうるか型から判別できない
String x = map.get("key");
// String y = x; // コンパイルできる
String y = x == null ? x : "default";
nullを使ったプログラム片 (Java)
お手軽型推論
 自明な型をコンパイラが推論(型推論)
 自明でない型(メソッドの引数等)は書く
val map = new HashMap[String, List[String]]()
// 型を書いても良い
val map: Map[String, List[String]] = ...
Map型の変数宣言(Scala)
// 自明な型でも書かなければいけない
Map<String, List<String>> map =
new HashMap<String, List<String>>();
Map型の変数宣言 (Java)
無名クラスのシンタックスシュガー
 いわゆる「関数リテラル」と呼ばれているもの
 実体は単なる無名クラスのシンタックスシュガー
 Java 8のラムダ式(予定)と異なり、変更可能な外部変数も参照可能
 関数型プログラミングを知らなくても使える
val multiply = (x: Int, y: Int) => x * y
println(multiply(5, 10))
val multiply = new Function2[Int, Int] {
def apply(x: Int, y: Int): Int = x * y
}
println(multiply.apply(5, 10))
ケースクラス(case classes)
 よくある「値オブジェクト」のクラス定義を簡潔に記述できる
case class Person(name: String, age: Int)
// ...
val person = Person("hoge", 18)
値オブジェクトのクラス定義と生成(Scala)
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 String getAge() {
return age;
}
}
//...
new Person("hoge", 18)
値オブジェクトのクラス定義と生成(Java)
Loanパターン (VS. Java 7 ARM(Automatic Resource Management)) (1)
 Loanパターン: リソースの自動closeを「ライブラリとして」提供
 Java 7 ARM: リソースの自動closeを「構文として」提供
 dispose()等でリソース破棄するライブラリには使えない
// 一度「ライブラリとして」定義すれば
def using[T <: Closeable](resource: T)(block: T => Unit): Unit = try {
block(resource)
} finally { resource.close() }
// 組み込みの構文のように使える
using(new FileInputStream("input.txt")){in =>
for(b <- Stream.continually(in.read()).takeWhile(_ != -1))
Console.out.write(b ^ 0xFF)
}
Loanパターン(Scala)
try (
FileInputStream in = new FileInputStream("input.txt");
){
int b;
for (int b; (b = in.read()) != -1 ) {
System.out.write(b ^ 0xFF);
}
}
ARM(Java 7)
Loanパターン (VS. Java 7 ARM(Automatic Resource Management)) (2)
 SWTでの比較: dispose()でリソースを解放
case class Wrapper[T <: { def dispose() }](core: T) extends
Closeable{
def close() : Unit = core.dispose()
}
def wrap[T](core: T): Wrapper[T] = Wrapper(core)
val display = new Display()
using(wrap(new Shell(display))){ case Wrapper(shell) =>
/* ... */
shell.open()
while (!shell.isDisposed())
if (!display.readAndDispatch()) display.sleep()
}
SWT + Loanパターン(Scala)
Display display = new Display();
Shell shell = new Shell(display);
/* ... */
try {
shell.open();
while (!shell.isDisposed())
if (!display.readAndDispatch()) display.sleep();
} finally {
shell.dispose(); // dispose()なので、ARM構文が使えない
}
SWT (Java 7)
強力なコレクションライブラリ (1) 簡潔な記述
 より重要なロジックに集中できる
val persons = List[Person](...)
// 年齢が18歳以上の人の名前のリストを抽出
val namesAged18 = persons.collect{ case p
if p.age >= 18 => p.name }
//カンマで区切って出力
print(namesAged18.mkString(", "))
フィルタリング処理(Scala)
List<Person> persons = new ArrayList<Person>();
/* ... */
List<String> namesAged18 = new ArrayList<String>();
for (Person p: persons) {
if (p.getAge() >= 18) namesAged18.add(p.getName());
}
if (namesAged18.size() > 0) {
System.out.print(namesAged18.get(0));
namesAged18 = namesAged18.subList(1, namesAged18.size());
}
for(String name: namesAged18) System.out.print(", " + name);
フィルタリング処理 (Java)
強力なコレクションライブラリ (2) 不変と可変
 「不変」コレクションと「可変」コレクションを別の型として管理
 可読性の向上 + コレクションの取り扱いミスを防御
 「型はドキュメント」の思想をJavaより進めている
// Listは不変なので安全に引数として渡せる
def concatWithLn1(names: List[String]): String = ...
// ArrayBufferは可変なので、中で変更され得る事がわかる
def concatWithLn2(names: ArrayBuffer[String]): String = ...
リストの文字列を連結するメソッドのシグニチャ(Scala)
// Listは可変
// (a) 防御的なコピー
// (b) Collections.unmodifiableList()
// 引数にそのまま渡すのは危険
String concatWithLn1 (List<String> namesIn) { ... }
// 「そのまま」渡す必要がある
String concatWithLn2 (List<String> names) { ... }
リストの文字列を連結するメソッド
のシグニチャ(Java)
サンプルプログラム:XML処理
 Twitterのpublicタイムラインのユーザから
 スクリーン名
 フォロワー数
を取得して、フォロワー数(降順)でソートして表示
val timeline = XML.load(
new URL("http://api.twitter.com/1/statuses/public_timeline.xml")
)
val info = for(user <- timeline ¥¥ "user";
name <- user ¥¥ "screen_name"; follower <- user ¥¥ "followers_count"
) yield (name.text, follower.text)
val sorted = info.sortBy{ case (name, followers) => - followers.toInt }
for ((name, count) <- sorted) {
printf("Name: %s%n", name)
printf("Followers: %s%n", count)
}
Twitterのpublicタイムライン取得プログラム
サンプルプログラム:XML処理(実行結果)
 $ "scala Timeline.scala" で実行可能
 コンパイルと実行が同時に行われる
Name: PreferKobayashi
Followers: 1953
Name: PapaDock_TFF
Followers: 1380
Name: dida34
Followers: 1359
Name: DeLaAsia
Followers: 699
Name: olivacarden
Followers: 444
Name: ReflectSound
Followers: 171
Name: _KEYBUMMIE
Followers: 167
Name: ElPadrino_2595
Followers: 145
Name: bubych
Followers: 144
Name: ranrats
Followers: 140
Name: MaryKateMolina
Followers: 138
Name: jpii777
Followers: 96
Name: dee_jo_freshh
Followers: 94
Name: nova_luna
Followers: 87
Name: dedLavanza
Followers: 75
Name: RichieMinaj88
Followers: 27
Name: hazelsnutz
Followers: 25
Name: cogancool
Followers: 7
Name: bellgos6
Followers: 3
Name: telurodebiz
Followers: 0
基本ツール(標準添付)
 scalacコマンド
 javacに相当(クラスファイルへのコンパイラ)
 オプションもjavacと類似した部分が多い(-classpath等)
 fscコマンド
 scalaコンパイラをサーバとして常駐させて、コンパイルを高速化するコマンド
 それ以外はscalacと同じ
 scalaコマンド
 1.scalacで生成されたクラスファイルを簡単に実行
 2.scalaスクリプト(テキスト)をそのままコンパイル・実行
 3.対話環境(REPL)
 Scala/Java APIの動作を調べたい時に便利
 scaladocコマンド
 javadocコマンド相当
 sbazコマンド
 scalaアプリケーション/ライブラリ用のパッケージマネージャ
18
準標準ライブラリ/フレームワーク
 sbt
 Scalaのデファクトスタンダードなビルドツール
 ビルド設定ファイルをScala DSLとして記述
 Apache Ivyベース
 Mavenリポジトリをそのまま利用できる
 Mavenと同じディレクトリ構成を採用
 簡単な記述で、Scalaの各種ライブラリに対する依存関係を記述可能
 ScalaTest/Specs
 Scalaにおける2大ユニットテスティングライブラリ
 ScalaTestの方が保守的、Specsは新機能を積極的に取り込む傾向
 ScalaCheck
 (半)自動テスティングライブラリ
 テスト対象の型からテストケースを自動生成
 ScalaTest/Specsを補完
19
sbtのビルド設定ファイル例
 単純なプロジェクトなら、これだけでOK
 No more XML hell
 必要であれば、Scalaのプログラムを設定ファイルに書ける
// プロジェクト名
name := "Simple Project"
// バージョン
version := "1.0"
// 組織
organization := "hoge"
// ビルドに使うScalaのバージョン
scalaVersion := "2.9.1"
// ライブラリの依存性記述
libraryDependencies ++= Seq(
"org.specs2" %% "specs2" % "1.6.1",
"org.specs2" %% "specs2-scalaz-core" % "6.0.1" % "test"
)
Build.sbt
主要Webアプリケーションフレームワーク/ツールキット

Lift





Play!




Twitter製
Scala用RPCライブラリ
JBoss Nettyベース
Casbah



httpサービスを提供するためのライブラリ/ツールキット(≠Webアプリケーションフレームワーク)
no view
簡潔な記述で、URLに対応するサービスをつなげられる
Remember the Milk等で採用
Finagle




RubyのSinatraフレームワークに影響を受けたフレームワーク
小規模Webアプリケーションの開発に適している
フレームワークの仕組みを理解するのが簡単
Unfiltered





Java/Scala用Webアプリケーションフレームワーク
Ruby on Rails(RoR)ライクな開発サイクル
2.0からコードベースをScalaに移行(Java用 APIは引き続き提供)
Scalatra




Scala用Webアプリケーションフレームワーク
XMLリテラルなどScalaの機能を活用
企業における採用実績一定以上あり (Foursquareなど)
Ajax/Cometアプリケーション開発のための便利なAPI
MongoDBのScala用API
MongoDB開発元の10gen謹製
その他多数
21
主要IDEプラグイン
 IntelliJ IDEA Scalaプラグイン




IDE開発が公式に提供しているプラグイン
最も高機能・安定性が高い
Java -> Scala変換のような、マイグレーションのための機能
自動リファクタリング
 Java/Scala混在プロジェクトもうまく扱える
 コード補完
 Scala IDE for Eclipse




Typesafe社に管理が移行
急速に品質が改善
自動リファクタリング(名前変更・メソッド抽出など、現時点では限定的)
コード補完
 NetBeans Scalaプラグイン
 個人での開発
 コード補完など、基本機能は揃っている
 インストールするのがやや面倒
22
Scalaの採用メリット
 簡潔なコード
 実用的にはJavaの1/3~1/4程度のコード量
 冗長なJavaコードを「書く」のはIDEがサポート
 冗長なJavaコードを「読む」のは労力が必要
 より安全なコード
 不変オブジェクトを作りやすい言語設計
 Javaでライブラリ化(できない/現実的でない)部分をライブラリ化可能
 Don't Repeat Yourself(DRY)原則
 リソースの自動クローズ(Loanパターン)
 Java 7では「言語仕様の拡張」が必要だった
 Scalaでは、単なるライブラリとして提供できる
 一般化: 前処理 -> 本処理 -> 必ず実行される後処理 をライブラリ化可能
 ロック不要の並行処理記述ライブラリ(Actor)
 マルチスレッドプログラムのバグ削減に有効
 コレクションライブラリ
 Java:
 標準では「可変」コレクションのみ提供(「読み込み専用」に変換するメソッドはある)
 型から「可変」、「読み込み専用」、「不変」のどれを意図しているかがわからない
 Scala:
 標準で、不変コレクション/可変コレクションの両方を提供
 型から「可変」、「読み込み専用」、「不変」コレクションのどれかが判別できる
 不変コレクションは安全に複数スレッド間で共有可能
 領域特化言語(DSL)を簡単に作成できる
 Actor、パーザライブラリなど
23
Scalaの採用リスク
 学習のための良いドキュメント(日本語)不足
 「読んですぐScalaを使える」 ドキュメント(チートシート)があまり無い
 所謂「コップ本」は速習には向いていない
 国内におけるScala開発者の尐なさ
 新しい言語には付き物の問題
 誮がコードをメンテナンスする?
 商用サポート
 Typesafe社による公式商用サポートは英語前提
 日本語の商用サポートは未定
 Scalaライブラリにバグがあった場合どうするか
24
リスク回避策(1): Better Javaから始める
 言語仕様はJavaよりも複雑
 「言語の全てを把握していないと使えない」なら学習コストは高い
 言語仕様の複雑さ≠言語の学習コスト(難しさ)
 Perl, Ruby, PHP等の言語も言語仕様から言えば複雑
 全てを最初から覚える必要は無い
 「Better Java」から始める
 構文を除いて、Javaとの高い互換性を持っている
 「JavaプログラムのようなScalaプログラム」はすぐ作れる
 要: Java構文 -> Scala構文 のチートシート
 Java -> Scala自動変換器(IntelliJ IDEA Scalaプラグイン)が存在
 型推論・ライブラリの恩恵はすぐに受けられる
 「Scalaらしいプログラム」への緩やかな移行が可能
25
リスク回避策(2): 部分的に使い始める
 JavaソースとScalaソースが混在したプロジェクトをビルド可能
 尐しずつScalaを導入できる
 ユニットテスト用DSL(領域特化言語)としてScalaを導入
 ScalaTest/Specs
 カスタムDSL実装用言語としてScalaを導入
 パーザライブラリ等
 scalaコマンド(対話環境)の活用
 Java APIの挙動をすぐに確かめるのに便利
 Scalaの習得のためにも使える
 実行結果がすぐ返ってくる
26
Scalaに関するFAQ(1) – 関数型プログラミング
 Scalaは関数型プログラミングを覚えないと使えない?  NO
 関数型プログラミングを知っていた方が「より良い」
 知らなくても、「新しい静的型付けオブジェクト指向言語」として使える






case classによる簡潔なValue Objectの定義
無名クラスのシンタックスシュガー
ジェネリックス
強力なコレクションライブラリ
型推論
Option型
 オブジェクト指向と関数型のハイブリッド?
 アカデミックで難しそう
 実用的ではない
 色々な機能をごちゃまぜ?
 学習コストが高い
 IDEサポートが貧弱?
 IDEが無いとちょっと…
27
Scalaに関するFAQ(2) – 複雑さと学習曲線
 Scalaは複雑なので、習得が難しい?  NO
 言語仕様の複雑さ ≠ 習得難易度
 いわゆるLL(Perl, Ruby, PHP)も言語仕様は「複雑」
 言語仕様の全てを知らなくてもプログラムは書ける
 ただし
 汎用Scalaライブラリを開発するなら、ある程度の仕様理解は必要
 「汎用ライブラリ設計者」にとっては習得が難しい
 かもしれない
 「ライブラリユーザ」にとっては習得はそれほど難しくない
 いかにして両者を切り分けるかが誯題
28
Scalaに関するFAQ(3) – 設計思想
 Scalaはオブジェクト指向と関数型のハイブリッド?  No
 Javaの仕様をリファクタリングして、型推論やDSL、関数型プログラミング
サポート等を統合した静的型付けオブジェクト指向言語
 (Java – staticメンバ – プリミティブ型 - …) + 型システムの拡張 + 型
安全なコレクションライブラリ + ... = Scala
 追加した部分だけではなく、削った部分がある
 Scalaはごった煮言語?  No, but ...
 Scalaの設計哲学は「統合」
 比較的尐ない概念でより様々な事を表現できるように進化
 1つの概念で様々な面を表現可能
 概念の数が多いと誤解しがち
 Scalaは「実用」言語
 コミュニティの成長によって、「統合」哲学にそぐわない機能の要望も
 結果として、ad hocに見える仕様が追加/維持される事がある
29
Scalaに関するFAQ – IDEサポート
 IDEサポートが貧弱で使い物にならない?  No, but ...
 主要IDEに関しては「使える」レベルに達している
 Eclipse Scalaプラグイン
 IntelliJ IDEA Scalaプラグイン
 NetBeans Scalaプラグイン
 IntelliJ IDEA + Scalaプラグインが最も高機能・安定性が高い
 しかし
 各種IDEのJavaサポートの完成度にはまだ及ばない
 自動リファクタリング、補完、コード生成などの面
 IDEのサポートをどこまで期待するか
30
デモ
 Eclipse + Scala IDE for Eclipse
 NetBeans + Scalaプラグイン
 IntelliJ IDEA + Scalaプラグイン
31
Fly UP