groovy++、来襲

Post on 28-May-2015

1.479 Views

Category:

Documents

2 Downloads

Preview:

Click to see full reader

TRANSCRIPT

Groovy++ 、来襲

Date: 2010/12/09

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

package sample

println "Hello, World!"

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

@Typedpackage sample

println "Hello, World!"

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

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

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

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

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

どれくらい速くなるの?

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

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

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

どうなってるの?クイックソートのメインとなるメソッドです。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)}

どうなってるの?@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; }

どうなってるの?@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);}

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

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

でも

そう簡単にはいきません

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

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

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

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

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

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

@Typed

println "Hello, World!"

@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

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

@Typedpackage example

println "Hello, World!"

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

"Hello, World!".toStrings()

コンパイル時にエラー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)

コンパイル時にエラー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

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

package example

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

"Hello, World!".p()

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

@Typedpackage example

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

"Hello, World!".p()

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

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

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

@Typed(TypePolicy.MIXED)package example

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

"Hello, World!".p()

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

アクセス修飾子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()

アクセス修飾子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()

アクセス修飾子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

クロージャと 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])

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

$ groovy ex05.groovy2

クロージャと 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])

クロージャと 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

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

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

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

クロージャと 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])

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

package example

println((4 / 2).class)

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

$ groovy ex06.groovyclass java.math.BigDecimal

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

$ groovy ex06.groovyclass java.math.BigDecimal

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

package example

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

整数同士の割り算Groovy

$ groovy ex07.groovy22.5

整数同士の割り算Groovy++

$ groovy ex07.groovy22 2.5

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

型推論例えばこのコード

@Typedpackage example

def x = new Date()println x + 1

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

型推論となります。

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

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

@Typedpackage example

Date x = new Date()println x + 1

型推論となります。

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

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

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

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

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

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

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

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

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

まとめ

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

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

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

発表は以上です。

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

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

top related