#ハンドラのデータ受け渡し
構造化プログラミングを行なう上で、
サブルーチン(ハンドラ)は
プログラムの見通しを良くするために必要だと言われます。
ところが、AppleScript はハンドラでのデータ受け渡しがとても遅く、
繰り返しハンドラを呼び出すとさらに遅くなります。
それはそれで、実行速度は工夫次第で何とかするもの、
と思い込んでましたが、それにしても遅いです。
本当は、工夫よりも知識と探求心なんじゃないか、
と思います。
以下は、
(1)1〜10,000をループさせて、
(2)ループ変数をハンドラへ渡し、
(3)ハンドラでループ変数を文字列化してリストに追加、
(4)ハンドラからリストを戻す。
というスクリプトです。
**サンプルコード1**
use framework "Foundation"
use scripting additions
set eDate to current application's NSDate's timeIntervalSinceReferenceDate()
property theResult : {}
set theResult to {}
repeat with i from 1 to 10000
set theResult to my theLoop(i)
end repeat
display alert ((((current application's NSDate's timeIntervalSinceReferenceDate()) - eDate) & "秒かかりました") as string)
----------------------------------※Script Librariesハンドラを想定
on theLoop(i)
set end of theResult to i as string
return theResult
end theLoop
私のMacBook Pro(os10.14.6/2.2GHz Intel Core i7)では
こうなりました。
そりゃそうです。
「こんなループ、ハンドラの中でやらなきゃ遅いに決まってんだろ!」
と先輩から怒られる代物です。
#script object を使用したハンドラ処理
そこで試して頂きたいのが、
以前投稿した、 [script object を使用した高速化処理] (https://qiita.com/ginn_nezz/items/b7b1ad86f61d47bdf10d) です。
repeat 文のループ変数、及びリスト変数を script object として設定、
script object 自体を引数と戻り値にしています。
**サンプルコード2**
use framework "Foundation"
use scripting additions
set eDate to current application's NSDate's timeIntervalSinceReferenceDate()
script theIterator
property record : 0
end script
script theResult
property record : {}
end script
set record of theIterator to 0
set record of theResult to {}
repeat with i from 1 to 10000
set record of theIterator to i
set theResult to my theLoop(theIterator)
end repeat
display alert ((((current application's NSDate's timeIntervalSinceReferenceDate()) - eDate) & "秒かかりました") as string)
----------------------------------※Script Librariesハンドラを想定
on theLoop(theIterator)
set end of record of theResult to record of theIterator as string
return theResult
end theLoop
またもや1/10以下!
どうも AppleScript は変数の処理に負荷が掛かっており、
プログラムの中で使う変数を全て script object にすることで
なぜか負荷が軽減されるようです。
特にハンドラのデータ受け渡しを
script object にしてしまうことがポイント。
デメリットとしては
センテンスがかなり冗長になってしまうので
プログラムの見通しが悪くなりそうですが、
Cocoa フレームワーク呼び出しも相当なものなので、
要は「慣れ」だと思います。
ぜひお試しください。