羽生田 栄一 株式会社 豆蔵 取締役会長

40
羽羽羽 羽羽羽羽 羽株株株株 株株 株株株株株 株株株株 株株 株株株株株 怪怪 怪怪 Ruby Ruby 怪怪 怪怪 Scala Scala 怪怪怪怪怪 怪怪怪怪怪 羽羽羽 羽羽羽 羽羽羽羽羽羽羽羽羽羽 羽羽羽羽羽羽羽羽羽羽 Scala Scala 羽羽羽 羽羽羽 株株株株 2008.2.26 @ 株株株株株株株株

Upload: hyatt-burt

Post on 03-Jan-2016

27 views

Category:

Documents


3 download

DESCRIPTION

豆ナイト 2008.2.26 @ 新宿三井ビル豆蔵. 怪盗 Ruby から Scala 座の怪人へ 関数型 オブジェクト指向言語 Scala 超入門. 羽生田 栄一 株式会社 豆蔵 取締役会長. クイズ:次の式の意味は?. val l = List(1,2,3,4,5,6,7,8,9,10) (0 /: l)( _+_ ). public class Person { private String lastName; private String firstName; private Person spouse; - PowerPoint PPT Presentation

TRANSCRIPT

Page 1: 羽生田 栄一 株式会社 豆蔵 取締役会長

羽生田 栄一羽生田 栄一株式会社 豆蔵 取締役会長株式会社 豆蔵 取締役会長

怪盗怪盗 RubyRuby からから ScalaScala 座の怪人座の怪人へへ

関数型関数型オブジェクト指向言語オブジェクト指向言語

ScalaScala 超入門超入門

豆ナイト 2008.2.26@ 新宿三井ビル豆蔵

Page 2: 羽生田 栄一 株式会社 豆蔵 取締役会長

クイズ:次の式の意味は?クイズ:次の式の意味は?1.1. val l = List(1,2,3,4,5,6,7,8,9,10)val l = List(1,2,3,4,5,6,7,8,9,10)

2.2. (0 /: l)( _+_ )(0 /: l)( _+_ )

Page 3: 羽生田 栄一 株式会社 豆蔵 取締役会長

JavaJava コード (コード ( 3737 行、行、 {}{} なしでなしで2121 行)行)

1.1. public class Personpublic class Person2.2. {{3.3. private String lastName;private String lastName;4.4. private String firstName;private String firstName;5.5. private Person spouse;private Person spouse;6.6. 7.7. public Person(String fn, String ln, Person s)public Person(String fn, String ln, Person s)8.8. {{9.9. lastName = ln; firstName = fn; spouse = s;lastName = ln; firstName = fn; spouse = s;10.10. }}11.11. public Person(String fn, String ln)public Person(String fn, String ln)12.12. {{13.13. this(fn, ln, null);this(fn, ln, null);14.14. }}15.15. 16.16. public String getFirstName()public String getFirstName()17.17. { { 18.18. return firstName;return firstName;19.19. }}20.20. 21.21. public String getLastName()public String getLastName()22.22. { { 23.23. return lastName;return lastName;24.24. }}25.25.

1.1. public Person getSpouse()public Person getSpouse()2.2. { { 3.3. return spouse;return spouse;4.4. }}5.5. public void setSpouse(Person p) public void setSpouse(Person p) 6.6. { { 7.7. spouse = p;spouse = p;8.8. // // 婚姻の対称性と姓の変更に関しては婚姻の対称性と姓の変更に関しては9.9. // // 考慮していません考慮していません10.10. }}11.11. 12.12. public String introduction()public String introduction()13.13. {{14.14. return "return " 私の名前は私の名前は ," + firstName + " " + lastName +," + firstName + " " + lastName +15.15. (spouse != null ? (spouse != null ? 16.16. " " 相方の名前は相方の名前は ," + spouse.firstName + " " + spouse.last," + spouse.firstName + " " + spouse.last

Name + " Name + " 。。 " :" :17.17. " " 。。 ");");18.18. }}19.19. }}

参考) http://blogs.tedneward.com/2006/03/02/Scala+Pt+2+Brevity.aspx

Page 4: 羽生田 栄一 株式会社 豆蔵 取締役会長

RubyRuby コードⅠ(コードⅠ( 1616 行、行、 endend なしなしでで 1212 行)行)1.1. class Personclass Person2.2. def initialize(firstname, lastname, spouse = nil)def initialize(firstname, lastname, spouse = nil)3.3. @firstName = firstname@firstName = firstname4.4. @lastName = lastname@lastName = lastname5.5. @spouse = spouse@spouse = spouse6.6. endend

