繰り返しで処理しよう

繰り返しはお手のもの

 順番に処理を実行するだけでなく、さまざまな道筋をたどって処理を実行する文を「制御文」と呼びます。
 制御文の1つとしては、条件分岐を行う「if〜then」を「インテリジェントでいこう」で紹介しました。
 今回は、もう1つの重要な制御文を紹介します。それが「繰り返し」です。

 AppleScriptの重要な役割の1つとして、単純作業の効率化があります。
 そして面倒な単純作業とは、つまるところ大量の繰り返し作業です。
 AppleScriptでは、制御文を使うことで面倒な繰り返し作業からユーザーを解放してくれます。

「repeat」を使った繰り返し

 繰り返し処理を行うには、repeat文を使います。
 repeat文には多くの記述方法がありますが、まずは同じ処理を決まった回数だけ繰り返すスクリプトを作ってみましょう。
 書式は次のようになります。

repeat 繰り返し回数 times
	繰り返したい処理
end repeat

 では、beep 5と同じ処理をrepeatを使って表現してみましょう。

repeat 5 times
	beep
end repeat

 repeat〜end repeatの部分をrepeatブロックと呼びます。
 tellブロックと同じように、構文確認後ブロック内部はインデント(右に少しずれて表示)されます。

足しながら繰り返し

 次に、変数の値を変化させながら処理を繰り返すスクリプトを試してみましょう。
 書式は次のようになります。

repeat with 変数 from 開始 to 終了
	繰り返したい処理
end repeat

 今度は、変数「i」の値が1つずつ増えていくスクリプトです。

repeat with i from 5 to 10
	display dialog i
end repeat

 また、1から100までの数字をすべて加算するスクリプトは次のようになります。

set n to 0
repeat with i from 1 to  100
	set n to n + i
end repeat
display dialog n

 このスクリプト中のrepeatの引数である100をさらに大きな値に変更してみましょう。
 変更後のスクリプトを実行することで、人間とは比較にならないほどの速さでAppleScriptが処理を行うことを実感できます。
 とは言え、足す数が多くなってくれば、単純な足し算の繰り返しよりも、積分した方が手っ取り早いですが。

リストを順に繰り返し

 さらに、「{ }」で囲んだリストの項目を、1つずつ取り出しながら処理を繰り返すスクリプトを紹介します。
 AppleScriptで非常によく使われる書式です。

repeat with 変数 in リスト
	繰り返したい処理
end repeat

 次のスクリプトを実行すると、変数の値をリストから順に1つずつ取り出していることがわかります。

set theList to {2, 3, 2, 1, 0, 4}
repeat with curItem in theList
	display dialog curItem
end repeat

 変数のcurItemは、「current item(現在の項目)」の省略です。
「current」はプログラムの世界では頻繁に使う単語で「cur」と省略することが多いので覚えておきましょう(注1)。
 もちろん、略さずに「currentItem」と書いても結構です。逆に、省略しすぎるのは良くありません。
「currentItem」の頭文字だけ取って「ci」などとすると、変数の意味がわからなくなる恐れがあります。
 ちなみに、変数を短く書いてもスクリプトの実行スピードは向上しません。

 次のスクリプトは、Finder上で選択した項目の拡張子を"txt"に変更します。

tell application "Finder"
	set theList to selection
	repeat with curItem in theList
		set name extension of curItem to "txt"
	end repeat
end tell

 このスクリプトは、ファイル属性を一度に設定する場合の常套手段でしょう。

条件を持った繰り返し

 これまでの方法では、処理の繰り返し回数をスクリプト中で決めていました。
 今度は、条件式に合致した場合に処理を繰り返すスクリプトを紹介します。書式は次の通りです。

repeat while 条件式
	繰り返したい処理
end repeat

 次のスクリプトを実行すると、4分の1の確率で終了します。

repeat while ((random number 3) > 0)
	display dialog "繰り返します"
end repeat

 repeat開始時に条件式が「false」の場合は、repeatブロックの中(repeat〜end repeat)は実行されません。
 ですから、次のスクリプトを実行しても警告音が鳴ることはありません。

repeat while false
	beep
end repeat

repeatの応用

 また、いつまででも繰り返すスクリプトも作成できます。

repeat
	繰り返したい処理
