73
Scala勉強会

Scala Study Session

Embed Size (px)

Citation preview

Page 1: Scala Study Session

Scala勉強会

Page 2: Scala Study Session

Scalaとのであい

あの忌まわしい「Haskell勉強会」から1年

あのとき感じた関数型言語に対する

激しい敗北感

そんなとき耳にした、少しだけフレンドリー

そうな関数型言語

Page 3: Scala Study Session

Scalaとのであい

え、なんかJavaと似てるらしい?

モナド?圏論?そんなの関係ねえ?

悪Javaみたいに書けばおk?

これは…

Page 4: Scala Study Session

Scalaとのであい

、、、,.

,._

>>Scalaくん……

Scalaくん………

ィ`‘′

〃/ノノ八レレ、.

|

Scalaくんに託すっ…!

ル三’‘′`三ヽ. |

[ ≧|ニ|≦_]~|^)ト、

虫のいい話なんだが……

.

| ,-L__」

-、u |ト:|

|’‘‐-

...__

_..

-┬|l王l王l王l`/ .|

| |

Haskellの代わりに…

.

|├‐┬─‐’‘′/

||

ぼくをきたえあげて……

/

l

|.l-―|、___/-―┤

| ̄ ̄|.| | | ヽ. /

| |

関数型をわからせてやってくれ…

/.|

| l. | |

Y。

| |

\/~三三..l

| ̄ ̄ ̄ ̄ ̄

 ̄|

たのむ……

/、

丁` /ヽ「|

/.|

|

.

/

へ、./

| l. /⊿

|_

|

/

|/

| |. └‐::┐r‐┘

.|

. ! /

|_|.

└'

|==

Page 5: Scala Study Session

もくじ

Scalaの概要

JavaからScalaへ

Real World Scala

Page 6: Scala Study Session

Scalaの概要

Page 7: Scala Study Session

Scalaの作者

Martin Oderskyもともと、Javaバイトコードに変換される関数型言語を開発

javacやJava-Genericsに取り込まれる

制限なしで一からミニマムな言語を作ってみた

使う人にとってはあまり嬉しくないことがわかった

Scalaの開発を開始

目標は変わらずOOとFunctionalの統合

開発者が使いやすいように

Page 8: Scala Study Session

Scalaのコンセプト

オブジェクトパラダイムと関数パラダイムを統合したマルチパラダイム言語

関数パラダイム

不変な値

関数中心

合流性

参照透明性

再帰

オブジェクトパラダイム

可変な値

オブジェクト中心

多態性

継承

統合(?)

Page 9: Scala Study Session

Scalaの実装

Javaバイトコードを生成するScalaコンパイラ+Scala標準ライブラリ(JAR)群

Scalaソースコード

Javaバイトコード

scala-library.jar

Scalaコンパイラ

Page 10: Scala Study Session

Scalaの実装

ゆえに(?)Java Scalaの相互呼び出しが可能

object ScalaToJavaCallSample extends Application {def method = println("Hello, Scala!")new JavaToScalaCallSample().method()

}

public class JavaToScalaCallSample {public void method() {System.out.println("Hello, Java!");

}public static void main (String[] args) {

ScalaToJavaCallSample.method();}

}

Page 11: Scala Study Session

Scalaの実装

Java -> Scala呼び出しの場合には、ある程度コンパイラの挙動を把握しておく必要あり

変数

すべてメソッドに

クロージャFunctionクラスに

などなど

Page 12: Scala Study Session

動作プラットフォーム

Java VM.NET Frameworkそして、、、

Android

Page 13: Scala Study Session

Scalaの捉え方

1. OO言語としてのScala2. 関数型言語としてのScala3. 並列処理基盤としてのScala

Page 14: Scala Study Session

OO言語としてのScala

というか、Better JavaとしてのScala“すべてがオブジェクト”

記法の簡略化

“Singleton”の言語レベルサポート

Mix-Inの導入

型推論の広範な導入

暗黙的な引数/型の補完・変換

擬似ダックタイピング

ネストされたメソッドの導入

Page 15: Scala Study Session

関数型言語としてのScala

高階関数

ラムダ式

クロージャ

Yコンビネータ

カリー化

遅延評価

不変オブジェクトだらけの標準ライブラリ