7.7. attr_reader :lastNameattr_reader :lastName8.8. attr_attr_accessoraccessor :firstName, :spouse :firstName, :spouse9.9. 10.10. def introductiondef introduction11.11. if spouse == nilif spouse == nil12.12. "" 私の名前は私の名前は , #{firstName} #{lastName}", #{firstName} #{lastName}"13.13. elseelse14.14.     "" 私の名前は私の名前は , #{firstName} #{lastName} , #{firstName} #{lastName} 相方の名前は相方の名前は , #{spouse.firstName} #{spous, #{spouse.firstName} #{spous

e.lastName}"e.lastName}"15.15. endend16.16. endend17.17. endend

Page 5: 羽生田 栄一 株式会社 豆蔵 取締役会長

RubyRuby コードⅡ(コードⅡ( 1111 行、行、 endend なしなしでで 88 行)行)1.1. class Personclass Person2.2. def initialize(firstname, lastname, spouse = ndef initialize(firstname, lastname, spouse = niil)l)3.3. @first@firstNName, @lastame, @lastNName, @spouse = firstname, lastname, spouseame, @spouse = firstname, lastname, spouse4.4. endend

5.5. attr_reader :lastNameattr_reader :lastName6.6. attr_accessor :firstName, :spouseattr_accessor :firstName, :spouse

7.7. def introductiondef introduction8.8.          "" 私の名前は私の名前は , , #{firstName} #{lastName} " + (spouse ?#{firstName} #{lastName} " + (spouse ?9.9.          " " 相方の名前は相方の名前は , #{spouse.firstName} #{spouse.lastName}" : , #{spouse.firstName} #{spouse.lastName}" :

"")"")10.10. endend11.11. endend

Page 6: 羽生田 栄一 株式会社 豆蔵 取締役会長

ScalaScala コード(コード( 1010 行、行、 {}{} なしなしでで 88 行)行)1.1. class Person(ln : String, fn : String, s : Person)class Person(ln : String, fn : String, s : Person)2.2. {{3.3. def lastName = ln;def lastName = ln;4.4. def firstName = fn;def firstName = fn;5.5. def spouse = s;def spouse = s;6.6. 7.7. def this(ln : String, fn : String) = { this(ln, fn, null); }def this(ln : String, fn : String) = { this(ln, fn, null); }

8.8. def introduction() : String = def introduction() : String = 9.9. return "return " 私の名前は私の名前は , " + firstName + " " + lastName +, " + firstName + " " + lastName +10.10. (if (spouse != null) " (if (spouse != null) " 相方の名前は相方の名前は , " + spouse.firstName + " " + s, " + spouse.firstName + " " + s

pouse.lastName + "pouse.lastName + " 。。 " else "" else " 。。 ");");11.11. }}

Ruby とほぼ同じ簡潔さ  +  強い型付き!

<=型推論のおかげで型宣言が不要!

Page 7: 羽生田 栄一 株式会社 豆蔵 取締役会長

新世代言語新世代言語 ScalaScala に関する事に関する事実1実1 Scala からすべての Java クラスを簡単に利

用可 Java から Scala クラスを呼び出すことも自

由 膨大な Java 、 J2EE 、 Java ME CLDC の資

産がすべて、より合理的でコンパクトな形で利用可

Page 8: 羽生田 栄一 株式会社 豆蔵 取締役会長

新世代言語新世代言語 ScalaScala に関する事に関する事実2実2 Scala は Java VM 上で実行され その実行性能は Java コードとほぼ同等 結果として、

ほとんどのスクリプト言語より一桁速い > Ruby, Groovy ほか…

Page 9: 羽生田 栄一 株式会社 豆蔵 取締役会長

新世代言語新世代言語 ScalaScala に関する事に関する事実3実3 Scala は純粋なオブジェクト指向純粋なオブジェクト指向言語 しかも本格的な関数型本格的な関数型言語

Scala のデータはすべてオブジェクト: 文字列も配列も関数もすべて!

関数もオブジェクト: データとして自在に操作可(高階関数、クロー

ジャ、カリー化)

Page 10: 羽生田 栄一 株式会社 豆蔵 取締役会長

新世代言語新世代言語 ScalaScala に関する事に関する事実4実4 Scala 作者 Martin OderskyMartin Odersky 教授

Javac や Java Generics の開発貢献者 強力な開発体制強力な開発体制

早いペースでリリース ドキュメントも充実

実用的な汎用プログラミング言語実用的な汎用プログラミング言語 Scala 言語処理系

2008 年 1 月の時点で Scala 2.6.1-final が最新版

Page 11: 羽生田 栄一 株式会社 豆蔵 取締役会長

