コンテナの参照

多くの場合、スクリプト内のコンテナは、値を直接コンテナに格納して(つまりコンテナから値を直接読み取って)使用されるか、スクリプト内で直接変数名(またはその他のコンテナ識別子)を指定して使用されます。ただし、コンテナの参照を格納することは、後でそのコンテナの値にアクセスするのに使用できるため、非常に役に立つ場合があります。参照は、その値ではなくコンテナの識別子を保持し、その参照へのアクセスにより、参照するコンテナのコンテンツの読み取りまたは書き込みが行われます。

特別な機能

参照は、主に経験豊かなスクリプト作成者向けの先進の機能です。初歩ユーザーは、本項目をスキップすることが推奨されます。

参照の特徴

参照には、作業する際に気をつけなければならない2、3の特徴が存在します。参照の作用を理解するために、まずは簡単な変数の参照を利用した以下の例を考察します。

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のワード、またはコンテナの前で記号「@」を使用して作成できます。以下はすべて等価となります。

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

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

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

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は参照です)

put ref into number -- 123 (numberは参照では「ありません」)

put @ref into ref2 -- 123 (ref2はソースへの別の参照になります)

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は再度割り当てられます

put 789 into ref -- source1には影響しません

put (source1, source2) -- (123, 789)

元の参照変数を再度割り当てる代わりに、参照されたコンテナを参照に変更するには、これを明示的にリクエストします。

put @source1 into the container referred to by ref

-- refはsource2を参照したまま、source1の参照になります

put "We're Twins" into ref -- 根本のコンテナに割り当てます

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は新しいアイテム5を参照します)

参照の永続性

変数が参照になると、異なる参照として再度割り当てられるまで、または参照そのものが削除されるまで、参照するコンテナにしっかりと結びつけられます。ただemptyを中に入れるだけで他用途向けに参照変数を解放できると思われるかもしれませんが、これは単に、参照するコンテナにemptyが入るだけの結果となります。別の目的で変数を使用するには、delete variableコマンドを使用してまずその変数を削除する必要があります(deleteコマンドは使用しません。上記を参照)。参照をリスト内のアイテムまたはオブジェクトのプロパティとして格納する場合は、そのアイテムまたはプロパティを削除できます。

put "green" into source

set localColor to refer to source

set localColor to "yellow"

put source -- "yellow"

delete variable localColor -- localColorは定義されていません(参照ではなくなりました)

set localColor to "blue" -- その値を割り当てます

put source -- "yellow"

変数を明示的に削除することなく、参照がプレーンな変数になることが可能な2つの例外的なケースが存在します。特別な変数itの値を明示的に設定するコマンド(「it」に関するすべてにおけるリストを参照)は、新たな値を割り当てる前に、まずitに格納されている参照を破棄します。また、繰り返し構造が現時点の参照であるループ変数を指定する場合は、その参照は変数が繰り返し使用される前に消去されます。

参照の使用

参照は、スクリプト内で多くの方法で使用できます。以下に、最もよく使用される例をいくつか示します。

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

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

put "candy" into tastyFood

pluralize @tastyFood -- 参照によって渡されます

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は、参照によってinitialハンドラから複数形のハンドラに渡されます。これは参照であるため、aWordを複数形のハンドラで変更する場合は、実際は、initialハンドラ内の変数tastyFoodの値が変更されます。

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

別のハンドラへの参照の受け渡しにより、そのハンドラに参照するコンテナのコンテンツを変更する能力が与えられるのと同じように、関数に呼び出し元による変更ができるコンテナの参照を返す能力のあることが役に立つ場合があります。例えば、関数は、グローバル変数の参照や関数が選択したファイルの参照、またはそのようなコンテナのチャンクの参照を返す場合もあります。これを行うには、2つの事柄が起こる必要があります。まず、呼び出された関数が参照を返す必要があります。次に、呼び出しハンドラは、その返された値をコンテナとして使用することを示す必要があります(デフォルトでは、関数の戻り値は常に値によって処理されます)。

例えば、どちらのリストにより少ないアイテムが含まれるかに応じて、2つのリストのうち1つに値を挿入すると仮定します(より現実的な例では、複数のリストが関与すると考えられます)。関数を利用してこのアイデアを実装し、適切なリストを選択するためのスクリプトは以下のようになります。

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"

 

This topic was last updated on 2月 01, 2019, at 11:13:23 午前.

Eggplant icon Eggplant.io | Documentation Home | User Forums | Support | Copyright © 2019 Eggplant