メインコンテンツまでスキップ
バージョン:23.5

コンテナへの参照

ほとんどの場合、スクリプト内のコンテナは、スクリプト内で直接変数名(または他のコンテナ識別子)を指定することで、コンテナに直接値を格納したり、コンテナから値を読み出したりすることで使用されます。しかし、時々、コンテナへの参照を格納することが非常に有用になることがあります。これを使って、後でそのコンテナの値にアクセスすることができます。参照はコンテナの値ではなく、コンテナのアイデンティティを保持しており、参照にアクセスすると、それが参照しているコンテナの内容を読み出したり書き込んだりします。

参照の特性

参照には、それらを使って作業を行う際に認識しておきたいいくつかの特性があります。参照がどのように動作するかを理解するための第一歩として、次の単純な変数への参照を使用した例を考えてみてください:

put 32 into age -- Ageは現在、値32を含む変数です
put a reference to age into yearsOnThePlanet -- 参照を格納する
put yearsOnThePlanet -- 32 (yearsOnThePlanetはageの値を参照します)
add 1 to age -- Ageは現在33です
put yearsOnThePlanet -- 33を出力する (参照は動的です)

上記の最初の行では、単純な値(32)が普通の変数(age)に割り当てられます。次の行では、変数ageへの参照を変数yearsOnThePlanetに格納します。これにより、yearsOnThePlanet変数の値への任意のアクセスは、実際にはスクリプトの次の行で示されているように、age変数の値にアクセスすることになります。スクリプトの最後の2行では、age変数の値を増やし、yearsOnThePlanet変数が更新された値にアクセスすることを示しています。

参照は強く結びつく

参照によって確立される接続は"スティッキー"(上記の例ではyearsOnThePlanetageにしっかりと接着されています)なので、割り当ては他の方向でも動作します - どちらの値を変更しても、両方の値が変わります:

put 29 into yearsOnThePlanet
put age -- 29を出力します

参照構文

参照は、containerreferencereference to、または refer to という単語を使用するか、コンテナの前に短縮記号 @ を使用して行うことができます。または、コンテナの後に by reference または as reference を使用します。次のすべては同等です。...

put container thing into watcher
set watcher to be a reference to thing
put @thing into watcher
set watcher to reference thing
set watcher to refer to thing
set watcher to thing by reference
set watcher to thing as a reference

構文:
コンテナ aContainer
{a} reference {to} aContainer
refer to aContainer
@ aContainer
aContainer [by | as {a}] reference

参照はリストまたはプロパティリストに格納できます

参照は、これまでの例で示したように変数に格納するだけでなく、リストのアイテムとして、またはオブジェクトまたはプロパティリストのプロパティとして格納することもできます。この場合、参照である特定のアイテムまたはプロパティにアクセスすると、それが参照しているコンテナにアクセスします。次の例で示しています:

put 13 into luckyNumber
put ["horseshoe", container luckyNumber, "penny"] into charms
put charms -- [horseshoe, 13, penny]
put 7 into item 2 of charms
put charms -- [horseshoe, 7, penny]
put luckyNumber -- 7

参照はプロパティ、ファイル、チャンクを指すことができます

参照は、変数だけでなく、任意の種類のコンテナを参照することができます。これには、このセクションの前半部分で説明したすべての異なる種類のコンテナが含まれ、プロパティ、ファイル、さらには任意のコンテナのチャンクを含みます:

set highScore to reference item 2 of line 3 of file "/tmp/stats"
put @ item 2 delimited by "." of the numberFormat into decimalFormat

参照は動的です

オブジェクトのプロパティやコンテナのチャンク(reference to word 3 of sentenceのような)への参照が作成されると、その参照は使用されるたびに動的に評価されます。これは、sentenceの内容が変更された場合でも、参照は常に新しい内容の3番目の単語にアクセスすることを意味します。

参照は"感染性"がありません

SenseTalkの代入は、明示的に参照が示されていない限り、常に値によって行われます。したがって、参照を含む変数を別の変数に代入すると、別の参照は作成されず、ソースコンテナの現在の値のコピーだけが作成されます。別の参照を作成するには、代入時に明確に参照を指定する必要があります(参照への参照を指定すると、同じソースへの2つ目の参照が作成されます)。

put 123 into source
put a reference to source into ref -- 123 (ref is a reference)
put ref into number -- 123 (number is NOT a reference)
put @ref into ref2 -- 123 (ref2 is now another reference to source)
put 456 into source
put ref -- 456
put number -- 123
put ref2 -- 456

参照は再割り当て可能です

すでに参照を含む変数に参照を格納すると、その変数は新しい参照に単純に再割り当てされます。以前参照していた変数の値は変わりません:

put [123, 456] into [source1, source2]
put a reference to source1 into ref
put ref -- 123
put a reference to source2 into ref -- Ref is now reassigned
put 789 into ref -- Source1 is unaffected
put [source1, source2] -- [123, 789]

元の参照変数を再割り当てするのではなく、参照していたコンテナを参照に変更するには、container referred toを使用して明示的に要求することができます:

put @source1 into the container referred to by ref -- Ref still refers to source2, which now becomes a reference to source1
put "We're Twins" into ref -- Assign to ultimate container
put [source1, source2] -- [We're Twins,We're Twins]

参照による削除

deleteコマンドを使用してチャンクやプロパティへの参照を削除すると、参照しているチャンクやプロパティが削除されます(これは参照を含む変数を削除するのとは異なることに注意してください - 下記参照)。

put [1,3,5,7,9,11,13] into odds
set num to refer to item 5 of odds
put num -- 9 (num refers to item 5)
delete num
put odds -- [1,3,5,7,11,13]
put num -- 11 (num now refers to the new item 5)

