変数は値を入れる袋

変数ってなんだ?

 コンピューターを使って計算を行う場合、対象になるデータを値(Value)と言います。
 具体的には、数値/文字列/日付/真偽値/参照——などのことです。
 これらの値は「Macも計算機なんだし」で説明したとおり、演算子を使ったさまざまな計算が可能です。

 そして、この値を中に入れた袋を変数(Variable)と呼びます。
 文字どおり、中に入っている値が変化することが特徴です。
 実は、変数は今回初めて使うものではなく、その1つである「result」を前回までも使ってきました。
 ただし、resultは直前に実行した命令や計算結果が入っている特殊な変数です。
 一般的な変数とは少し異なる性質を持ちますが、とりあえずresultの延長として変数を使っていけば理解しやすいでしょう。

 変数で数学を挫折してしまった方もいるんじゃないかと思いますが、普段の生活で使わないために理解しづらいだけで、それほど難しいものではありません。
 袋に入れてものを持ち運ぶと便利、という程度の理屈です。
 これから、スクリプトを作っていくうちに自然と理解できるようになるでしょう。

 変数を理解すれば、高度なスクリプトを作ることもできるようになりますが、まずは気楽な気持ちで、まねから始めてみるといいでしょう。

変数は規則のある名前にしよう

 では、変数の使い方に関する最初の一歩を踏み出してみましょう。
 まず、変数の名前にはアルファベットや数字、「_(アンダースコア)」以外は使えません。
 また、名前は数字以外で始める必要があります。
 さらに、命令やオブジェクト、属性ですでに使ってある名前は命名できません。

 変数として使えるかどうかを見分けるには、エディタで「コンパイル(構文確認)」を行います。
 そこで、[AppleScript書式]にある[利用者定義の名前]で設定した書式に変換されたら変数として使用できます。
 変数名には、アルファベットの大文字と小文字を使えますが、AppleScriptは大文字と小文字の区別を行いません。
 つまり、「apple」と「Apple」「APPLE」は同じ変数になります。

 2つの単語をスペースを入れずに組み合わせた名前は、基本的に命令やオブジェクト、属性では使いません。
 裏を返せば、変数の名前に使いやすいと言えます。
 本書では区切りとなる単語の頭を大文字にします。
 例えば「theName」という具合です。
 また、「the_name」のようにスペースの代わりにアンダースコアを使うのも一般的な変数名の付け方です。

 変数名はどんな意味を持ったものかが分かる名前にしましょう。
 適当に付けていると、自分で書いたスクリプトの意味が分らなくなってしまいます。
 変数の意味に合った名前が思い浮かばないからといって、意味もなく好きな食べ物やアイドルの名前を付けると、後でスクリプトが読めなくなって必ず後悔します。
 変数名はアルファベットを使うので、和英辞書を用意しておけば便利です。
 英単語の勉強にもなるので一石二鳥でしょう。

 変数名を付ける作業は簡単に思えますが、あれこれ考えていると案外いい名前が思い浮かばないものです。
 そこで、最初から規則性を持たせてやると命名が楽です。

 本書では基本的に、1)「theFile」のように値の種類にtheを付ける、2)「nameOfFolder」のように文をそのまま使う——の2種類の命名方法を採ります。
 1)の場合、100文字を超えるようなると(作る事はできますが)さすがに変数名としては長すぎますが、ある程度長い名前を付けておけば、重複することもありませんし意味も把握しやすくなります。
 20文字程度だったら、面倒がらずに使ったほうが結果的に楽になると思います。
 一度書いてしまえば、コピー&ペーストすればいい(注1)のですから、たいした手間ではないですね。

 また、すぐに不要になる変数は、c/i/n/x——などのアルファベットの1文字を使います。
 一般的に使われている変数名は「識別子の中の略語」 を、命名法についてさらに詳しくは「変数の命名方法」を参照して下さい。

setで代入しよう

 変数を使うには、まずAppleScript命令の「set」で値を代入します。
 スクリプトの書き方は、属性を設定する場合とまったく同じで「to」を使います。

set x to 10

 では、「x」が変数で数値の10を代入しています。
 変数はいくつでも同時に使え、値と同じように計算に使用できます。

set x to 100  -- xに100を代入
set y to x + 50  -- yに100+50を代入
x + y
	--> 250

 結果ウィンドウを見ると、「x」と「y」のそれぞれの中身が足されていることが分かります。

「result」は直後に使わないと内容が変わってしまいますが、変数はスクリプトで入れ替えるまでは同じ値を保存しています。
 また、同じ変数に何度でも値を代入できます。
 当然の話ですが、1つの変数に重ねて値を代入すると最初に代入した変数の値は失われます。

