このページは福井県立大学の田中求之が2006年1月まで運用していた Mac のサーバ運用に関する会議室 「Web Scripter's Meeting」の記録です。情報が古くなっている可能性がありますのでご注意ください。

リストを作るとき

発言者:猫の手
( Date Saturday, June 28, 1997 08:00:57 )


--script 1---
set b to {}
repeat 5 times
  set a to {}
  repeat 5 times
    set end of a to 0
  end repeat
  set end of b to a as list
end repeat
set item 1 of item 1 of b to 1
--
 としていたんですが、内側のループを外に出した方が
速く実行出来るかなと思って、下のスクリプトを書いた
のですが、実行結果が異なります。
 これは、アップルスクリプトの仕様でしょうか。それと、
script2のような書き方で、script1の結果を得るような
スクリプトを書くには、どう工夫すればいいのでしょうか。
--script 2---
set a to {}
repeat 5 times
  set end of a to 0
end repeat
set b to {}
repeat 5 times
  set end of b to a
end repeat
set item 1 of item 1 of b to 1
--

田中求之 さんからのコメント
( Saturday, June 28, 1997 14:42:17 )

> これは、アップルスクリプトの仕様でしょうか。

そうです。なぜだかわかりますか? ここのところを理解していないと、スクリプトを
書くとき、特にリストを扱うときに、思い通りに行かなくて悩むことになります。

>script2のような書き方で、script1の結果を得るような
>スクリプトを書くには、どう工夫すればいいのでしょうか。

以下のように、set ではなく copy を使います

set a to {}
repeat 5 times
  set end of a to 0
end repeat
set b to {}
repeat 5 times
  copy a to end of b
end repeat
set item 1 of (item 1 of b) to 1


田中求之 さんからのコメント
( Saturday, June 28, 1997 14:47:45 )

ようは copy と set の違いがポイントです。以下の二つのスクリプトの実行結果
を見てもらえば、違いがわかると思います。

=== set end of b to a の場合

set a to {}
repeat 5 times
  set end of a to 0
end repeat
set b to {}
repeat 5 times
  set end of b to a
end repeat

set item 3 of a to 5  --- ここに注目
b


=== copy a to end of b の場合

set a to {}
repeat 5 times
  set end of a to 0
end repeat
set b to {}
repeat 5 times
  copy a to end of b
end repeat

set item 3 of a to 5
b

smart さんからのコメント
( Saturday, June 28, 1997 20:45:52 )

script2では、aは1度定義しているだけなので、この結果は納得できると思います。
script1ですが、aを5回定義しているので、この結果も不思議はないと思います。
仮に、以下の様にaの定義を変えると良く分かると思います。

【Script】
set counter to 0
set b to {}
repeat 5 times
  set a to {}
  repeat 5 times
    set end of a to counter
  end repeat
  set counter to counter + 1
  set end of b to a as list
end repeat
set item 1 of item 1 of b to 1
b
--結果--
--{{1,0,0,0,0},{1,1,1,1,1},{2,2,2,2,2},{3,3,3,3,3},{4,4,4,4,4}}

猫の手 さんからのコメント
( Monday, June 30, 1997 00:09:03 )

田中さん、smartさん、コメント有り難うございます。
なるほど、ここに違いが出てくるのですね。
set と copyと。
何気なく使ってましたが、今まで、エラーが出てない
出ていても気がついていないのが、幸いです。

田中求之 さんからのコメント
( Monday, June 30, 1997 01:44:55 )

>なるほど、ここに違いが出てくるのですね。

そうなんですよ。set と copy とが同じものだと思っていると、こういうときに
痛い目に合うわけです。

set end of b to a

の場合、リスト b の各 item は、リスト a へのリファレンスが収まります。
ですから、a のアイテムの値を変更すると、リスト b の各アイテムの値もすべて
変わってしまう(それぞれが a をさしているのだから当たり前ですが)わけです。
また、リスト b のあるアイテムに対して操作を加えると、それは a を操作する
ことになりますので、結果として b の全アイテムの値が一斉に変わったように
なります。

一方の

copy a to end of b

は、a と同じ値のリストのコピーが作られて、それがリスト b の各アイテムに
収まっていきます。リファレンスではなく、実体が収まりますので、a の値が
変化しようが、あるいは同じ b の中のほかのアイテムの値を変更しようが関係
ないわけです。