AppleScript & Adobe アプリケーションで高速リスト処理

#script object を使用したリスト処理

**AppleScript** は、リスト処理がとにかく遅いので有名です。
たとえば、以下のスクリプトは
1〜10,000をループさせて、一つずつ文字列に変換しつつリストに代入してゆくのですが、
とにかく実行してみてください。
***
<details><summary>**サンプルコード1**</summary><div>

```AppleScript:sample1
use scripting additions
use framework "Foundation"

set eDate to current application's NSDate's timeIntervalSinceReferenceDate()

set a to {}
repeat with i from 1 to 10000
	set end of a to i as string
end repeat

display alert ((((current application's NSDate's timeIntervalSinceReferenceDate()) - eDate) & "秒かかりました") as string)
```

</div></details>

私のMacBook Pro(os10.14.6／2.2GHz Intel Core i7)では
こうなりました。
![スクリーンショット0.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/500852/83989ade-e6db-2d4c-7696-62e904d5ba94.png)
いやいや…
こんなのに約1.4秒は遅いでしょ。

ということで、
リストを **script object** にしてみます。
***
<details><summary>**サンプルコード2**</summary><div>

```AppleScript:sample2
use scripting additions
use framework "Foundation"

set eDate to current application's NSDate's timeIntervalSinceReferenceDate()

script a
	property contents : {}
end script

set contents of a to {}

repeat with i from 1 to 10000
	set end of contents of a to i as string
end repeat

display alert ((((current application's NSDate's timeIntervalSinceReferenceDate()) - eDate) & "秒かかりました") as string)
```

</div></details>

結果は、
![スクリーンショット1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/500852/76f66d08-8cff-3f62-42c7-970092f2dd72.png)
1/10以下のスピードで処理できます。

単にリストを定義するのではなく、
**script object** の **property** を使用してリスト定義をすると、
なぜか高速化するのです。

これについては以下のサイトを参考にさせて頂きました。

* [AppleScript で高速データ処理](http://www.script-factory.net/monologue/FastDataOperation/index.xhtml "Script factory")

#では早速 Adobe アプリケーションに使ってみよう
こんなに速くなるのなら、と
**Illustrator** やら、 **InDesign** やら
大量にリストを使用する **script** に使ってみます。

以下は、**Illustrator** ドキュメント上の
全ての **text frame** をリストに代入しようとしています。

***
<details><summary>**サンプルコード3**</summary><div>

```AppleScript:sample3
script allText
	property contents : {}
end script

tell application "Adobe Illustrator"
	tell document 1
		set contents of allText to text frames
	end tell
end tell
```

</div></details>

これを実行すると、
![スクリーンショット2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/500852/4b76b7e7-45ed-0988-6ba2-69e1e3f7dccb.png)
エラーになってしまいます。

というのは、
**Adobe Illustrator** は、
「**contents**」という **property** を内部で使っているからです。
![スクリーンショット3.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/500852/5bedd52a-c2fa-002a-90cb-1a5ea2ba7fa7.png)
なんという意地悪！
#じゃ、結局使えないの？
そんなことはないです。

***
<details><summary>**サンプルコード4**</summary><div>

```AppleScript:sample4
script allText
	property record : {}
end script

tell application "Adobe Illustrator"
	tell document 1
		set record of allText to text frames
	end tell
end tell
```

</div></details>

「**contents**」を「**record**」に変えるだけで、
使用できるようになります。
![スクリーンショット3.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/500852/bf0ec617-9a73-10a7-93c6-f884de961b8f.png)
**Adobe Indesign** も同様に、
***
<details><summary>**サンプルコード5**</summary><div>

```AppleScript:sample5
script allPageItems
	property record : {}
end script

tell application "Adobe InDesign CC 2019"
	tell document 1
		set record of allPageItems to all page items
	end tell
end tell
```

</div></details>
![スクリーンショット4.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/500852/55fc0029-a7ad-d53e-15eb-dec4283b60b0.png)


なぜ「**record**」が使えるのか、
私にはよくわかりません。

わかりませんが、
これであなたの作った **script** も確実に高速化します。
#最後に注意点
リストの高速化で、
一点だけ注意して欲しいこと。

それは、**script obejct** に対して
「**count**」が使えなくなることです。
***
<details><summary>**サンプルコード6**</summary><div>

```AppleScript:sample6
script allPageItems
	property record : {}
end script

tell application "Adobe InDesign CC 2019"
	tell document 1
		set record of allPageItems to all page items
	end tell
end tell

repeat with i from 1 to count of record of allPageItems
	get item i of record of allPageItems
end repeat
```

</div></details>
これを実行するとエラーになります。
![スクリーンショット5.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/500852/e81020e6-e75c-ed19-d0ad-7d945796927f.png)
これの解決策は、
「**count**」を「**length**」に変えること。
***
<details><summary>**サンプルコード7**</summary><div>

```AppleScript:sample7
script allPageItems
	property record : {}
end script

tell application "Adobe InDesign CC 2019"
	tell document 1
		set record of allPageItems to all page items
	end tell
end tell

repeat with i from 1 to length of record of allPageItems
	get item i of record of allPageItems
end repeat
```

</div></details>
![スクリーンショット6.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/500852/e223f7af-08dd-b173-df66-b539db0399f1.png)

よしよし。

では皆様、今後ともよろしくお願いいたします。