groovy++、来襲

92
Groovy++ 、来襲 Date: 2010/12/09

Upload: takahiro-sugiura

Post on 28-May-2015

1.479 views

Category:

Documents


2 download

TRANSCRIPT

Page 1: Groovy++、来襲

Groovy++ 、来襲

Date: 2010/12/09

Page 2: Groovy++、来襲

自己紹介名前 : 杉浦孝博twitter: @touchez_du_bois

Page 3: Groovy++、来襲

はじめに本日は、最近気になる OSS の Groovy++ について、・ Groovy++ ってなに?・何ができるの?・ Groovy と何が違うの?とかを語ってみたいと思います。

Page 4: Groovy++、来襲

Groovy ってなに?最初に Groovy とはなにか?Wikipedia 先生に聞いてみたいと思います。

Page 5: Groovy++、来襲

Groovy ってなに?Groovy は JVM 上で動作する言語処理系および言語の名称であり、 Java との直接的な連携を特徴とする。 ( 略 )Groovy は動的な言語であり、 ( 略 )Groovy コードは内部的にはJava バイトコードに変換されて JVM 上で実行される。 ( 略 )

Page 6: Groovy++、来襲

動的な言語Wikipedia 先生によると、コンパイル時に行うことを実行時に行う高級プログラミング言語・コードの追加・オブジェクトや定義の拡張・型システムの変更によるプログラムの拡張

Page 7: Groovy++、来襲

動的な言語のよい点いろいろとありますが・・・・型を書かなくてもよい ( 書く箇所が減る )・コンパイルしないで、すぐ実行できる

Page 8: Groovy++、来襲

動的な言語の残念な点いろいろとありますが・・・・実行速度が遅い・実行してみないとコンパイルエラー的な エラーさえわからない

Page 9: Groovy++、来襲

動的な言語の残念な点動的な言語の残念な点は、 Groovy にもあてはまります。・実行速度が遅い・実行してみないとコンパイルエラー的な エラーさえわからない

Page 10: Groovy++、来襲

Groovy の残念な点実行速度については・・・・ GroovyServ で起動時間は改善できます !!・その他は Java 化で高速に!! ...(^_^;)

Page 11: Groovy++、来襲

Groovy の残念な点コンパイルエラー的なエラーについては・・・・ IDE でどうにかなる?

Page 12: Groovy++、来襲

そこでGroovy++ の登場です。

Page 13: Groovy++、来襲

Groovy++ ってなに?Groovy++ とは、・ Groovy を静的型付けする拡張機能です。

Page 14: Groovy++、来襲

Groovy++ ってなに?つまり、・静的な型付けにより、 Groovy が持つ動的 言語の残念な点をある程度改善します。

Page 15: Groovy++、来襲

Groovy++ ってなに?Groovy++ が提供する機能はそれだけではありません。

Page 16: Groovy++、来襲

Groovy++ ってなに?こんなものも・ Trait・ GrUnit・ Tail Recursion

Page 17: Groovy++、来襲

Groovy++ ってなに?今回はパスします。・ Trait・ GrUnit・ Tail Recursion

Page 18: Groovy++、来襲

さっそく使ってみようまずはプロジェクトのページへhttp://code.google.com/p/groovypptest/

Page 19: Groovy++、来襲

さっそく使ってみようプロジェクトのページです。

Page 20: Groovy++、来襲

さっそく使ってみようgroovypp-0.4.101.zip をダウンロードします。

Page 21: Groovy++、来襲

さっそく使ってみよう展開して、環境変数 GROOVY_HOME とPATH を設定します。・ export GROOVY_HOME=/opt/groovypp-0.4.101・ export PATH=${GROOVY_HOME}/bin:${PATH}

Page 22: Groovy++、来襲

さっそく使ってみようgroovy コマンドでスクリプトを実行します。

$ groovy < スクリプトファイル名 >

Page 23: Groovy++、来襲

