Script-Fu の解説続き

前回に引き続いて実際に公開してる[複数の画像からパターンを一括作成]を用いてのScript-Fuの解説です。
今回はメインの処理部分を見ていきます。

(define (script-fu-fe-layers-to-patterns img drawable dir)
        (map
         (lambda (layer)
           (let* ((basename
                   (remove-extension
                    (car (gimp-drawable-get-name layer))))
                  (filename (concat dir "/" basename ".pat")))
             (file-pat-save
              1 img layer filename basename basename)))
         (vector->list (cadr (gimp-image-get-layers img)))))

define で関数の定義

まず、一行目。

(define (script-fu-fe-layers-to-patterns img drawable dir)

この define を使うことにより新しい関数を定義できます。
引数の一つ目が関数の名前、ここでは script-fu-fe-layers-to-patterns になっています。
その後ろについてる img, drawable, dir の3つが引数ですね。
これは前回の script-fu-register で使った SF-IMAGE, SF-DRAWBLE, SF-DIRNAME を受け取ってます。

そうそう、関数名は頭に script-fu- が付けることが決まってるそうです。
あとは他のスクリプトと被らないようにだけ気をつけて適当に命名してください。

便利な map の使い方

(map
(lambda (layer)

ここがとっつきにくいポイントなので、map を使った簡単な例を紹介ます。

(map + '(1 2 3) '(4 5 6))

では、GIMPを立ち上げてメニューの[フィルタ]→[Script-Fu]→[コンソール]を開いて
上のコードを入力欄にいれて、エンターキーを叩いて確定してください。

(5 7 9)

と表示されたでしょう。次は + を * に変えて入力してください

(map * '(1 2 3) '(4 5 6))

こんどは

(4 10 18)

と表示されましたね。同じように – や / も試して見てください

(map - '(1 2 3) '(4 5 6)) ; (0.25 0.4 0.5)
(map - '(1 2 3) '(4 5 6)) ; (-3 -3 -3)

規則には気づかれたでしょうか?
具体的に述べますと map は 第一引数に関数をとりそれ以降のリストに適用し、
その結果をリストで返します。つまり

(map + '(1 2 3) '(4 5 6))

(list (+ 1 4) (+ 2 5) (+ 3 6)) ; listはリストを返す関数

と同様の処理になります。大変便利な関数なのですが普通は+などの簡単な処理ではなく
自分の定義したもっと複雑な関数を適用させる事が多いでしょう。

scheme でよく使う lambda とは

そこで出てくるのが lambda(無名関数)です。
無名関数とはその名の通り名前を持たない関数です。
言葉にするとややこしいですが「関数を定義するまでもない簡単な関数が欲しい時に使う」ぐらいの理解で大丈夫でしょう

さて、その使い方の解説のために初めは名前を持つ関数を作ってみます。

(define (add-2 n) (+ n 2))

この関数 add-2 は 数字を一つ引数にとり、その数字に 2 を足して返します。先程のmapと組み合わせると

(map add-2 '(1 2 3)) ; (3 4 5)

となります。実際にGIMPのコンソールで試してみてください。
そしてこれを lambda を使って書くとどうなるかといいますと

(map
(lambda (n) (+ n 2))
'(1 2 3))

となります。 lambdaを使うことによって add-2 を使わずに記述できるようになりました。

(lambda (引数) 処理部分)

という構造です。この map と lambda の組み合わせは scheme では頻繁に登場します。
よく C や JAVA のプログラミングに慣れている人が while や if 文を使って記述している処理も
map, lambda を使えば簡潔にわかりやすく書けてしまうことも多々ありますので、どんどん使っていきましょう

let の使い方

次は let についての説明です

(let* ((basename (remove-extension
                  (car (gimp-drawable-get-name layer))))
       (filename (concat dir "/" basename ".pat")))

また難しいですね。解説するには長すぎるので、短いサンプルをひとつ

(let* ((foo 3)(bar 1)) (+ foo bar))

この処理では局所変数 foo に 3 を bar に 1 を代入しその合計を返しています。
scheme では変数を set! でも代入できますが推奨されていませんのでこのような処理になります。
[複数の画像からパターンを一括作成]のスクリプトでは局所変数 basename と filename に必要な情報を代入してるわけです。

長くなってきましたので今回はここまで。 あと1,2回で終わります

Leave a Reply