たとえば、「set x to 2+3」は以下のようにも書けるわけですが、利用者定義命令の呼び出しによって、速度低下が起きます。
set x to add2(2,3)
on add2(n1,n2)
return n1+n2
end add2
一回の呼び出し程度ではたいした差はありませんが、これが100回1000回と大量になるとバカにできません。
つまり、呼び出しを含んだループを作るよりも、ループごとハンドラにする方が速度的には有利となります。時間のかかる処理をループの中に置かないのは、ループを作るときの鉄則でもあります。
次のスクリプトでは4回呼び出しがおきて、効率が良くありません。
set sumOfList to 0
repeat with curItem in {1,2,3,4}
set sumOfList to add2(sumOfList,curItem)
end repeat
sumOfList -- 加算の結果
on add2(sumOfList,curItem)
return sumOfList+curItem
end add2
次のスクリプトでは、利用者定義命令の呼び出し回数が1回だけですから、断然速く処理できるというわけです。
sumList({1,2,3,4})
on sumList(theList)
set sumOfList to 0
repeat with curItem in theList
set sumOfList to sumOfList+curItem
end repeat
return sumOfList
end sumList
また、呼び出しで渡す変数をできるだけ少なくするなども、場合によっては効果があります。
かといって、ハンドラをできるだけ作らずに済ませてしまうのは感心できる方法ではありません。
というのも、スクリプトの見通しが悪くなる、保守管理が難しくなる、スクリプトの再利用が難しくなる、バグの発見が難しくなる、等などなど、ハンドラを使わないスクリプトの欠点は枚挙に暇がありません。
ハンドラを使わない事よりも「適切にハンドラを使う」ことを心掛け、分かりやすいスクリプトを書くようにしましょう。
利用者定義命令の引数は、ハンドラの中ではどのように扱われるのかもきちんと理解しておきましょう。
set x to 1
a(x)
b(x)
x
on a(handlerX)
set handlerX to 10
end a
on b(x)
set x to 10
end b
結果を見てみると変数xの値は、ハンドラの中で変えても変化ありません。
このように、ハンドラの中だけで使われる変数を「局所変数」と言います。
特に指定しない場合は、変数は「局所変数」となります。
利用者定義命令を実行するには、現在のスクリプトに向けてメッセージを送る必要があります。
特にメッセージの送り先をtellで指定しない限り、メッセージは現在のスクリプトオブジェクトに向かって送られるので気にする必要は無いのですが、tellブロック内では、必ず現在のスクリプトオブジェクトを指定する必要があります。
具体的には、命令の前にmyをつけます。これはmeの所有格ですから、命令の後にof meをつける形でも構いません。
meは、現在のスクリプトオブジェクトを示すシステム変数です。
tell application "Finder"
my x() -- myを付けないとエラー
end tell
on x()
end x
このあたりがハンドラの持っている基本的な性質です。
色々とおもしろい使い方ができるので、基本をしっかり押さえておくと混乱せずにすむでしょう。