新世代言語新世代言語 ScalaScala の基本情報の基本情報 Scala の基本サイト

http://www.scala-lang.org/index.html Scala 言語チュートリアル

「 A Scala Tutorial for Java programmers 」(日本語訳) http://homepage.mac.com/takashi_miyamoto/scala/ScalaTutorial.pdf

Scalazine 「 First Steps to Scala 」(英語) http://www.artima.com/scalazine/articles/steps.html

より詳しい解説 Scala By Example

http://www.scala-lang.org/docu/files/ScalaByExample.pdf

Page 12: 羽生田 栄一 株式会社 豆蔵 取締役会長

まずは対話型インタープリタ Read-Eval-PrintRead-Eval-Print ループループ ScalaScala 基本サイトからダウンロード基本サイトからダウンロード

Page 13: 羽生田 栄一 株式会社 豆蔵 取締役会長

インタプリタ利用例インタプリタ利用例1. scala> val msg = " こんにちは " ,.................. val で定数の宣言。型省略。リテラルに日本語 OK

2. msg: java.lang.String = こんにちは ,..................... msg が String だと型推論されている3. scala> msg size ,.............................. msg.size や msg.size( ) としても同じ4. res2: Int = 5 ,......................... 結果の値が res<N> に、後で利用可。正しく 5 文字!5. scala> (1 to res2) foreach print ,.......... Int のメソッド to で範囲。メソッド foreach の引数に関数 print

6. 12345 ,........................ 1 ~ 5 を関数 print に順番に適用。改行したければ関数 println

7. scala> msg = " さよなら " ,....................... val で定義した msg は定数なので代入不可8. <console>:2: error: assignment to non-variable ,.................... エラー:定数への代入9. scala> var msg = " 挨拶 " ,................ var で変数を宣言。型指定すると var msg: String = " 挨拶 "

10. msg: java.lang.String = 挨拶 ,......................... 型指定しなくても String と推論。11. scala> msg = " やぁ " ,................................ 変数なので新規に代入可能12. msg: java.lang.String = やぁ13. scala> msg.foreach(println) ,......................... msg の各 Char に関数 println を適用14. やぁ15. scala> msg (0) ,................ String は Array[Char] とみなせ、ゼロ始まりの (i) で要素 i にアクセス16. res3: Char = や ,........... msg (i) は msg.apply(i) の省略形。更新は update(i, a) だが文字列には適用不可17. scala> for (c <- ' あ ' to ' ん ') ,..... to で Iterator[Char] の範囲指定。 <- は要素[集合記号]集合の記号を意味す

る18. | print(c) ,................ for 文の途中であえて改行。インタープリタ中で縦棒で継続可能。19. あぃいぅうぇえぉおかがきぎくぐけげこごさざしじすずせぜそぞただちぢっつづてでとどなにぬねのは

ばぱひびぴふぶぷへべぺほぼぽまみむめもゃやゅゆょよらりるれろゎわゐゑをん20. scala> :quit ,................................... Scala インタープリタを終了

Page 14: 羽生田 栄一 株式会社 豆蔵 取締役会長

言語言語 ScalaScala の文法の特徴の文法の特徴 11

統一性統一性::すべての値は、すべての値は、オブジェクトオブジェクト IntInt ArrayArray Function<N>Function<N>

すべてすべて メソッドをもちメソッドをもち 変数に代入し変数に代入し 引数に渡せるs引数に渡せるs

Page 15: 羽生田 栄一 株式会社 豆蔵 取締役会長

言語言語 ScalaScala の文法の特徴の文法の特徴 22

統一性統一性::すべての操作は、すべての操作は、メソッド適用メソッド適用 3 3 + + 4    ・・・  実は、次の式と同じ意味4    ・・・  実は、次の式と同じ意味 3 3 . +. +(4) (4) ・・・  ・・・  ++というメソッドを引数4で適というメソッドを引数4で適

用用

arrayarray (3) (3)   ・・・  配列の要素の参照も  ・・・  配列の要素の参照も array. apply(3) array. apply(3) ・・・  実は、メソッド・・・  実は、メソッド apply(i)apply(i) の適用の適用

array(3) = 0 array(3) = 0           ・・・  配列の要素の更新も・・・  配列の要素の更新も array. update(3, 0) array. update(3, 0) ・・・  実は、メソッド・・・  実は、メソッド update(i, v)update(i, v)

の適用の適用

Page 16: 羽生田 栄一 株式会社 豆蔵 取締役会長

言語言語 ScalaScala の文法の特徴の文法の特徴 33 基本基本 : : 必要に応じて省略可必要に応じて省略可