パターンマッチ、Caseクラス

Page 16: Scala Study Session

並列処理実行基盤としてのScala

Future並列計算

セマフォ

Reader/Writer同期/非同期チャネル

WorkersMailboxesActors

Page 17: Scala Study Session

JavaからScalaへ

Page 18: Scala Study Session

すべてがオブジェクト

プリミティブ型消滅、Scala独自のクラス群に

scala.Int, scala.Long, …内部的にはプリミティブ+俺Boxingで処理

関数/メソッドもオブジェクトに(後述)

Function0~クラス

演算子はすべてメソッドに

メソッドも演算子のように使える

Page 19: Scala Study Session

記法の簡略化

例:クラス定義(Java)

public class Foo {private String name;public Foo(String name) {

this.name = name}public void setName(String name) {

this.name = name}public String name() {

return name}

}

Page 20: Scala Study Session

記法の簡略化

例:クラス定義(Scala)

class Foo (var name: String)

Page 21: Scala Study Session

objectの導入

要するに「Singletonなclass」staticの代替と考えてもおk

コンパイル後には実際、static+Singletonクラスに

classとは異なる名前空間を持つ

Scalaライブラリの中で、classと同名のFactoryとしてリテラルの拡張のような形で使われている

object HelloWorld extends Application {println(“Hello, World!”)

}

val list : List = List(1, 2, 3, 4, 5)

Page 22: Scala Study Session

Mix-In

特定のプログラム要素(trait)をclassに付加可能

traitは実装を持つインタフェースのように振舞う

Javaのインタフェースは存在しない

class A extends B with Ctrait B

trait C

自分のイメージはなんかこんなかんじ

Page 23: Scala Study Session

Mix-in

Traitの例

trait HelloTrait {val msg = "Hello, World!"def say {println(msg)

}}class SimpleClass extends HelloTraitnew SimpleClass().say

Page 24: Scala Study Session

Mix-Inの正体

コンパイラは、このようなバイトコードを生成

