2007年10月26日

Script-fu In GIMP 2.4

Gimp-2.4ではSchemeインタプリタがSIODからTinySchemeへと変更されました。2.4リリースアナウンス時に公開された、これによる変化について書かれた文章の翻訳です。

→ Script-fu In GIMP 2.4

GIMP 2.4のScript-Fu



バージョン1.0のGimpからずっと、プログラマーの可能性を拡張させて繰り返し作業を単純化させるスクリプト言語が入っていました。このプログラミング言語"Script-Fu"はSchemeプログラミング言語の実装であるSIODインタプリタをベースに作られていました。SIODは80年代にボストン大学の教授であるGeorge J. Carretteによって作られました。


このScript-FuインタプリタはCarrette氏のSIODをベースとしていましたが、この10年間実によくGimpの役に立ってくれました -- そして数多くのスクリプトがGimpユーザーによって書き上げられ、共有されてきました -- しかしもう歳を召してしまったこともあり、Gimp開発者チームはTinySchemeというもっと近代的なSchemeインタプリタと交換することに決めたのです。この置き換えのもっとも大きな理由の一つは、SIODでは規定されていなかった言語やフォントの国際化に対応するためでした。他にも理由がありますが、国際化対応は最も重要なことだったわけです。


これによりGimp開発者(特にKevin Cozens氏)に広範囲な努力が求められ、Gimpソースコードの中身にはいくつかの重要な変更がなされ、Gimpユーザーにはちょっとだけ目に見える変更がありました。Gimpのスクリプト拡張はまだ"Script-Fu"と呼ばれており、利用可能な圧倒的多数のスクリプトは既に新しいTinySchemeベースのインタプリタで使われている機能になっています。


Gimp内部に対する変更による影響をできる限り最小限に抑えようとしたため、SIODベースのインタプリタとTinySchemeベースのインタプリタとの間にはいくつかの違いが生じてしまいました。それはGimp 2.4より古いスクリプトを使おうとすると出てくるかもしれません。以下は、遭遇するかもしれない問題についての説明と、それを修正するためにはどの手順を踏めばよいのかの説明です。





未宣言変数の扱い



古いスクリプトを使おうとするとよく遭遇する問題は、最初に変数を宣言することなく変数に値を割り当ててしまうことかもしれません。SIODベースのScript-Fuでは'x'が宣言されていなくても(set! x 4)といった構文が使用できていました。'x'が自動的にグローバル変数として定義されるようになっていたからです。新しいScript-Fuではこのような状況を保護します。プログラマーはまず最初に変数を宣言しなければいけません。問題のあるスクリプトでは"Error: set!: unbound variable: x"というメッセージが表示されるでしょう。


普通はグローバル変数を使うようなことはしないでおきましょう。なぜなら(別の作者によって書かれた)別の関数が同じ名前を使用してしまうと、その二つの関数はお互いに干渉してしまうからです。このため、先ほどの例での'x'を正しく宣言する方法は、letlet*構文を使うことです。




(let* ( (x 4) )
...
...
...
)



条件式における空リスト



(if, while, cond, not, =, などの)条件判定においてSIODは空リストをFALSEとして扱います。一方Schemeの標準仕様ではこれをTRUEと評価します。プログラマーは最初からこの違いに気付いていて、SIOD非標準規格のスクリプトになることを残念に思っていました。しかしこれは可能であったのです。簡単な解決方法はリストをテストするために 'pair?' 関数を使用することです。例えば (while lis ... )(while (pair? lis) ...) に置き換えます。(pair? lis)(not (null? lis)) に置き換えられます。




空リストの先頭要素にアクセス



SIODでは、空リストを'car'で取り出すと空リストを返しました。TinySchemeにおいてこれは許可されず、エラーメッセージ ("Error: car: argument 1 must be: pair") が作成されます。こういった条件文のように、プログラマーはSIOD非準拠の挙動に気を付けなければいけません。この問題に遭遇することはレアケースにならなくてはいけません。この問題を直すには、もし遭遇したら、リストにアクセスする前にリストが空であるかどうかの構成テストが必要です。




リストの最後尾要素より後ろにアクセス



前の問題に似ていますが、SIODはリストの最終要素を超えた要素にアクセスすることが許されており、このときには空リストが返されます。例えば、要素を持たないリストから'cdr'や'cddr'で取り出すことができました。Gimp 2.4ではこれを行うとエラーメッセージ ("Error: cdr: argument 1 must be: pair") となります。繰り返しになりますが、SIODの挙動は長い間ずっと非標準の挙動をしていて、この問題によりこういったレアな問題を発生させていました。この問題を修正するには、もし遭遇したら、リストにアクセスするときにはより正確なテストをしなければなりません。



ペアを作る



Schemeのcons関数はペアへと結合させる二つの引数を必要とします。SIODでは、引数が一つだけしかなかった場合には二番目の引数は自動的に空リストであるとみなされていました。Gimp 2.4では、二番目の引数が存在しなかった場合にはエラー ("Error: cons: needs 2 argument(s)") となります。解決するには、この問題が発生したら、第二引数として明示的に空リストを追加します。



推奨されない機能



次のSIOD関数や定数は現在のTinySchemeで使用することはできますが、将来のバージョンでは消えてしまうかもしれません。




  • aset - TinySchemeの vector-set! で置き換え

  • aref - TinySchemeの vector-ref で置き換え

  • fopen - TinySchemeの open-input-file で置き換え

  • mapcar - TinySchemeの map で置き換え

  • nil - TinySchemeの '() で置き換え

  • nreverse - TinySchemeの reverse で置き換え

  • pow - TinySchemeの expt で置き換え

  • prin1 - TinySchemeの write で置き換え

  • print - TinySchemeの write (newlineに続けて) で置き換え

  • strcat - TinySchemeの string-append で置き換え

  • string-lessp - TinySchemeの string<? で置き換え

  • symbol-bound? - TinySchemeの defined? で置き換え

  • the-environment - TinySchemeの current-environment で置き換え

  • *pi* - 定数 *pi* はTinySchemeにおいて定義済ではありませんが (* 4 (atan 1.0)) で定義することができます

  • butlast - TinySchemeで使用することはできませんが別コード (reverse (cdr (reverse x))) が利用可能です

  • cons-array - TinySchemeの make-vector で置き換え



最後に



もとのScript-FuとGimp 2.4のScript-Fuの間にはいくつかの違いがありますが、それらはレアケースであるため既存のスクリプトでそれほど大きな問題にはならないでしょう。catch/throw 文(これはエラーを捕捉する)と bytes-append 関数(これは世に出回っているScript-Fuの中には見られない)といった構文も違いに含まれます。そういった問題が含まれているスクリプトに遭遇したら、Gimp開発者メーリングリストへ問題の要旨について投稿してみてください。


posted by いっちー at 00:16| Comment(1) | News | 更新情報をチェックする
この記事へのコメント
翻訳ありがとうございます。先日まで、これほど極端に仕様が変わっていた、というのを全く知りませんでした。

ここの記事にリンク張らせてもらいました。
Posted by たむぶん at 2008年05月19日 00:22
コメントを書く
お名前: [必須入力]

メールアドレス:

ホームページアドレス:

コメント: [必須入力]

認証コード: [必須入力]


※画像の中の文字を半角で入力してください。
×

この広告は1年以上新しい記事の投稿がないブログに表示されております。