さっそく使ってみようこれだけでは、 Groovy を普通に動かすのと変わりません。スクリプトファイルを変更する必要があります。

Page 24: Groovy++、来襲

さっそく使ってみよう通常の Groovy プログラム

package sample

println "Hello, World!"

Page 25: Groovy++、来襲

さっそく使ってみようGroovy++ 化

@Typedpackage sample

println "Hello, World!"

Page 26: Groovy++、来襲

さっそく使ってみよう「基本的に」 Typed アノテーションを付けるだけ。

Page 27: Groovy++、来襲

で、どうなるの?Typed アノテーションを付けることにより、静的な型付がなされ、実行速度がアップします!!

Page 28: Groovy++、来襲

どれくらい速くなるの?サンプルのクイックソート・ Groovy : 284.758 秒

Page 29: Groovy++、来襲

どれくらい速くなるの?サンプルのクイックソート・ Groovy : 284.758 秒・ Groovy++ : 3.387 秒 (※@Typed を付けただけ )

Page 30: Groovy++、来襲

どれくらい速くなるの?サンプルのクイックソート・ Groovy : 284.758 秒・ Groovy++ : 3.387 秒 (※@Typed を付けただけ )・ Java : 2.394 秒

Page 31: Groovy++、来襲

どれくらい速くなるの?

Page 32: Groovy++、来襲

どうなってるの?Groovy のコードからバイトコードに変換されるときに、「錬金術」が発動されます。

Page 33: Groovy++、来襲

どうなってるの?Groovy のコードからバイトコードに変換されるときに、「 AST(Abstract Syntax Tree) 変換」を使って、静的に型解決されたバイトコードを生成します。

Page 34: Groovy++、来襲

どうなってるの?groovyc コマンドで Groovy コードをバイトコードに変換し、 jad で生成されるバイトコードを見てみましょう。

Page 35: Groovy++、来襲

どうなってるの?クイックソートのメインとなるメソッドです。def quicksort(int[] a, int L, int R) { int m = a[(L+R) >> 1] int i=L int j=R while (i<=j) { while (a[i]<m) i++ while (a[j]>m) j-- if (i<=j) { swap(a, i, j) i++ j-- } } if (L<j) quicksort(a,L,j) if (R>i) quicksort(a,i,R)}

Page 36: Groovy++、来襲

どうなってるの?@Typed 付けない場合です。public Object quicksort(int a[], int L, int R) { CallSite acallsite[] = $getCallSiteArray(); Integer m = (Integer)ScriptBytecodeAdapter.castToType(acallsite[19].call(a, acallsite[20].call(acallsite[21].call(DefaultTypeTransformation.box(L), DefaultTypeTransformation.box(R)), $const$3)), $get$$class$java$lang$Integer()); Integer i = (Integer)ScriptBytecodeAdapter.castToType(DefaultTypeTransformation.box(L), $get$$class$java$lang$Integer()); Integer j = (Integer)ScriptBytecodeAdapter.castToType(DefaultTypeTransformation.box(R), $get$$class$java$lang$Integer()); do { if(!ScriptBytecodeAdapter.compareLessThanEqual(i, j)) break; while(ScriptBytecodeAdapter.compareLessThan(acallsite[22].call(a, i), m)) { Integer integer = i; i = ((Integer) (acallsite[23].call(i))); Integer _tmp = integer; } while(ScriptBytecodeAdapter.compareGreaterThan(acallsite[24].call(a, j), m)) { Integer integer1 = j; j = ((Integer) (acallsite[25].call(j))); Integer _tmp1 = integer1; } if(ScriptBytecodeAdapter.compareLessThanEqual(i, j)) { acallsite[26].callCurrent(this, a, i, j); Integer integer2 = i; i = ((Integer) (acallsite[27].call(i))); Integer _tmp2 = integer2; integer2 = j; j = ((Integer) (acallsite[28].call(j))); Integer _tmp3 = integer2; } } while(true); if(ScriptBytecodeAdapter.compareLessThan(DefaultTypeTransformation.box(L), j)) acallsite[29].callCurrent(this, a, DefaultTypeTransformation.box(L), j); if(ScriptBytecodeAdapter.compareGreaterThan(DefaultTypeTransformation.box(R), i)) return acallsite[30].callCurrent(this, a, i, DefaultTypeTransformation.box(R)); else return null; }