end repeat

 この場合、途中の処理でrepeatブロックを抜け出す文を入れておかないと繰り返し処理を止めることができずに、いわゆる「フリーズ状態」になります。
 アプリケーションなどがフリーズしてしまったときは[command + option + esc]キーで強制終了、もしくはリセットボタンなどで強制再起動を行う必要がありますが、AppleScriptの場合は[command + . ]キーでスクリプトを終了させることができます。
 また、このようなスクリプトを「永久ループ」と呼びます。

 では、repeatブロックを抜け出す文を記述してみましょう。
 if〜then文とexit repeat文を組み合わせて使います。

if 条件式 then exit repeat

 exit repeat文は、あらゆる書式のrepeatブロックで使えます。
 また、繰り返し処理を終了する条件は複数設定することも可能です。
 では2分の1の確率、もしくはダイアログで「いいえ」を選択した場合に処理を終了するスクリプトを作ってみましょう。

repeat
	set theBoolean to some item of {true, false}
	if theBoolean then exit repeat
	display dialog "繰り返します" buttons {"いいえ","はい"}
	if button returned of result = "いいえ" then exit repeat
end repeat

 このスクリプトでsome item of {true, false}の部分は、次のような参照形式になっています。

some クラス of コンテナ

 これは「任意要素参照形式」と呼ばれており、コンテナから要素をランダムに1つ取り出します。
 以前紹介したOSAX命令の1つであるrandom number命令を使うよりも高速に処理できるうえ、見た目もわかりやすい点が特徴です。
 ちなみに、「some クラス of コンテナ」の任意要素参照形式を、random number命令を使って書き換えると、次のようになります(「n」はコンテナに含まれる要素数)。

クラス (random number from 1 to n) of コンテナ

 また、「random number」などのOSAX命令は呼び出しに時間がかかるため、スクリプトの処理速度が低下する傾向にあることを覚えておきましょう。

多重の繰り返し

 repeat文を使って、二重三重に繰り返し処理を行うことも可能です。

repeat 各種
	繰り返したい処理
	repeat 各種
		繰り返したい処理
	end repeat
	繰り返したい処理
end repeat

 このように、ブロックの中にブロックがある状態を入れ子(nest)と言います。
 入れ子になった繰り返し処理は、表のように縦横の項目があるものや、テキストを行と文字で区別して処理する場合などに使います。
 次に紹介するスクリプトを実行したあとに、クリップボードのテキストをテキストエディタにペーストして保存しましょう。
 保存したファイルをWebブラウザで開くと、<teble>タグを使った10×10の表が出来上がっているはずです。

set thetable to "<html><head><title>自動で作った表<title></head><body><table border>" & return
repeat with v from 1 to 10
	set thetable to thetable & "<tr>"
	repeat with h from 1 to 10
		set thetable to thetable & "</td><td>" & v & "," & h
	end repeat
	set thetable to thetable & "</tr>" & return
end repeat
set thetable to thetable & "</table></body></html>"
set the clipboard to theTable

 ちなみに、スクリプト内で使っている「v」は「vertical(垂直方向)」、「h」は「horizontal(水平方向)」の略で、AppleScriptだけでなくプログラムでよく使われる変数です。

 繰り返し処理にはさまざまな書式が用意されていますが、すべてを覚える必要はありません。
 if文などを組み合わせれば、繰り返し作業の内容を簡単に書き換えることができるからです。
 同じ処理を行うプログラムもスクリプトの書き方は1つではありませんし、結果が同じならどれも「正しいスクリプト」と言えます。

 今回までで、プログラムに「最低限必要な」構文はすべて紹介したことになります。
 それらをまとめると、1)並んだスクリプトを順番に処理する「連続処理」、2)処理する道筋を変える「条件分岐」、3)何度も処理する「繰り返し」——の3つです。これがプログラムの基本であり、すべての処理をコントロールする基になります。
 どんなプログラム言語であっても、この3つの組み合わせでアプリケーションを作成します。

【今回のまとめ】

繰り返しは、

  • 省力化が可能

繰り返しの書式は、

  • 回数を指定する
  • 変数に回数を入れる
  • リストを順に取り出す
  • 条件を満たすまで繰り返す
  • ただひたすら実行する

repeat文は、

  • 「exit repeat」を使って終了できる
  • 二重三重に繰り返すことも可能