良くある使い方

 最初に変数に値を入れる際にコメントを添えておけば、スクリプトを修正するときに便利です。
 通常、スクリプトでは最初に変数を設定するので、スクリプトの内容が分からなくても変数に代入している値を変えるだけで、簡単に改造して利用することができます。
 次のような例を考えてみましょう。

set theComment to "コメント" -- サイトのコメント

tell application "Finder"
	set comment of folder "Sites" of home to theComment
end tell

 homeのSitesフォルダのコメントが変わります。
 最初にあるset theComment to "コメント""コメント"の部分に別の値を代入すれば、異なるコメントを設定できます。
 この程度の短さならば、あまり意味が無いように見えますが、スクリプトが長くなり何度も同じ値が登場するようになると、修正が容易になり効果的です。

 では、他にも良くある使い方を紹介しましょう。
 次のスクリプトを見て下さい。

set x to 2
set x to x+1  --xに2+1を代入

 このスクリプトは、一見奇妙な記述に感じますが、まず「x+1」を計算してその結果を「x」に代入するという順番で処理されますから、エラーは発生しません。
 AppleScript は、まず「to」に続く式を計算して、その結果を「set」に続く変数に代入します。つまり、「set x to x+1」を細かく分けると次のように書けます。

x+1
set x to result

 代入元と代入先に同じ変数を使う手法は頻繁に出てきますので、覚えておきましょう。
 実際、既に「オブジェクトと属性」でも属性に対して同じようなことをしていますね。

リストってなんだ

 Finder上でファイルをいくつか選択して、次のスクリプトを実行してみましょう(注1)。

tell application "Finder"
	selection
end tell

 ここで、結果ウィンドウに表示されている値をリスト(list)と呼びます。書式は次の通り。

{値, 値, ..., 値}

 リストは、値を串のようにつなげて1つの値にまとめたもので、似た値をまとめて扱いたいときに重宝します。
 1つのリスト中に数値と文字列など、異なる種類の値を混在させて使えます。

 また、通常は1つしか値が代入できない変数にも、リストを使えば複数の値を代入できます。
 ちなみに、リストに含める値は1つでもいいですし、値を代入しなくても構いません。
 例えば、次のように値が入っていないリストを「空リスト」と呼びます。

{}  -- 空リスト

リスト項目を使う

 リスト中のそれぞれの値は、並んでいる番号で指定できます。
 番号は左から1で始まりますので、次のように書けばリスト中の値を取得できます。

item 整数 of リスト

 要するに、リストはオブジェクトの番号指定と同じ方法を使うわけです。
 例えば、値を読み出すには次のように書きます。

item 3 of {1, 2, 3}

 リストの一部に値を代入する場合は、次のように書きます。

set theList to {true,false}
set item 2 of theList to true
theList
	--> {true, true}

 リストの中にはあらゆる値が格納できるので、当然リストの中にリストを入れることも可能です。

{1, {2, 3, 4}, 5}

 ここではリストが二重になっていますが、さらに三重四重と幾重にもリスト内にリストを含められます。
 また、リストの中にある値はitem n ofという形を重ねることで指定できます。

item 2 of item 1 of {{1, 2}, 3, 4}
	--> 2

 このスクリプトでは、右から順に処理されます。
 カッコをつけて処理の順番を分かりやすくすると、次のように書けます。
 同じ処理をするスクリプトなので、もちろん結果は変わりません。

item 2 of (item 1 of {{1, 2}, 3, 4})
	--> 2

 また「result」を使って分割して書くと、次のようにも表現できます。

{{1, 2}, 3, 4}
item 1 of result
item 2 of result
	--> 2

 もちろん、幾重にもなったリスト中の値も書き換えられます。

set theList to {{1, 2}, 3, 4}
set item 2 of item 1 of theList to 5
theList
	--> {{1, 5}, 3, 4}

asで値の変換

 これまでas演算子は「miles」などの単位付きの数値を、別の単位の数値に変換する場合にしか使いませんでした。
 しかし、このほかにも「as」演算子は数値を文字列に変換するなど、別の種類の値への変換に使えます。

 まずは、文字列を数値に変換してみます。

"10.0" as number
	--> 10.0

 数値を文字列に変換することもできます。

10 as string
	--> "10"

 数字を文字列に変換するスクリプトは簡単に記述できますが、そのほかの値に変換する場合の法則は少し複雑になります。
 値の変換が必要な場合は、「値の変換表」を参考にしてください。

 リストのそれぞれの値が文字列や数値などの場合は、リスト中のすべての値を文字列に変換できます。