参照は持続的です

変数が一度参照になると、それは別の参照に再割り当てされるか、または参照自体が削除されるまで、それが参照するコンテナに結びついたままです。単にそれに空を入れることで参照変数を他の用途のために解放できると思うかもしれませんが、これは単にそれが参照するコンテナに空を入れるだけです! 変数を他の目的のために使用するためには、最初に delete variable コマンド( delete コマンドではない - 上記参照)を使用して削除する必要があります。参照がリストのアイテムやオブジェクトのプロパティとして保存されている場合、そのアイテムやプロパティを削除できます。

put "green" into source
set localColor to refer to source
set localColor to "yellow"
put source -- "yellow"
delete variable localColor -- LocalColor is now undefined (no longer a reference)
set localColor to "blue" -- assigns its own value
put source -- "yellow"

参照が明示的に削除されずに普通の変数になる2つの特殊なケースがあります。特殊な変数 it の値を暗黙的に設定するコマンド(All About "it"のリスト参照)は、新しい値を割り当てる前に it に格納された任意の参照を最初に切断します。また、repeat構造が現在参照であるループ変数を指定する場合、その参照は変数がrepeatで使用される前にクリアされます。

参照の使用

参照はスクリプトの多くの場面で使用することができます。ここでは、最も一般的な使用法のいくつかを紹介します。

参照によるパラメータの渡し

参照の一般的な使用法の一つは、他のハンドラに参照をパラメータとして渡すことです。参照を渡すことにより、呼び出されたハンドラはローカルハンドラ内の値を変更することができます。以下に例を示します:

put "candy" into tastyFood
pluralize @tastyFood -- Pass by reference
put tastyFood

to pluralize aWord
if aWord ends with "y" then put "ies" into last char of aWord
else put "s" after aWord
end pluralize

上のスクリプトを実行すると、"candies"が表示されます。tastyFoodという変数は初期ハンドラからpluralizeハンドラに参照として渡されます。これが参照であるため、aWordがpluralizeハンドラによって変更されると、実際には初期ハンドラのtastyFood変数の値が変更されます。

参照の戻り / 関数結果をコンテナとして使用する

他のハンドラに参照を渡すと、そのハンドラは参照が指すコンテナの内容を変更する能力を得るのと同じように、関数が呼び出し元がその後変更できるコンテナへの参照を返すことが有用なことがあります。たとえば、関数はグローバル変数や関数によって選択されたファイル、あるいはそのようなコンテナのチャンクへの参照を返すかもしれません。これを行うためには、2つのことが起こらなければなりません。第一に、呼び出される関数は参照を返さなければなりません。第二に、呼び出し側のハンドラは、戻り値をコンテナとして使用したいと指示しなければなりません(デフォルトでは、関数の戻り値は常に値として扱われます)。

例として、どちらのリストが少ないアイテムを持っているかによって、2つのリストのいずれかに値を挿入したいとします(より現実的な例では、複数のリストが関与するかもしれません)。以下に、このアイデアを実装するスクリプトを示します。このスクリプトでは、適切なリストを選択するための関数を使用しています:

put "a,b,c,d,e,f" into firstBox
put "9,8,7,6" into secondBox
put ",Here" after container chooseContainer(@firstBox, @secondBox)
put firstBox -- "a,b,c,d,e,f"
put secondBox -- "9,8,7,6,Here"

to chooseContainer @c1, @c2
if the number of items in c1 < number of items in c2
then return container c1
else return container c2
end chooseContainer

この例では、多くの参照があります。関数呼び出しの戻り値をコンテナとして扱うようにSenseTalkに指示するために、chooseContainer()の前に"container"(または"@"または"reference")が必要です。この例を動作させるためには、パラメータも参照として渡されなければなりません(@firstBox, @secondBox)これは、それらが呼び出しスクリプトから来るからです。そしてもちろん、選択されたコンテナは参照として返されなければなりません。結果として、任意の2つのコンテナへの参照を受け入れ、アイテムが少ないコンテナへの参照を返す関数が得られます。関数の入力パラメータを参照としてマークする(@c1, @c2)はオプションであり、現在のSenseTalkのバージョンでは機能的な意味はありませんが、chooseContainer関数のユーザに、パラメータは参照として渡されるべきであることを思い出させるのに役立ちます。

値が参照であるかどうかを判断する

前述の例では、chooseContainer()関数は、そのパラメータの前に"@"記号を使用することによって、ユーザに対して参照を使って呼び出すべきであることを示しています(@c1, @c2)。しかし、SenseTalkはこれを何ら強制しません。関数をより堅牢にするために、実際にパラメータが参照として渡されたかどうかをチェックし、間違って呼び出された場合にユーザに警告することができます。この目的のために、is a(またはis not a)オペレータを使用できます。以下に、このテストを行う関数の改良版を示します:

to chooseContainer @c1, @c2

if c1 is not a reference or c2 is not a reference then
throw "Not A Reference", "Must pass containers by reference"
end if

if the number of items in c1 < the number of items in c2
then return container c1
else return container c2

end chooseContainer

Repeat With Each ... By Reference

repeat with each コマンドの特別な "by reference" オプションは、イテレータ変数を現在の要素への参照に設定します。これは単にその値ではありません。これは、コンテナのチャンクを反復処理するだけでなく、その要素の一部に変更を加えるスクリプトを書くことを大幅に簡素化します。以下に例を示します:

put "come all you good people and make merry" into phrase

repeat with each word of phrase by reference
if the last char of it is not in "aeiou" then put "e" after it
if it is "you" then set it to "ye"
end repeat

put phrase -- "come alle ye goode people ande make merrye"