Page 37: Groovy++、来襲

どうなってるの?@Typed 付けた場合です。public Object quicksort(int a[], int L, int R) { do { int m = ArraysMethods.getAt(a, L + R >> 1); int i = L; int j = R; do { if(i > j) break; for(; ArraysMethods.getAt(a, i) < m; i++); for(; ArraysMethods.getAt(a, j) > m; j--); if(i <= j) { swap(a, i, j); i++; j--; } } while(true); if(L < j) quicksort(a, L, j); if(R > i) { R = R; L = i; a = a; this = this; } else { return null; } } while(true);}

Page 38: Groovy++、来襲

どうなってるの?静的に解決されたコードが生成され、実行されるので、速くなるのが解っていただけると思います。

Page 39: Groovy++、来襲

明日からGroovy のコードに @Typed を付けまくるぞ!!

Page 40: Groovy++、来襲

でも

Page 41: Groovy++、来襲

そう簡単にはいきません

Page 42: Groovy++、来襲

なぜ?エドワード・エルリックという錬金術師は、第1話「二人の錬金術師」でこう言いました。

Page 43: Groovy++、来襲

なぜ?「つまり錬金術の基本は『等価交換』!!何かを得ようとするなら、それと同等の代償が必要ってことだ」

Page 44: Groovy++、来襲

代償?代償、ってほどでもないのですが、注意点があります。

Page 45: Groovy++、来襲

代償?@Typed を付けても、動かなかったり、動作が変わったりする場合があります。

Page 46: Groovy++、来襲

@Typed を付けられる位置@Typed を付けられる位置は決まっています。・パッケージ・クラス、インタフェース、列挙・コンストラクタ・メソッド

Page 47: Groovy++、来襲

@Typed を付けられる位置以下のコードは、

@Typed

println "Hello, World!"

Page 48: Groovy++、来襲

@Typed を付けられる位置コンパイルエラーになります。org.codehaus.groovy.control.MultipleCompilationErrorsException: startup failed:C:\Sample\ex01.groovy: 3: unexpected token: println @ line 3, column 1. println "Hello, World!" ^

1 error

Page 49: Groovy++、来襲

@Typed を付けられる位置動かすためには、 package を指定します。

@Typedpackage example

println "Hello, World!"

Page 50: Groovy++、来襲

コンパイル時にエラー間違ったメソッド呼び出しの場合

"Hello, World!".toStrings()

Page 51: Groovy++、来襲

コンパイル時にエラーGroovy は実行時にエラーになります。Caught: groovy.lang.MissingMethodException: No signature of method: java.lang.String.toStrings() is applicable for argument types: () values: []Possible solutions: toString(), toString(), toString(), contains(java.lang.CharSequence), contains(java.lang.String), substring(int)

at example.ex02.run(ex02.groovy:4)

Page 52: Groovy++、来襲

コンパイル時にエラーGroovy++ はバイトコード変換時 ( コンパイル時 ) にエラーになります。org.codehaus.groovy.control.MultipleCompilationErrorsException: startup failed:C:\Sample\ex02.groovy: 4: Cannot find method String.toStrings() @ line 4, column 17. "Hello, World!".toStrings() ^1 error

Page 53: Groovy++、来襲

実行時に解決するものはGroovy では問題なく動きますが、

package example

String.metaClass.p = { println "${delegate.size()} : ${delegate}"}

"Hello, World!".p()