class A extends B { trait B {

class A implements B { interface B {

abstract class B$class {

def method {…

public void method();

public void method {B$class.method();

}public static void method {

println(“hello, world!”);}

実装

委譲

Page 25: Scala Study Session

型推論

型を明記しなくてもコンパイラが推測、補完

一番簡単な例

推測できない場合や、矛盾が見つかった場合にはエラー吐いてくれる

val obj: SampleClass = new SampleClass

val obj = new SampleClass

Page 26: Scala Study Session

型推論

もうちょい凝った例:

dupはこのような形で呼び出し可能

自分は、どこでなら型推論が働くのか、あまり把握できてません。コンパイラの奴隷です。

def dup[T](x: T, n: Int): List[T] =if (n == 0) Nil else x :: dup(x, n - 1)

dup(“three”, 3)推測

Page 27: Scala Study Session

implicit

暗黙的にメソッド引数を補完

引数が足りなくても、implicit宣言した値を探し出してきて勝手に補完してくれる

def method[A](x: List[A])(implicit y: Param[A]) {println(x); println(y)

}abstract class Param[A]implicit object IntParam extends Param[Int]implicit object StringParam extends Param[String]

method(List(1,2,3)) <= IntParamを補完method(List(“a”, “b”, “c”)) <= StringParamを補完

Page 28: Scala Study Session

implicit

暗黙的に型変換(というより、型をラップ)

C#の拡張メソッドのようなことができる

class Factorizer(x: Int) {def fact(n: Int): BigInt =

if (n == 0) 1 else fact(n-1) * ndef ! = fact(x)

}implicit def int2fact(n: Int) = new Factorizer(n)println(10!)

Page 29: Scala Study Session

擬似ダックタイピング

Structured Typesという機能で可能に

「def close : Unit」をメンバに持つオブジェクトであればなんでもOKもちろんここでも(r: R)から型推論される

def method[R <: {def close : Unit}](r: R) = { …

Page 30: Scala Study Session

ネストしたメソッド

メソッド内にメソッドを定義可能

定義されたメソッドは、外側のメソッドのローカル変数を参照できる

カリー化や、その他高階関数で使ったりする

def outer {val innervalue = “hello.”def inner() = {println(innervalue)

}inner()

}

Page 31: Scala Study Session

高階関数・匿名関数

関数を返す関数や、関数を引数に取る関数

クロージャ、カリー化の基盤になる

無名関数も作ることが出来る

例:有名なやつ

xs map (x => x * x)

abstract class List[A] { ...def map[B](f: A => B): List[B] = this match {case Nil => thiscase x :: xs => f(x) :: xs.map(f)

}

Page 32: Scala Study Session

カリー化

関数の引数を部分的に渡すことで、引数が部分的に適用された関数を作ることができる

関数内でバリエーションを扱える

関数をカリー化可能な形式にする必要あり

def func(x: Int, y: Int, z: Int): Int = {x + y + z}

def func(x: Int)(y: Int)(z: Int): Int = {x + y + z}

Function.carried(func _)(func _).carry

Page 33: Scala Study Session

カリー化

簡単な例:

val newfunc = func(1)(2)newfunc(3) // => 6Newfunc(5) // => 8

Page 34: Scala Study Session

遅延評価

Scalaでは、引数の評価タイミングを選ぶことが出来る

Call by Value(Javaとか)

def func(x: Int) =…

Call by Name(Haskellとか)

def func(x: => Int) =…呼び出される側には、未評価のブロックが渡ってくる

関数渡しdef func(x: () => Int) = …関数がわたってくる

実質的にはCall by Nameと同じ

Page 35: Scala Study Session

遅延評価

変数初期化式の評価タイミングも選べる

lazy val = DB.hogeTable.selectAllvalが 初に評価されるまで、SELECTは行われない

フィボナッチ数列の無限リスト

lazy val fib: Stream[Int] =Stream.cons(0, Stream.cons(1,fib.zip(fib.tail).map(p => p._1 + p._2)))

Page 36: Scala Study Session

モナド

List、Stream、Map、Optionなどはモナドとして構成されている

For-ComprehensionはList内包表記ではなくモナド操作用構文

For-Comprehensionが正常に動作するためには

map[B] (f: A => B) : M[B]flatMap[B] (f: A => M[B]) :M[B]unit[A] : M[A]

これらが存在し、モナド則(Monadic Law)を満たす必要がある

Page 37: Scala Study Session

Real World Scala

Page 38: Scala Study Session

AOP

traitを使うことでそれっぽいことが実現可能

インスタンス単位でtraitを付加できることを利用する

内部的には、traitを付加したインスタンスごとに個別にクラスを生成している

DIと組み合わせれば効果的なのはJavaと同じ

実行時に織り込むタイプのAOPフレームワークも使える

val enhanced = new Target with AroundAdvice

Page 39: Scala Study Session

DI

Mix-InとSelf-Type Annotationでそれっぽいものが実現可能

Self-Type Annotationとは、Mix-inされ、インスタンス化される際の型を指定できる機能

既存のDIコンテナも使えるけど、相性もあるScalaだとフィールド定義できないとか

setter/getterがスタイルにあわないとか

trait SomeTrait {this: SomeClass =>…

Page 40: Scala Study Session

ライブラリ

Scala-Library不変コレクション

Actorパーサコンビネータ

Page 41: Scala Study Session

Actorモデル

動作モデル

scala.actorsパッケージでこのモデルをサポート

Actor

Actor

create

Actor

send async messages

send async messages

address

address

addressM

M

M

M

なんかこんなかんじ詳しく知りたければWikipediaにリンクされてる論文読んで

共有領域は持たない必要な情報はメッセージで

Page 42: Scala Study Session

scala.actors

scala.actors.Actor

M

mailboxMM

Actorオブジェクト

act

処理M

send

Page 43: Scala Study Session

Actorフレームワーク

ThreadとActorの関係

Actorオブジェクトに割り当てられる「わけではない」

メッセージ駆動の処理に「都度」割り当てられる

M

mailboxMM

Actorオブジェクト

act処理M

send

Page 44: Scala Study Session

Actorフレームワーク

Threadの割り当てはSchedulerが行う

M

mailboxMM

Actorオブジェクト

act処理M

Scheduler

send

Page 45: Scala Study Session

Actorフレームワーク

スレッド依存版(receive/wait)Thread

mailbox メッセージ取得

M

メッセージなし

ブロック!

Page 46: Scala Study Session

Actorフレームワーク

スレッド非依存版(react)Thread

mailbox 1. メッセージ取得

M

メッセージなし

2. 処理保存

3. 例外スローにより終了

処理

Page 47: Scala Study Session

Actorフレームワーク

スレッド非非依存版(react)Thread

mailbox

4. メッセージ取得M

Thread

send

3. 再開

処理2. 処理取得5. 処理実行

1. 送信

Page 48: Scala Study Session

【恒例】デモ「悟空vsフリーザ」【行事】

悟空とフリーザを戦わせてみた

VSKorea Japan

Page 49: Scala Study Session

パーサコンビネータ

Scala標準の構文解析ライブラリ群

字句解析してくれるあたり

expr ::= term {'+' term | '-' term}term ::= factor {'*' factor | '/' factor}factor ::= floatingPointNumber | '(' expr ')'

object ArithParser extends JavaTokenParsers {def expr: Parser[Any] = term ~ rep("+"~term | "-"~term)def term : Parser[Any] = factor ~ rep("*"~factor | "/"~factor)def factor : Parser[Any] = floatingPointNumber | "("~expr~")“def parse(text : String) = { parseAll(expr, text) }

}

Page 50: Scala Study Session

ライブラリ

Scala-DbcScalaでSQLライクに書けるモノらしい

ドキュメント皆無 Webにも情報皆無

評判悪

Page 51: Scala Study Session

ライブラリ

Scala-SwingScala標準ライブラリの1つ

デフォルトのアプリケーションモデルを提供基本的な画面構造をあらかじめ定義

(Simple)GUIApplication

イベントモデルの修正Event Publisher/Subscriberイベントハンドラが色んなコンポーネントを知らなくて良い

Swingを利用したプレゼンテーション用言語内DSLとも見ることができる

リテラルライクな画面構築

ちょっとだけ宣言的に書いている気になれる

Page 52: Scala Study Session

ライブラリ

Scala-Swingobject SwingApp extends SimpleGUIApplication {

def top = new MainFrame {title = “SwingApp”; var numclicks = 0object label extends Label {

text = “Number:” + "0 "listenTo(button)reactions += {case ButtonClicked(button) =>numclicks = numclicks + 1text = “Number:” + numclicks

}}object button extends Button { text = "I am a button" }contents = new FlowPanel { contents.append(button, label) }

}} Scala勉強会@札幌より引用

Page 53: Scala Study Session

フレームワーク

LiftServletで動作するフルスタックWebフレームワーク

Railsライクな開発スタイルMaven2のプラグインで実現

内部はRailsと同じく黒魔法、実際の学習コストは高め

非同期系のサポートAjaxサポート、jQuery同梱

ActorによるCometのサポート

共通機能SiteMapやACLの組み込み

設定はコードで

Page 54: Scala Study Session

フレームワーク

LiftView

XMLリテラルによるViewの記述

ControllerではなくView中心、ViewHelperの組み合わせみたいな感じ

ORMARみたいな標準ORMあり

Djangoとかいうのに似た機能もあるらしい

Page 55: Scala Study Session

フレームワーク

Liftのアーキテクチャ

LiftFilter

LiftServlet

Boot

LiftRules

http://liftweb.net/index.php/How_lift_processes_HTTP_requests

登録

early

フック

URLリライト

RequestState

呼び出し

生成

Snippet Model

TemplateXHTMLS

Model

dispatch

Snippet

REST

Comet

Ajax

LiftSession

Page 56: Scala Study Session

フレームワーク

Form仕様は意味不明

Menu画面 1-1./form.html

Lift

form.html

1-2.refer

input text

submit

show Snippet

Form画面

Lift2-1.submit

Handler

1-4.register

2-2.execute2-4.instanciate

show Snippet

2-3.値取得

1-3.instanciate

Page 57: Scala Study Session

フレームワーク

Liftざっとさわってみて

レイヤの感覚は希薄、model.toFormがHTMLタグ返す

APIが直感的ではないAjax、CometはまぁOKFormが使いづらすぎる

ドキュメントなさすぎ、古すぎ

新のScalaに対応してない(2008.11.21現在)

Page 58: Scala Study Session

フレームワーク

Web Flavorぶっちゃけて言えば、Scala版JSPServlet/JSPコンテナ上のScala(Java)アプリとしてJSPコンテナを実装しているようなイメージ

XMLリテラルでPHP的なテンプレートエンジンを構成

リクエスト発生時にScalaソースコードをコンパイルして実行、表示

Page 59: Scala Study Session

フレームワーク

Web FlavorPOHPでHTMLテンプレート的な構成も可能に

<span flavor:id=“xxx”>

事前に全コンパイルし、通常のJavaWebアーカイブとしても配布可能に

手軽にWebアプリを作るには結構便利

XMLリテラル以外にScalaっぽい要素は少ない

Page 60: Scala Study Session

補:SAStruts

出来心で使ってみた。

CoC的なFWはラップしないと使いづらい

Scalaコンパイラが生成するバイトコードのスタイルはScalaプログラムが直接コントロールできないため

フレームワークにあわせようとするとScala的なプログラミングスタイルから逸脱する

Scalaプログラミングスタイルにあわせるとフレームワークが動かない

Page 61: Scala Study Session

Scalaのよさそうなところ

簡略記法による軽量な開発

副作用排除による品質の向上

わりと速い(Javaとあまりかわらない)

Javaとの相互運用性は高い

Scala=>Javaはほぼ問題なし

Java=>Scalaは注意が必要

Better Javaとして使うには十分なレベル

Actorその他で並列処理が得意

並列処理のAP基盤開発には良さげ

Page 62: Scala Study Session

Scalaのよさそうなところ

DSLが作りやすそう

言語機能との区別がつきづらいような記述が可能

リテラルもどき

制御構文もどき

Caseクラス

パーサコンビネータ

Page 63: Scala Study Session

Scalaのなんかいまいちなところ

開発環境はイマイチ

Eclipseプラグインはエラーの嵐、Javaレベルは遠い

Scalaの長所を生かしきったFWが少ない

関数型のわかりづらさとカオスな言語仕様があいまって、読めない人続出の予感

Page 64: Scala Study Session

もう意味がよくわからない例

Scalaの制御構文?

object TargetTest2 extends Application {var i = 10loop {println("i = " + i) i -= 1

} unless (i == 0)}

Page 65: Scala Study Session

もう意味がよくわからない例

いいえ、メソッドです。

object TargetTest2 extends Application {def loop(body: => Unit): LoopUnlessCond =

new LoopUnlessCond(body)protected class LoopUnlessCond(body: => Unit) {

def unless(cond: => Boolean) {body if (!cond) unless(cond)

}}

}

Page 66: Scala Study Session

なぜそうなる

List構築の際の一般的な書き方

これは何?Listクラスの特別な構文か何か?

val list = List(“First”, “Second”, “Third”)

Page 67: Scala Study Session

なぜそうなる

いいえ、Listオブジェクトです。

object List {def apply[A](xs: A*): List[A] = xs.toList

…sealed abstract class List[+A] extends Seq[A] {…

Page 68: Scala Study Session

なぜそうなる

Streamを構築する際の一般的な書式は

Streamクラス?いやいや、違うはず。

Streamオブジェクトのconsメソッドだよね。

Stream.cons(1, Stream.cons(2, Stream.Empty))

Page 69: Scala Study Session

なぜそうなる

Streamオブジェクトの内部オブジェクトである「cons」のapplyメソッドです。

object Stream {object cons {

def apply[A](hd: A, tl: => Stream[A]) =new Stream[A] {override def hasDefiniteSize =

if (tlDefined) tlVal.hasDefiniteSizeelse super.hasDefiniteSize

…}

Page 70: Scala Study Session

言語内DSLへの道

このようなよくわからない構文を使うと、言語内DSLへの道が開けます

implicitもあわせると効果抜群、意味不明

val con = new FooConnectionusing(con) { c =>c.doSomething

}

Page 71: Scala Study Session

さわってみた印象

しょせんJavaだから

とか思ってなめてかかると痛い目にあう

というか意味がわからなくなるなった

Page 72: Scala Study Session

さわってみた印象

JavaScriptやRubyを超える

カオスさに好印象

Page 73: Scala Study Session

ありがとうございました

何か質問があれば