読者です 読者をやめる 読者になる 読者になる

Groovy スクリプトで複素数データを扱う その2

前回の test2.groovy をもう一度見てみます。

// test2.groovy
// Number クラスに複素数オブジェクト用の演算を追加する。
// 加算
Number.metaClass.plus = {Complex b ->
  new Complex (delegate + b.r, b.i)
}
// 乗算
Number.metaClass.multiply = {Complex b ->
  new Complex (delegate * b.r, delegate * b.i)
}

def i = new Complex(0, 1) // 虚数 i
def z1 = 2 + i
def z2 = 1 + 5 * i
println z1 * z2

前半の Number へのメソッドの追加と虚数 i の宣言の行は毎回記述しないといけないのでしょうか。

このスクリプトでは最後の3行分だけがやりたいことであって、それ以外の部分は複素数の計算式を成立させるための実装にすぎません。一度実装内容を理解したら、あとは興味はわきませんよね。できることならば次のように簡潔に記述したいと思うはずです。

// test3.groovy
def z1 = 2 + i
def z2 = 1 + 5 * i
println z1 * z2

この中では虚数 i はビルトイン定数となっています。

さて、Groovy にはスクリプトの文字列を実行してくれる非常に強力なクラス GroovyShell が用意されています。早速、GroovyShell の例を見てみましょう。

// calc.groovy
// Number クラスに複素数オブジェクト用の演算を追加する。
// 加算
Number.metaClass.plus = {Complex b ->
  new Complex (delegate + b.r, b.i)
}
// 乗算
Number.metaClass.multiply = {Complex b ->
  new Complex (delegate * b.r, delegate * b.i)
}
// ビルトイン定数やビルトイン関数の定義
def binding = new Binding([
  i: new Complex(0, 1), // 虚数
])

// 式の評価。
def shell = new GroovyShell(binding)
shell.evaluate(new File(args[0]))

まず Number クラスへのインスタンスメソッドを追加し、複素数オブジェクト用の加算と乗算の演算を追加しています。
虚数 i は Binding クラスのコンストラクタの引数のマップ配列で定義しています。この Binding クラスのインスタンスオブジェクトは GroovyShell のコンストラクタに渡され、生成された shell オブジェクトの中でのみ有効なビルトイン定数となっています。
最後の evaluate メソッドでこのスクリプトに渡された引数のファイルを実行します。

test3.groovy を実行してみましょう。

C:\work> groovy calc.groovy test3.groovy
-3 + 11i

期待通りの結果が出力されました。

今後、複素数データを扱うスクリプトでは calc.groovy を呼ぶようにバッチを用意してしまいましょう。

まず calc.groovy と Complex.groovy は %GROOVY_HOME%\mylib ディレクトリの下にコピーしておきます。

次のようなバッチファイル mygroovy.bat を作成します。

@echo off
"%JAVA_HOME%\bin\java.exe" ^
 "-Xmx128m" ^
 -Dprogram.name="" ^
 -Dgroovy.home="%GROOVY_HOME%" ^
 -Dgroovy.starter.conf="%GROOVY_HOME%\conf\groovy-starter.conf" ^
 -Dscript.name="%GROOVY_HOME%\mylib\calc.groovy" ^
 -classpath "%GROOVY_HOME%\lib\groovy.jar" ^
 org.codehaus.groovy.tools.GroovyStarter ^
 --main groovy.ui.GroovyMain ^
 --conf "%GROOVY_HOME%\conf\groovy-starter.conf" ^
 --classpath "%GROOVY_HOME%\mylib;." ^
 %GROOVY_HOME%\mylib\calc.groovy ^
 %1

実行はこんな感じになります。

C:\work> mygroovy test3.groovy
-3 + 11i

(続く)