Page 54: Groovy++、来襲

実行時に解決するものはGroovy++ では

@Typedpackage example

String.metaClass.p = { println "${delegate.size()} : ${delegate}"}

"Hello, World!".p()

Page 55: Groovy++、来襲

実行時に解決するものはコンパイルエラーになります。

org.codehaus.groovy.control.MultipleCompilationErrorsException: startup failed:C:\Sample\ex03.groovy: 5: Cannot find property p of class MetaClass @ line 5, column 18. String.metaClass.p = { ^1 error

Page 56: Groovy++、来襲

実行時に解決するものは解決方法は、 @Typed を付けないか、 @Typed(TypePolicy.MIXED) を付けます。

@Typed(TypePolicy.MIXED)package example

String.metaClass.p = { println "${delegate.size()} : ${delegate}"}

"Hello, World!".p()

Page 57: Groovy++、来襲

実行時に解決するものは指定できる TypePolicy は、以下のとおり・ STATIC(単に「 @Typed 」とした場合と同じ )・ DYNAMIC(@Typed を付けない場合と同じ )・ MIXED( 静的 / 動的を塩梅良くやってくれる )

Page 58: Groovy++、来襲

アクセス修飾子Groovy では private のプロパティ・メソッドもアクセスできます。package example

class Person { private String name private int age public Person(String name, int age) { this.name = name this.age = age } private dump() { println "name = ${name}, age = ${age}" }}def p = new Person("Mike", 25)p.dump()

Page 59: Groovy++、来襲

アクセス修飾子Groovy++ では@Typedpackage example

class Person { private String name private int age public Person(String name, int age) { this.name = name this.age = age } private dump() { println "name = ${name}, age = ${age}" }}def p = new Person("Mike", 25)p.dump()

Page 60: Groovy++、来襲

アクセス修飾子Groovy++ ではエラーになります。

org.codehaus.groovy.control.MultipleCompilationErrorsException: startup failed:C:\Sample\ex04.groovy: 19: Cannot access method Person.dump() @ line 19, column 3. p.dump() ^1 error

Page 61: Groovy++、来襲

クロージャと final 修飾子Groovy ではpackage example

def evenNum(List list) { def x = 0 list.each { int it -> if (it % 2 == 0) { x++ } } return x}println evenNum([1, 2, 3, 4, 5])

Page 62: Groovy++、来襲

クロージャと final 修飾子Groovy では正常に動作します。

$ groovy ex05.groovy2

Page 63: Groovy++、来襲

クロージャと final 修飾子Groovy++ では@Typedpackage example

def evenNum(List list) { def x = 0 list.each { int it -> if (it % 2 == 0) { x++ } } return x}println evenNum([1, 2, 3, 4, 5])

Page 64: Groovy++、来襲

クロージャと final 修飾子Groovy++ ではコンパイルエラーになります。org.codehaus.groovy.control.MultipleCompilationErrorsException: startup failed:C:\Sample\ex05.groovy: 8: Cannot modify final field example.ex05$evenNum$1.x @ line 8, column 13. x++ ^1 error

Page 65: Groovy++、来襲

クロージャと final 修飾子ロジックを変更するか@Typedpackage example

def evenNum(List list) { return list.findAll({ int it -> it % 2 == 0}).size()}

println evenNum([1, 2, 3, 4, 5])

Page 66: Groovy++、来襲

クロージャと final 修飾子groovy.lang.Reference を使っても解決できます。@Typedpackage example

int evenNum(List list) { Reference x = [0] list.each { int it -> if (it % 2 == 0) { x++ } } return x}println evenNum([1, 2, 3, 4, 5])

Page 67: Groovy++、来襲

整数同士の割り算整数同士の割り算ですが、

package example

println((4 / 2).class)

Page 68: Groovy++、来襲

整数同士の割り算Groovy では、 BigDecimal になります。

$ groovy ex06.groovyclass java.math.BigDecimal

Page 69: Groovy++、来襲

整数同士の割り算Groovy++ では、 int になります。0.4.96 から 0.4.101 のどこかで、 BigDecimal となりました。

$ groovy ex06.groovyclass java.math.BigDecimal

Page 70: Groovy++、来襲

整数同士の割り算次のソースは、

package example

println(4 / 2)println(5 / 2)

Page 71: Groovy++、来襲

整数同士の割り算Groovy

$ groovy ex07.groovy22.5

Page 72: Groovy++、来襲

整数同士の割り算Groovy++

$ groovy ex07.groovy22 2.5

Page 73: Groovy++、来襲

型推論Groovy++ では、静的な型付けのため、型推論も行っています。

Page 74: Groovy++、来襲

型推論例えばこのコード

@Typedpackage example

def x = new Date()println x + 1

Page 75: Groovy++、来襲

型推論groovyc でコンパイルし、 jad でバイトコードから Java のソースに戻すと・・・

Page 76: Groovy++、来襲

型推論となります。

(省略 ) public Object run() { Object x = new Date(); println(DateGroovyMethods.plus(((Date) (x)), 1)); return null; }(省略 )

Page 77: Groovy++、来襲

型推論def ではなく Date で宣言すれば・・・

@Typedpackage example

Date x = new Date()println x + 1

Page 78: Groovy++、来襲

型推論となります。

(省略 ) public Object run() { Date x = new Date(); println(DateGroovyMethods.plus(x, 1)); return null; }(省略 )

Page 79: Groovy++、来襲

他の G*なプロダクトと一緒他の G*なプロダクトと Groovy++ を一緒に使えるのか?

Page 80: Groovy++、来襲

他の G*なプロダクトと一緒Griffon と Groovy++・試していません m(_ _)m

Page 81: Groovy++、来襲

他の G*なプロダクトと一緒Grails と Groovy++・ Grails プラグインが提供されています。

Page 82: Groovy++、来襲

他の G*なプロダクトと一緒Grails と Groovy++・ダウンロードページからプラグインをダウンロードし、 install-plugin コマンドでインストールします。

$ grails install-plugin /path/to/grails-groovy-plus-plus-0.4.101.zip

Page 83: Groovy++、来襲

他の G*なプロダクトと一緒Grails と Groovy++・ Grails 1.3.6 + Groovy++ プラグイン 0.4.101・ generate-all で生成した Controller クラスに@Typed を付けるとどうなるか?・ create-xxx で生成した Domain Class やService クラスに @Typed を付けるとどうなるか?

Page 84: Groovy++、来襲

他の G*なプロダクトと一緒Grails と Groovy++・作成した Controller クラスや Service クラスに、 @Typed(TypePolicy=MIXED) を付けます。・ @Typed だと、 redirect メソッドや render メソッドでコンパイルエラーになります。

Page 85: Groovy++、来襲

他の G*なプロダクトと一緒Grails と Groovy++・ Domain Class の場合、 @Typed(TypePolicy=MIXED) でも、 @Typeでも、 constraints でエラーになります ...orz

Page 86: Groovy++、来襲

まとめ

Page 87: Groovy++、来襲

まとめ・ Groovy++ は、 Groovy を静的に型付する拡張機能です。

Page 88: Groovy++、来襲

まとめ・ Groovy++ は、 Groovy を静的に型付する拡張機能です。・基本的に @Typed を付けるだけです。

Page 89: Groovy++、来襲

まとめ・ Groovy++ は、 Groovy を静的に型付する拡張機能です。・基本的に @Typed を付けるだけです。・でも「錬金術」なので、 Groovy との違いに気をつけてください。

Page 90: Groovy++、来襲

発表は以上です。

Page 91: Groovy++、来襲

質問、意見、ご要望がありますでしょうか?

Page 92: Groovy++、来襲

以上、ご清聴ありがとうございました。