クロージャがなにかってことはイマイチよく分かっていないのだけど。
Python クックブック 第2版を読んでいて、載っていたスクリプトを AppleScript で書き直したら、動いたって話なんだけど。JavaScript ほど多彩なことができるわけではないのだけど。
まぁ、どこでどのように使うのかというギモンは残るんだけどね。
AppleScript の場合、関数(ハンドラ)の中に関数(ハンドラ)は作れない。これはご存知だと思います。しかし、スクリプトオブジェクトなら作ることができます。
on makeObject(i)
script MyObject
property counter : i
on countUp()
set counter to counter + 1
end countUp
on getCounter()
my counter
end getCounter
on run
countUp()
end run
end script
end makeObject
set theObject to makeObject(0)
tell theObject
run
display dialog getCounter()
run
display dialog getCounter()
end tell
単純な例ですが、実行するたびにカウントを行うスクリプトオブジェクトです。makeObject ハンドラ実行時に引数を渡し、それが MyObject の属性に初期値として設定されています。これはこれで特に問題はないのですが、MyObject の属性 counter は書き換え可能です。
tell theObject
run
display dialog getCounter() -- 1
run
display dialog getCounter() -- 2
set counter of it to 100 -- 値を書き換えてみる
run
display dialog getCounter() -- 101
end tell
スクリプトオブジェクトの属性は読み書き可能。これは、AppleScript では当たり前のことですね。では、次のように書き換えてみましょう。
on makeObject()
set counter to 0
script MyObject
on countUp()
set counter to counter + 1
end countUp
on getCounter()
return counter
end getCounter
on run
countUp()
end run
end script
end makeObject
set theObject to makeObject()
tell theObject
run
display dialog getCounter() -- 1
run
display dialog getCounter() -- 2
try
set counter of it to 100 -- 値を書き換えてみる
on error msg number num
error number num
end try
run
display dialog getCounter() -- 3
end tell
makeObject ハンドラ実行時の引数をなくし、MyObject の属性 counter を makeObject ハンドラ内のローカル変数にしてみました。ハンドラ実行時のローカル変数がハンドラ実行後も保持され、スクリプトオブジェクト内から参照可能です。が、スクリプトオブジェクトの外から counter の値を変更することも参照することもできません。
もう少し分かりやすく書くと以下のようになります。
on DataObject(theKey, value)
script
on getKey()
return theKey
end getKey
on getValue()
return value
end getValue
end script
end DataObject
set theData to DataObject("id", "someone")
theData's getKey() -- "id"
theData's getValue() -- "someone"
変数 value や theKey にアクセスするにはハンドラを利用する以外ありません。もちろん、グローバル変数を利用すると話は別ですが(または、スクリプトオブジェクト内に setter を用意するとか)。
と、にハンドラ内のローカル変数が保持されることは分かったのですが、これがクロージャなのかといわれるとよくわからなかったりする。以下のようにしておけば、スクリプトオブジェクトの初期化処理を複数回呼び出すことを防いだりできるかな?
on makeObject()
set instance to missing value
script MyObject
on init()
if instance is missing value then
(* ここに初期化処理 *)
-- ハンドラのローカル変数に自身を割り当てる
set instance to me
else
-- 初期化されてるよ
display dialog "Initialize OK"
end if
end init
on greeting()
display dialog "Hello"
end greeting
end script
init() of MyObject
return instance
end makeObject
set x to makeObject()
init() of x
greeting() of x
init ハンドラ自体を呼び出せないようにしたいけど、そこまで求めるのは無理があったりなかったり。
0 件のコメント :
コメントを投稿