オブジェクト オブジェクト .. メソッド メソッド ((引数リスト引数リスト)) オブジェクト メソッド (引数リスト)オブジェクト メソッド (引数リスト) オブジェクト メソッド  1引数オブジェクト メソッド  1引数

文と文の区切り:  ;か改行文と文の区切り:  ;か改行 ブロック:       ブロック:        {S; T; U}{S; T; U} 式を整理するための括弧式を整理するための括弧 : : ()か()か {}{}

( ( a .m( b )a .m( b ) ) ) * * ( ( c / c / ( ( d + fd + f (( ee )) ) ) ) ) { a m( b )} * { c / { d + f{ a m( b )} * { c / { d + f (( ee )) } }} } ( ( a m b a m b ) ) * * ( ( c / { d + fc / { d + f (( ee )) } } )) { a m b } * { a m b } * ( ( c / { d + fc / { d + f (( ee )) } } ))

⇐ ⇐ DSLDSL に便利に便利

⇐ ⇐ DSLDSL に便利に便利 ⇐ ⇐ DSLDSL に便利に便利

Page 17: 羽生田 栄一 株式会社 豆蔵 取締役会長

Scala vs. Java :文法上の相違点1 型の宣言は型名変数 = 値ではなくて変数:型名 = 値で

指定 ただし、与えられた値から型推論できる場合には型名は省略可

代入不可の変数は val で宣言 通常の変数は var で宣言 任意のデータに def を用いて名前を付けられる

val の代わりにも def を使えるが振る舞いは若干異なる 関数やメソッドの宣言には def を用いる

文の区切り目の ; はオプション。通常は改行で表す 一連の複文は ; で区切ってブロック { } でまとめる。

単文はブロックにしなくてよい。 for ループ中の print(c) は { print(c) } としてもしなくても問題ない

Page 18: 羽生田 栄一 株式会社 豆蔵 取締役会長

Scala vs. Java :文法上の相違点2 数や文字列、配列も含めすべてのデータはオブ

ジェクト。 int 、 double 、 boolean なども含めすべてのデータは特定の型を表す Scala クラスに属する

void は Unit クラスとして扱い、 Unit 型の唯一のインスタンスは ( )

配列のインデックスは array[i] ではなく array(i) とアクセスする。配列の参照 array(i)および更新 array(i)=x も array.apply(i)および array.update(i,x) と

いう通常のメソッド適用と見なされる

Page 19: 羽生田 栄一 株式会社 豆蔵 取締役会長

Scala vs. Java :文法上の相違点3 [ ] は型パラメータの指定に使われ、 type IList =List[Int] の

ように宣言 型 T への cast は asInstanceOf [T] メソッドで

型パラメータを使えばほとんど無用 for ループは for-comprehension として定義

map 、 filter などに変換される static という概念はない

Singleton パターンで代用される。 class ではなく object を object Singleton extends Object { val data: Int } など

として定義し、その特性に static メンバ代わりにアクセスできる import 文でパッケージやクラスをインポートできる

* ではなく _ を利用 import javax.swing.JFrame; import javax.swing.JFrame._ などとする。 import javax.swing.{JFrame=>MyWindow} などと

名前を付け替えられる

Page 20: 羽生田 栄一 株式会社 豆蔵 取締役会長

関数の定義 基本は、名前付きの関数

def  関数名 (引数リスト):戻り型 = 関数本体

関数の仮引数の型は絶対に省略できません 戻り型は通常は型推論できるので省略可

ただし、関数定義本体が再帰的な場合は戻り型を省略できない

戻り型 void は、 Unit 型として宣言: ()は Unit 型の唯一のリテラル

Scala 関数のシグニチャ関数名 : ( 引数型リスト )戻り型

Page 21: 羽生田 栄一 株式会社 豆蔵 取締役会長

関数の定義例1. scala> def ##(str: String) = str.size , 文字数カウント。戻り型は省略2. $hash$hash: (String)Int ,.... 戻り型 Int をメソッド size から型推論3. scala> ##(“Scala 大好き” ) ,........... ## といった未使用記号も名前に

可4. res4: Int = 85. scala> def fact(n: BigInt): BigInt =  再帰なので戻り型宣言6. | if (n == 0) 1 else n * fact(n - 1)7. fact: (BigInt)BigInt ,.................... 関数 fact のシグニチャ表示8. scala> fact(100) ,............. 整数リテラル 100 から暗黙型変換で BigI

nt9. res5:BigInt=933262154439441526816992388562667004907159682643

81621468592963895217599993229915608941463976156518286253697920827223758251185210916864000000000000000000000000

Page 22: 羽生田 栄一 株式会社 豆蔵 取締役会長