{"R", 2, "D", 2} as string
	--> "R2D2"

さらにリストを極める

 また、リストは文字列と同様に「&」を使って結合できます。

{4, 5, 6} & 7
	--> {4, 5, 6, 7}

 ただし、「&」の左が文字列の場合は結合した値は文字列となります。

"3" & {4, "Go!"}
	--> "34Go!"

 このときリスト中の値は文字列に変換できなければいけません。

 また、リストとして値を結合したい場合は、「{ }」で文字列を囲う方法が一つ。

{"a"} & {"b", 3}
	--> {"a", "b", 3}

 そしてもう一つ、as演算子を使って文字列をリストに変換してから結合する方法があります。

("a" as list) & {"b", 3}
	--> {"a", "b", 3}

 また、リストには「=」と「/=」の2つの比較演算子を使えます。

{1, 2} = {2, 1}
	--> false

 リスト内で数値や文字列の順番が異なる場合は別の値となりますので、この演算結果は「false」です。
 また、「contains」などの包含演算子も使用可能です。

{"A", "O", "R"} contains "R"
	--> true

 リスト中の値には命令や式を含められます。

set x to 2
{"a", current date, 10 + x}
	--> {"a", date "2002年 10月 10日 木曜日 8:24:27 PM", 12}

 リスト中にある命令や式は、その場で実行されてリスト中に格納されます。
 ここでは、「current date」という命令や「10+x」という式がリストの値になるわけではなく、実行の結果である「date "2001年 7月 29日 日曜日 13:32:57"」や「12」などの値を代入するという意味になります。

レコードって何だ

 レコードを説明する前に、まずは次のスクリプトを実行してください(注1)。

display dialog "" default answer ""

 現れたダイアログで[OK]ボタンを押せば、結果ウィンドウには次のように表示されます。

{text returned:"", button returned:"OK"}

 この値がレコード(record)で、書式は次の通りです。

{属性名:値,属性名:値,...,属性名:値}

 レコードは属性を持つ値で、オブジェクトと同様に属性の読み書きを行えます。

 レコードでは、値を入れた順番に関係なく名前を使って取り出せるため、リストに比べて値の意味を把握しやすい点が特徴です。
 含まれる値の1つ1つにラベルを張り付けるようにして区別しているので、レコードの属性名はラベル(label)とも言われます。
 属性名の付け方は変数と同じです。

 レコードの値を取り出す場合の書式は次の通り。

属性 of レコード

 これはオブジェクトの属性を指定する方法とまったく同じです。
 例えば、値の読み出しは次のように書きます。

a of {a:10, b:0, c:2}
	--> 10

 レコード中の値の1つを書き換える場合も、属性と同様に書きます。

set theRecord to {a:10, b:0, c:2}
set c of theRecord to 120
theRecord
	--> {a:10, b:0, c:120}

レコードを使う

 as演算子では、レコードはリストにしか変換できません。

{list1:10, list2:""} as list
	--> {10, ""}

 また、「&」による結合はレコード同士でしか行えません。

{a:1, b:2, c:3} & {d:4, e:5, c:6}
	--> {a:1, b:2, c:3, d:4, e:5}

 このように、結合した場合に同じラベルが存在していると「&」の右側の値は無視されて、左側の値が残ります。
 また、リストと同様にレコードも、「=」「/=」の2つの比較演算子を使えます。

{a:1, b:2} = {b:2, a:1}
	--> true

 レコードでは、カッコ内の順番は関係なく、同じラベルの値同士が比べられます。
 ですから、このスクリプトの演算結果は「true」となります。

 そのほかに、順番に関係する「start with」などを除いて「contains」のような包含演算子も使用できます。
 ただし、演算子の両辺がともにレコードでなければいけません。

{a:17} is in {x:15, y:16, z:17}
	--> false

 この場合の包含演算では、ラベルと値が一致する必要があるので、このスクリプトの結果は「false」となります。
 リストと同様にレコードにも命令や式を含められます。

 また、レコード中にレコード、リスト中にレコード、レコード中にリスト——を含めることも可能です。
 値の指定方法はリストと同様に右から「属性 of」で連結していきます。もちろん、値の書き換えも可能です。

S of T of {K:{G:3, T:3}, T:{S:5}}
	--> 5

【今回のまとめ】

変数は、

  • 値を入れておく袋
  • setで代入して値を取り換える

変数の名前は、

  • アルファベットと数字で付ける
  • 法則性を持たせよう

値をまとめて使う場合は、

  • 値を串刺しにした値がリスト
  • 属性のある値がレコード