無名関数の定義 関数名を指定せずに関数が定義できる関数名を指定せずに関数が定義できる

(( a: T1, b:T2,... a: T1, b:T2,... )=>関数本体)=>関数本体 ()=>関数本体()=>関数本体

例例 (n: Int) => n * 2 (a: Int, b: Int) => a * b () => println(” 言語は Scala”)

これらの関数はすべてオブジェクトなので、 関数として他のオブジェクトにメソッド適用したり 変数に代入したり 後から名前を付けたりできる

Page 23: 羽生田 栄一 株式会社 豆蔵 取締役会長

無名関数の利用例1. scala> (n: Int) => n * 2 ,........ 2倍するという無名関数 λn:Int. (n *

2)2. res6: (Int) => Int = <function> ,.......... (Int)=>Int という型の関数3. scala> res6(10) ,........ 仮名 res6 で関数を参照し整数 10 に適用4. res7: Int = 20 ,............................. 結果は整数 205. scala> val double = (n: Int)=> n * 2 ,..... 無名関数に double と名前

を6. double: (Int) => Int = <function> ,...... 7. scala> double ( 100 ) ,..... 関数バインド変数 double に引数リスト

適用8. res4: Int = 200 ,.......................... 結果は整数 2009. scala> List(1, 2, 3, 4, 5) map double ,. リスト各要素に関数を適用10. res14: List[Int] = List(2, 4, 6, 8, 10) ,............ 結果は 2倍の値のリ

スト

Page 24: 羽生田 栄一 株式会社 豆蔵 取締役会長

Scala における関数の正体 実は関数は、

    Function0 、 Function1 、 Function2, … といった引数の数を末尾に持つクラスの

インスタンス

1. object double extends Function1[Int, Int] {

2. def apply(n: Int): Int = n * 2

3. }

Page 25: 羽生田 栄一 株式会社 豆蔵 取締役会長

Scala におけるクラス定義 クラス宣言が基本コンストラクタの定義も兼ねる

1. class Person(na: String, ag: Int) {2. def name() = na3. def age() = ag4. }

5. scala> val tanaka = new Person("田中 ", 25)6. tanaka: Person = Person@13c2797

Page 26: 羽生田 栄一 株式会社 豆蔵 取締役会長

Scala におけるクラス定義 2言語としての簡潔さ

JavaJava の場合の場合1.1. class ClassA {class ClassA {

2.2. private String name;private String name;

3.3. private int age;private int age;

4.4. public ClassA(String name, int age) {public ClassA(String name, int age) {

5.5. this.name = name;this.name = name;

6.6. this.age = age;this.age = age;

7.7. }}

8.8. }} ScalaScala の場合の場合

class ClassA(name: String, age: Int) {}class ClassA(name: String, age: Int) {}

Page 27: 羽生田 栄一 株式会社 豆蔵 取締役会長

TraitTrait による多重継承(による多重継承( MixinMixin機機能)能) 「 Trait 」という概念

単一継承しか認められない通常クラスとは別に、 Java でいう Interface をより強力にし属性や操作も持たせられる

Mixin 的に多重継承が可能 Ruby のモジュールに相当

しかも、インスタンス生成時に with節を使って Mixin することもできる

Page 28: 羽生田 栄一 株式会社 豆蔵 取締役会長

Scala における Trait ( Mixin のこと)

1. class Person2. trait Teacher {3. def teach:Unit {}................. バーチャルなメソッドであってもよい

し4. }5. trait PianoPlayer {6. def playPiano = ......... 実装をともなう具象メソッドであってもよい7. }8. class PianoplayingTeacher extends Person with Teacher with PianoPlayer

.................. クラスとして Trait から継承

9. val tanakaTaro = new Person with Teacher with PianoPlayer ……………..田中太郎インスタンスに個別に性質を付与!

Page 29: 羽生田 栄一 株式会社 豆蔵 取締役会長

Scala から Java を呼ぶ Scala では自由にかつ簡単に Java クラスや Java イ

ンタフェースを利用できます。 次の例は、 Java の Swing ライブラリの利用例:

1. import javax.swing.{JFrame=>Mado}

2. import javax.swing.JFrame._

3. val mameMado = new Mado("豆窓 ")

4. mameMado setSize(200, 150)

5. mameMado setDefaultCloseOperation(EXIT_ON_CLOSE)

6. mameMado setVisible(true)

Page 30: 羽生田 栄一 株式会社 豆蔵 取締役会長

パターンマッチング機能 パターンマッチ対象を「 case class 」として宣

言 そのクラスのインスタンス生成時のコンストラク

タ呼び出し時に new を省略可 new Var(“x1”) Var("x1")

case クラスを利用して、抽象データ型を定義1. abstract class Term2. case class Var(name: String) extends Term3. case class Fun(arg: String, body: Term) extends Term4. case class App(f: Term, v: Term) extends Term

5. Fun("x", Fun("y", App(Var("x"), Var("y"))))

Page 31: 羽生田 栄一 株式会社 豆蔵 取締役会長

パターンマッチング機能パターンマッチング機能1. def print(term: Term): Unit = term match {2. case Var(n) => print(n) ,.......... マッチ時の対応は個別に case以下で定義3. case Fun(x, b) => print("/\" + x + "." ); print(b)4. case App(f, v) => print("("); print(f); print(" "); print(v); print(")")5. }6. scala> val t1: Term = Fun("x", Fun("y", App(Var("x"), Var("y"))))7. t1: Term = Fun(x,Fun(y,App(Var(x),Var(y))))8. scala> print(t1)9. /\x. /\y. (x y)

10. def isIdFun(term: Term): Boolean = term match {11. case Fun(x, Var(y)) if x == y => true ,......... case 中の if節で等値テスト12. case _ => false ,.................... 残りすべてのケース「 - 」13. }

14. scala> isIdFun( Fun("a", Var("a") )) ,......... 項 /\a.a は明らかに恒等関数 Id15. res33: Boolean = true16. scala> isIdentityFun(t1) ,........... 項 /\x. /\y. (x y) は恒等関数ではない17. res32: Boolean = false

Page 32: 羽生田 栄一 株式会社 豆蔵 取締役会長

高階関数・クロージャの利用高階関数・クロージャの利用 ScalaScala では、関数もオブジェクトなので自由では、関数もオブジェクトなので自由

にに 変数に代入できる変数に代入できる 他のオブジェクトに対し、メソッド適用できる他のオブジェクトに対し、メソッド適用できる

引数の名前呼び(引数の名前呼び( call by namecall by name )で遅延評価)で遅延評価 f1f1 ( ( p1: T1p1: T1 ) ・・・通常の値呼び() ・・・通常の値呼び( call by call by

valuevalue )) f2f2 ( ( q1: q1: =>T1=>T1 ) ・・・) ・・・名前呼び(名前呼び( call by namcall by nam

ee ))

Page 33: 羽生田 栄一 株式会社 豆蔵 取締役会長

DSLDSL としてのとしての ScalaScala の可能性1:の可能性1:独自の制御構造の定義例独自の制御構造の定義例 例:独自の制御構造例:独自の制御構造WhileWhile の定義の定義

1. def While (p: => Boolean) (s: => Unit) {2. if (p) { s ; While(p)(s) }3. }

4. scala> var i: Int = 05. scala> While ( i < 3 ) {i=i+1; print(“ がってん ” )}6. がってん がってん がってん 7. scala>While ( true ) ( print (”世界は無限だ”)

Page 34: 羽生田 栄一 株式会社 豆蔵 取締役会長

DSLDSL としてのとしての ScalaScala の可能性の可能性 22 ::新しいデータ構造や型の追加新しいデータ構造や型の追加

新しい型新しい型 ((例:例: BigInteger)BigInteger) を追加したいときを追加したいとき > factorial(30) 265252859812191058636308480000000

従来の言語(従来の言語( JavaJava でもでも HaskelHaskel でもでも *1*1 )だと…)だと…1.1. import java.math.BigIntegerimport java.math.BigInteger2.2. def factorial(x: BigInteger): BigInteger =def factorial(x: BigInteger): BigInteger =3.3. if (x == if (x == BigIntegerBigInteger.ZERO.ZERO))4.4. BigIntegerBigInteger.ONE.ONE5.5. elseelse6.6. xx.multiply.multiply(factorial(x(factorial(x.subtract.subtract((BigIntegerBigInteger.ONE.ONE))))))

*1 *1 ここに最初は「ここに最初は「 RubyRuby でも」といれていたら、会場一番前で聞いておられでも」といれていたら、会場一番前で聞いておられたマツモトさん本人に誤解だと指摘され削除しました。ご指摘ありがとうござたマツモトさん本人に誤解だと指摘され削除しました。ご指摘ありがとうございました。いました。

Page 35: 羽生田 栄一 株式会社 豆蔵 取締役会長

DSLDSL としてのとしての ScalaScala の可能性の可能性 33 ::使い慣れたリテラルや演算子で使い慣れたリテラルや演算子で OOKK ScalaScala であれば…であれば…

1. def factorial(x: BigInt): BigInt =

2. if (x == 0) 1 else x * factorial(x - 1) クラス BigInt は Java の BigInteger をラップし

ているだけなのに通常の演算表記で使える ! 演算子( +,-,*,・・・)のオーバーローデングが

簡単 暗黙の型変換暗黙の型変換 Implicit Conversion が強力!1. implicit def intToBigInt(x: Int) = new BigInt(x)

Page 36: 羽生田 栄一 株式会社 豆蔵 取締役会長

DSLDSL としてのとしての ScalaScala の可能性の可能性 44 ::無名引数とカリー化無名引数とカリー化

無名関数の別記法( 無名関数の別記法( _ _ 無名パラメータ)無名パラメータ) ( ( _.isUpperCase _.isUpperCase ) == ) ==  (c:Char)=>c.isUpperCase(c:Char)=>c.isUpperCase ( _+_ )( _+_ )   == (  == ( a, ba, b )) => a + b …=> a + b … 変数の型は推論変数の型は推論

カリー化(関数の部分的具体化)カリー化(関数の部分的具体化)1. def foo(x: Int)(y: Int) = x + y2. def add1(x:Int) = foo(x)(1)      // x + 1 に相当3. add1(100) 1014. def `100add`(y:Int) = foo(100)(y)   // 100+y に相当5. `100add`(7) 107

クイズの答えクイズの答え1.1. val l = List(1,2,3,4,5,6,7,8,9,10)val l = List(1,2,3,4,5,6,7,8,9,10)2.2. (0 /: l)( _+_ )(0 /: l)( _+_ )  計算結果  計算結果 5555    00 にリストにリスト ll の要素を左から順番に足しの要素を左から順番に足し込んでいく込んでいく foldLeftfoldLeft (( a0:A, l:List[A]a0:A, l:List[A] ))

Page 37: 羽生田 栄一 株式会社 豆蔵 取締役会長

DSLDSL としてのとしての ScalaScala の可能性の可能性 55 ::日本語で語彙(型・関数・変数)自由に表日本語で語彙(型・関数・変数)自由に表現!現!

1.1. case class `case class `住所住所 `(adr: (Int, String, String, String))`(adr: (Int, String, String, String))2.2. case class `case class ` 利用者利用者 `(``(`登録登録 id`:BigInt, `id`:BigInt, `氏名氏名 `:String, ``:String, `連絡先連絡先 `:``:`住所住所 `)`)3.3. case class `case class `図書図書 `(``(`書名書名 `:String, ``:String, `図書図書 id`:BigInt){id`:BigInt){4.4. def `def ` を貸し出すを貸し出す =>`(`=>`(`借り手借り手 `:``:` 利用者利用者 `)`)    }}5.5. val `val `段田塊太段田塊太 `̀ = `= ` 利用者利用者 `(9200800345, “`(9200800345, “段田塊太”段田塊太” , `, `住所住所 `(101630434, `(101630434,

““ 新宿”新宿” , “2-1-1”, “, “2-1-1”, “ スカラ座ビル”スカラ座ビル” ))))6.6. val `val ` 本本 1`=`1`=`図書図書 ` (“` (“ はじめてのスカラ”はじめてのスカラ” , 1200700077), 1200700077)7.7. `̀ 本本 1` `1` ` を貸し出すを貸し出す =>` `=>` `段田塊太段田塊太 `̀    <= `<= ` 本本 1`.`1`.`貸し出し貸し出し `(``(`段田塊太段田塊太 `)`)

ScalaScala の識別子の定義(以下のの識別子の定義(以下の 44種のいずれか)種のいずれか) alphanumeric : a letter or _ で開始  例)  HHanyuda _var _Max _Int operator : printable ASCII 文字 +, :, ?, or # 等で開始  例)  +   ++   :::   <?>   :-> mixed : alphanumeric+ operator

op_ + op_* power_** human_? toBeOrNotToBe_? literal : ‘任意の文字列‘ (2つの back-tick‘ で囲った文字列)

‘x‘   ‘ <clinit>‘    ‘ yield‘    ‘人間‘   ‘貸し出す‘  ‘処理 A‘

要求要求コードコード の のトレーサビリティトレーサビリティの確立の確立 日本語で書いた要求を日本語のクラスとメソッドで仕様化し、日本語で書いた要求を日本語のクラスとメソッドで仕様化し、

日本語の変数や文字列でプログラミングできる!日本語の変数や文字列でプログラミングできる!

Page 38: 羽生田 栄一 株式会社 豆蔵 取締役会長

その他の Scala の可能性:注目機能注目機能1. Lisp以来の関数型言語の伝統の柔軟なリスト構造の処理2. 部分関数、カリー化や高階関数、クロージャの自由な扱い3. 総称型( generics )および暗黙の型変換を含む高度な型処理4. 文字列やリスト・クラス( case class )まで含めた強力なパターンマッチ

ング5. for 文( 正確には for -comprehension )と Some(T) によるモナドの実現6. 遅延評価 lazy機能7. メタプログラミングのためのアノテーション @機能8. 構造的サブタイピング(継承に依らないポリモルフィズム・Duck Typin

g )

9. XML 操作機能( XML リテラル、 Scala式の埋め込み、 DOMツリー操作)

10. PEG ( Parsing Expression Grammar :解析表現文法)と JSON パーサ

11. アクター理論にもとづく並列性ライブラリ( Ruby の Fiber に相当)

12.12. LiftLift ( Scala=階段、に対しエレベータの意。 http://liftweb.net )という Ruby on Rails風の強力なフルスタックの Web アプリ開発フレームワーク。Lift を利用し 140 行で作られたサイト http://scala-blogs.org も存在する

Page 39: 羽生田 栄一 株式会社 豆蔵 取締役会長

liftlift Web FrameworkWeb Framework : :  http://demo.liftweb.nethttp://demo.liftweb.net

/lift//lift/

RailsRails風フルスタック風フルスタック F/W(F/W(現在現在 v0.5)v0.5) lift lift はは Java WebJava Web コンテナ上で動く コンテナ上で動く + Scala + Scala で簡単にコーディングで簡単にコーディング ..

lift lift アプリは、 アプリは、 WAR files WAR files で任意の で任意の Servlet 2.4 engine (Tomcat 5.5.xx, Jetty 6.0, etc.)Servlet 2.4 engine (Tomcat 5.5.xx, Jetty 6.0, etc.) にデプロイ可能にデプロイ可能 lift lift は、オープンソースであり、は、オープンソースであり、 Apache License V2.0Apache License V2.0 で配布で配布

lift lift の特徴:の特徴: セキュリティセキュリティ , , アプリ開発の高生産性アプリ開発の高生産性 , , 開発・保守の容易性開発・保守の容易性 , , 高い実行性能高い実行性能 , , 既存既存 J2EEJ2EEシステムとの互換性システムとの互換性

影響を受けた既存のフレームワーク影響を受けた既存のフレームワーク Seaside の柔軟なセッションとセキュリティの取り扱い ,   Rails の超お手軽な高速アプリ開発 , Django の単なる CRUD 以上の機能 ,   Erlyweb の Comet スタイルのアプリのスケーラビリティ

Lift vs. RailsLift vs. Rails 同じくらいクリーンで簡潔なコード同じくらいクリーンで簡潔なコード

lift lift と と Rails Rails でコード規模はほぼ同じ。ただし、テストコードサイズは、 強い型のおかげで約でコード規模はほぼ同じ。ただし、テストコードサイズは、 強い型のおかげで約 60%60% 厳密な型チェック厳密な型チェック

1.1. User.find(By(User.email, "[email protected]")) // legalUser.find(By(User.email, "[email protected]")) // legal2.2. User.find(By(User.birthday, new Date("Jan 4, 1975"))) // legalUser.find(By(User.birthday, new Date("Jan 4, 1975"))) // legal3.3. User.find(By(User.birthday, "[email protected]")) // compiler errorUser.find(By(User.birthday, "[email protected]")) // compiler error

66倍高速、マルチスレッド対応倍高速、マルチスレッド対応 簡潔な簡潔な DSLDSL の提供の提供

1.1. User.find(20) // find the user with primary key 20User.find(20) // find the user with primary key 202.2. // find all the users that registered 4 days ago// find all the users that registered 4 days ago3.3. User.findAll(By(User.registered, 4.days.ago)) User.findAll(By(User.registered, 4.days.ago)) 4.4. // activate the account or suspend it after 4 days// activate the account or suspend it after 4 days5.5. State(NewAcct, On({case Activate =>}, Activated),After(4 days, Suspended))State(NewAcct, On({case Activate =>}, Activated),After(4 days, Suspended))6.6. State(Suspended) entry {sendSuspendedEmail}State(Suspended) entry {sendSuspendedEmail}

Page 40: 羽生田 栄一 株式会社 豆蔵 取締役会長

まとめ: Ruby もいいけど ScalaScalaもネ! Scala は単純で統一性のある文法を目指している さまざまな機能は言語としてでなく、ライブラリとして 性能を意識した最適化された処理系Ruby と比較して、 Scala は強い型付け

動的な性質が弱い分だけ柔軟性に欠けると予想されがちだが 統一性、型推論や高階関数、パターンマッチングに助けられて、

表現力において 記述のコンパクトさにおいて十分互角に戦える言語に仕上がっている

ぜひ食わず嫌いを止めて、まずは味見を!