</head> <body> <h1>スクリプト言語</h1> <p>AutoHotkeyスクリプトは、基本的にAutoHotkey専用のカスタム言語で書かれた、プログラムが従うべき命令の集合体です。この言語は、他のいくつかのスクリプト言語と類似していますが、独自の長所と落とし穴も持っています。本書では、その言語について説明するとともに、よくある落とし穴を指摘するようにしています。</p> <p class="note">AutoHotkeyで利用される様々な概念についてのより一般的な説明については、<a href="Concepts.htm">概念と規約</a>を参照してください。</p> <h2 id="toc">目次</h2> <ul> <li><a href="#general-conventions">一般的な慣習</a></li> <li><a href="#comments">コメント</a></li> <li><a href="#expressions">式</a> <ul> <li><a href="#strings">文字列 / テキスト</a></li> <li><a href="#variables">変数</a></li> <li><a href="#constants">定数</a></li> <li><a href="#operators">演算子</a></li> <li><a href="#function-calls">関数呼び出し</a> <ul> <li><a href="#function-call-statements">関数呼び出し文</a></li> <li><a href="#optional-parameters">オプションのパラメータ</a></li> </ul></li> <li><a href="#operators-for-objects">オブジェクトの演算子</a></li> <li><a href="#expression-statements">表現文</a></li> </ul></li> <li><a href="#control-flow">制御フロー文</a> <ul> <li><a href="#control-flow-vs">コントロールフローとその他の文との比較</a></li> <li><a href="#loop-statement">ループ文</a></li> <li><a href="#not-control-flow">非制御</a></li> </ul></li> <li><a href="#structure-of-a-script">スクリプトの構成</a> <ul> <li><a href="#global-code">グローバルコード</a></li> <li><a href="#functions">関数</a></li> <li><a href="#-include">#Includeディレクティブ</a></li> </ul></li> <li><a href="#misc">その他</a> <ul> <li><a href="#dynamic-variables">ダイナミックな変数</a> <ul> <li><a href="#pseudo-arrays">疑似配列</a></li> </ul></li> <li><a href="#labels">ラベル</a></li> </ul></li> </ul> <!-- TODO: Directives Declarations Class definitions Methods? --> <h2 id="general-conventions">一般的な慣習</h2> <p><strong>名前:</strong>変数名と関数名は大文字と小文字を区別しません(例えば、<code>CurrentDate</code>は<code>currentdate</code>と同じです)。最大文字数や使用可能文字数などの詳細は、<a href="Concepts.htm#names">名前</a>を参照してください。</p> <p><strong>型なし変数:</strong>変数には明示的に定義された型がなく、任意の型の値を任意の変数に格納することができます(定数および組み込み変数を除く)。数値は、状況に応じて自動的に文字列(テキスト)に変換されたり、その逆も可能です。</p> <p><strong>宣言は任意:</strong> <a href="Functions.htm">関数のページ</a>に記載がある場合を除き、変数は宣言する必要はありません。ただし、値が与えられる前に変数を読み取ろうとするとエラーとみなされます。</p> <p><strong>スペースの殆どは無視:</strong>インデント(先頭の空白)は、読みやすいコードを書くために重要ですが、プログラムでは必要とされないので、一般的には無視されます。スペースとタブは、行末と式内では<em>通常</em>無視されます(引用符の間を除く)。しかし、スペースは次のようなケースでは意味を持ちます:</p> <ul> <li><a href="#function-calls">関数</a>とメソッド呼び出しでは、関数・メソッド名と<code>(</code>の間にスペースを入てはいけません。</li> <li>連結を行う場合は、空白が必要です。</li> <li>曖昧さをなくすため、2つの演算子の間に空白が必要な場合があります。</li> <li>1行の<a href="#comments">コメント</a>は、行頭でない場合、先頭のスペースが必要です。</li> </ul> <p><strong>改行の意味:</strong>改行は一般的にステートメントの区切りとして機能し、前の関数呼び出しやその他のステートメントを終了させます。(<em>ステートメント</em>とは、単に実行されるべき何らかの動作を表現する、言語の最小の独立した要素です。) ただし、行の継続は例外です(下記参照)。</p> <p><strong>行の継続:</strong>長い行を小さな行の集まりに分割して、読みやすさや保守性を向上させることができます。これは前処理によって実現されるものであり、言語の一部ではありません。3つの方式:</p> <ul> <li><a href="Scripts.htm#continuation-line">継続の接頭辞</a>:<a href="Variables.htm#operators">式演算子</a>で始まる行(++と--を除く)は、前の行と統合されます。行が実際に式を含んでいるかどうかに関係なく、行はマージされます。</li> <li><a href="Scripts.htm#continuation-expr">囲い込みによる継続</a>:()、[]、{}で囲まれた部分式は、ほとんどの場合、自動的に複数行にまたがることができます。</li> <li><a href="Scripts.htm#continuation-section">継続の部</a>:複数の行は、セクションの上にある、<code>(</code>で始まり、<code>)</code>で終わる行にマージされます(両方の記号は、空白を除いて行頭に現れる必要があります)。</li> </ul> <h2 id="comments">コメント</h2> <p><em>コメント</em>とは、スクリプト内のテキストの一部で、プログラムによって無視される部分です。一般的には、説明を加えたり、コードの一部を無効にしたりするために使用されます。</p> <p>スクリプトは、行頭のセミコロンでコメントすることができます。事例:</p> <pre><em>; この行全体がコメントです。</em></pre> <p>コメントは行末に追加することもできますが、その場合、セミコロンの左側には少なくとも1つのスペースまたはタブが必要です。事例:</p> <pre>Run "Notepad" <em>; これは、関数呼び出しと同じ行にあるコメントです。</em></pre> <p>さらに、この<code><em>/*</em></code> および <code><em>*/</em></code>記号は、この例のように、セクション全体をコメントアウトするために使用することができます:</p> <pre><em>/* MsgBox "This line is commented out (disabled)." MsgBox "Common mistake:" */ " this does not end the comment." MsgBox "This line is commented out." */</em> MsgBox "This line is not commented out." <em>/* これも有効ですが、他のコードがその行を共有することはできません。*/</em> MsgBox "This line is not commented out." </pre> <p>タブ、スペースは除く。<code><em>/*</em></code> は行頭に表示する必要があります。 <code><em>*/</em></code>は、行頭または行末にのみ表示することができます。<code><em>*/</em></code>を省略することも有効です。 この場合、ファイルの残りはコメントアウトされます。</p> <p>コメントはスクリプトをファイルから読み込む際にフィルタリングされるため、パフォーマンスやメモリ使用量に影響を与えることはありません。</p> <h2 id="expressions">式</h2> <p><em>式</em>は、1つ以上の<a href="Concepts.htm#values">値</a>、<a href="Concepts.htm#variables">変数</a>、<a href="#operators">演算子</a>、<a href="#function-calls">関数呼び出し</a>の組み合わせです。例えば、<code>10</code>、<code>1+1</code>、<code>MyVar</code>は有効な表現です。通常、式は1つ以上の値を入力とし、1つ以上の演算を行い、結果として値を生成します。式の値を求める作業を<em>評価</em>といいます。例えば、<code>1+1</code>という式は、数字2に<em>評価</em>されます。</p> <p>簡単な式をつなぎ合わせて、どんどん複雑な式にすることができます。例えば、<code>Discount/100</code>で割引率を分数に変換した場合、<code>1 - Discount/100</code>で残額を表す分数を計算し、<code>Price * (1 - Discount/100)</code>を適用してネット価格を算出します。</p> <p><em>値</em>は、<a href="Concepts.htm#numbers">数値</a>、<a href="Concepts.htm#objects">オブジェクト</a>、<a href="Concepts.htm#strings">文字列</a>です。<em>リテラル</em>値とは、スクリプトに物理的に書かれた値で、コードを見ればわかる値です。</p> <h3 id="strings">文字列 / テキスト</h3> <p class="note">文字列の一般的な説明については、<a href="Concepts.htm#strings">文字列</a>を参照してください。</p> <p><em>ストリング</em>または<em>文字列</em>とは、単なるテキスト値のことです。式中、リテラルテキストは、変数名や他の式と区別するために、シングルクォーテーションまたはダブルクォーテーションで囲む必要があります。これはしばしば<em>引用リテラル文字列</em>、あるいは単に<em>引用文字列</em>と呼ばれる。例えば、<code>"これは引用符で囲まれた文字列です"</code>そして<code>'これはそうです'</code>という具合です。</p> <p>引用符で囲まれた文字列の中に<em>実際</em>の引用符を含めるには、<code>`"</code>または<code>`'</code> <a href="misc/EscapeChar.htm#quote">エスケープシーケンスを</a>使用するか、反対のタイプの引用符でその文字を囲みます。事例:<code>'She said, "An apple a day."'</code>。</p> <p>引用符で囲まれた文字列には、<code>`t</code>(タブ)、<code>`n</code>(ラインフィード)、<code>`r</code>(キャリッジリターン)といった他の<a href="misc/EscapeChar.htm">エスケープシーケンス</a>を含めることができます。</p> <h3 id="variables">変数</h3> <p class="note">変数の基本的な説明と一般的な詳細については、<a href="Concepts.htm#variables">変数</a>を参照してください。</p> <p><em>変数</em>は、変数名を書くだけで式の中で使用することができます。例えば、<code>A_ScreenWidth/2</code>です。ただし、引用符で囲まれた文字列の中では、変数を使用することができない。その代わりに、変数やその他の値をテキストと結合させるための処理として <a href="Variables.htm#concat"><em>連結</em></a>。式中の値を<em>連結</em>する方法は2つあります:</p> <ul> <li>暗黙の連結:<code>"The value is " MyVar</code></li> <li>明示的な連結:<code>"The value is " . MyVar</code></li> </ul> <p>暗黙の連結は、<em>自動連結</em>とも呼ばれる。いずれの場合も、変数とドットの前にあるスペースは必須です。</p> <p>また、<a href="lib/Format.htm">フォーマット</a>機能もこの目的に使用できます。事例:</p> <pre>MsgBox Format("You are using AutoHotkey v{1} {2}-bit.", A_AhkVersion, A_PtrSize*8)</pre> <p><code>MyVar := "Some text"</code>のように、変数に値を代入するには、<code>:=</code> <a href="Variables.htm#AssignOp">代入演算子</a>を使用します。</p> <p>式中の<em>パーセント記号</em>は、<a href="#dynamic-variables">動的な変数参照</a>を作成するために使用されますが、これらはほとんど必要ありません。</p> <h3 id="constants">キーワード定数</h3> <p>定数とは、単に変更不可能な値で、シンボリックな名前が与えられているものです。AutoHotkeyには現在、以下の定数があります:</p> <table class="info"> <tr><th>名前</th><th>値</th><th>型</th><th abbr="説明">説明</th></tr> <tr><td>False</td><td>0</td><td><a href="Concepts.htm#numbers">Integer</a></td><td><a href="Variables.htm#Boolean">ブール値</a> false。"off"、"no "などの意味を持つこともある。</td></tr> <tr><td>True</td><td>1</td><td><a href="Concepts.htm#numbers">Integer</a></td><td><a href="Variables.htm#Boolean">ブール値の</a>真偽。「オン」「イエス」などの意味を持つこともある。</td></tr> </table> <p>読み取り専用の<a href="Variables.htm#BuiltIn">組み込み変数</a>とは異なり、<a href="#dynamic-variables">動的参照</a>で返すことはできません。</p> <h3 id="operators">演算子</h3> <p><em>演算子</em>は、<code>+</code>や <code>:=</code>などの記号や記号群、または<code>and</code>、<code>or</code>、<code>not</code>、<code>is</code>、<code>in</code>、<code>contains</code>のいずれかの単語の形をとる。1つ、2つ、3つの値を入力として受け取り、結果として値を返します。演算子の入力として使用される値または部分式を<em>オペランド</em>と呼ぶ。</p> <ul> <li><em>単項</em>演算子は、演算子によって、1つのオペランドの前か後に書かれます。例えば、<code>-x</code>または、<code>not keyIsDown</code>。</li> <li><em>二項</em>演算子は、2つのオペランドの間に記述されます。例えば、<code>1+1</code> または <code>2 * 5</code>。</li> <li>AutoHotkeyには<em>三項</em>演算子が1つだけあり、次のような形をしています<a href="Variables.htm#ternary"><code>条件 ? valueIfTrue : valueIfFalse</code></a>。</li> </ul> <p>単項演算子と二項演算子には同じ記号を持つものがあり、その場合、演算子の意味は2つの値の前、後、間のいずれに書かれるかに依存します。例えば、<code>x-y</code>は引き算を行い、<code>-x</code>は <code>x</code>の符号を反転させる(負の値から正の値を生成し、その逆も同様)ことを意味します。</p> <p>乗算(<code>*</code>)や除算(<code>/</code>)などの優先順位が等しい演算子は、<a href="Variables.htm#operators">演算子テーブル</a>で特に指定がない限り、左から右の順番で評価されます。一方、加算(<code>+</code>)のような優先順位の低い演算子は、乗算(<code>*</code>)のような優先順位の高い演算子の後に評価されます。例えば、<code>3 + 2 * 2</code>は、<code>3 + (2 * 2)</code>と評価されます。この例のように、括弧を使用して優先順位を上書きすることができます:<code>(3 + 2) * 2</code></p> <h3 id="function-calls">関数呼び出し</h3> <p class="note">機能の一般的な説明と関連する用語については、<a href="Concepts.htm#functions">機能</a>を参照してください。</p> <p><em>関数</em>は、さまざまな入力を受け取り、何らかのアクションや計算を行い、その後 返り値を<a href="Concepts.htm#return-a-value"><em>返す</em></a>。関数の入力は、次のように呼ばれます。 <a href="Concepts.htm#parameters"><em>パラメータ</em></a>や<em>引数</em>などです。関数が <a href="Concepts.htm#call"><em>呼び出される</em></a>には、対象となる関数の後に、括弧で囲まれたパラメータを記述するだけでよい。例えば、<code>GetKeyState("Shift")</code>は、<kbd>Shift</kbd>が押されている場合は1を、それ以外の場合は0を返す(評価される)。</p> <p class="warning"><strong>注:</strong>関数と開いた括弧の間には、スペースを入れてはいけません。</p> <p>プログラミングの初心者にとって、括弧の必要性は、最初は不可解で冗長に見えるかもしれませんが、括弧は、関数呼び出しが他の操作と組み合わされることを可能にするものなのです。例えば、<code>GetKeyState("Shift", "P") and GetKeyState("Ctrl", "P")</code>という式は、両方のキーが物理的に押されている場合にのみ1を返します。</p> <p>関数呼び出し式は通常、リテラル関数名で始まりますが、呼び出しの対象は、<a href="misc/Functor.htm">関数オブジェクト</a>を生成する任意の式にすることができます。<code>GetKeyState("Shift")</code>という式では、<em>GetKeyState</em>は実際には変数参照ですが、通常は組み込み関数を含む読み取り専用変数を指します。</p> <h4 id="function-call-statements">関数呼び出し文</h4> <p>関数の戻り値が必要なく、関数名が行頭に書かれている場合(または<code>else</code>や <a href="Hotkeys.htm">ホットキー</a>に続くなど、<a href="Concepts.htm#statement">ステートメント</a>を許可する他のコンテキスト)、括弧を省略することができます。この場合、行の残りは関数のパラメータリストとして扱われます。事例:</p> <pre>result := MsgBox("This one requires parentheses.",, "OKCancel") MsgBox "This one doesn't. The result was " result "."</pre> <p>同じ文脈で<a href="Concepts.htm#methods">メソッド</a>を呼び出す場合、括弧を省略することもできますが、対象となるオブジェクトが<code>myVar.myMethod</code>や <code>myVar.myProp.myMethod</code>のように変数や直接名前の付いたプロパティの場合のみです。</p> <p>関数呼び出し式と同様に、関数呼び出し文のターゲットは定義済みの関数である必要はなく、代わりに<a href="misc/Functor.htm">関数オブジェクト</a>を含む変数にすることができます。</p> <p>関数呼び出し文は、<a href="Scripts.htm#continuation">複数の行にまたがる</a>ことができます。</p> <p>関数呼び出し文には、以下の制限があります:</p> <ul> <li>戻り値がある場合は、必ず破棄されます。</li> <li><a href="#control-flow">制御フロー文</a>と同様に、式の内部で使用することはできません。</li> <li>オプションのパラメータが省略された場合、パラメータリストの<em>末尾</em>にあるカンマも、<a href="Scripts.htm#continuation-line">行の継続</a>を防ぐために省略する必要があります。</li> <li>関数呼び出し文は、可変関数に固定数のパラメータを渡すことができますが、<a href="Functions.htm#VariadicCall">可変関数</a>にすることはできません。</li> </ul> <h4 id="optional-parameters">オプションのパラメータ</h4> <p>オプションのパラメータは、単に空白にすることもできますが、後続のパラメータがすべて省略されない限り、区切りカンマは必要です。例えば、<a href="lib/Run.htm">Run</a>関数は1つから4つのパラメータを受け取ることができます。以下のすべてが有効です:</p> <pre> Run "notepad.exe", "C:\" Run "notepad.exe",, "Min" Run("notepad.exe", , , &amp;notepadPID) </pre> <p id="unset"><a href="#function-calls">関数呼び出し</a>、<a href="Variables.htm#square-brackets">配列リテラル</a>、<a href="Variables.htm#curly-braces">オブジェクトリテラル</a>内で、キーワード<code>unset</code>を使用すると、パラメータまたは値を明示的に省略することができます。アンセット式は、以下のいずれかの効果を持ちます:</p> <ul> <li>ユーザー定義機能の場合、パラメータの<a href="Functions.htm#optional">デフォルト</a>値が使用されます。</li> <li>組込み関数の場合は、パラメータが省略されたものとみなされます。</li> <li><code>[var?]</code>のような<a href="Variables.htm#square-brackets">配列リテラル</a>では、その要素は配列の長さに含まれるが、値は与えられない。</li> <li><a href="Variables.htm#curly-braces">オブジェクトリテラル</a>(<code>{x: y?}</code>など)の場合、プロパティは付与されない。</li> </ul> <p><code>unset</code>キーワードは、<a href="Functions.htm#unset">関数定義</a>において、パラメータがオプションであり、デフォルト値がないことを示すために使用することもできます。関数が実行されるとき、パラメータが省略された場合、そのパラメータに対応するローカル変数には<a href="Concepts.htm#nothing">値</a>がありません。</p> <p><a href="Variables.htm#maybe">maybe演算子(<em>var</em><strong>?</strong>)</a>は、変数が値を持つかどうかによって、その変数を渡したり省略したりするのに使われます。例えば、<code>Array(MyVar?)</code>は<code>Array(IsSet(MyVar) ? MyVar : unset)</code>と等価です。</p> <h3 id="operators-for-objects">オブジェクトの演算子</h3> <p>このほかにも、以下に示すように、上記の分類に当てはまらない、あるいは表現の他の部分の意味に影響を与えるような記号が表現に使用されています。これらはすべて、何らかの形で<em>オブジェクト</em>に関係するものです。各コンストラクトがどのような働きをするのか、詳しく説明するためには、さらに多くの概念を導入する必要があり、このセクションの範囲外です。</p> <p><code>Alpha.Beta</code>は <em>メンバー</em>アクセスと呼ばれることが多い。<em>Alpha</em>は普通の変数で、関数呼び出しや、オブジェクトを返す他の部分式に置き換えることができる。評価されると、オブジェクトに「プロパティ<em>Beta</em>の値を教えて」「この値をプロパティ<em>Beta</em>に格納して」「<em>Beta</em>という名前のメソッドを呼び出して」という要求が送られます。つまり、<em>Beta</em>はオブジェクトに対して意味を持つ名前であり、ローカル変数やグローバル変数ではありません。</p> <p><code>Alpha.Beta()</code>は、上記の通り、<em>メソッド呼び出し</em>です。特定の場合、括弧を省略することができます。「<a href="#function-call-statements">関数呼び出しステートメント</a>」を参照してください。</p> <p><code>Alpha.Beta[Param]</code>は、リクエストに追加のパラメータを含む特別な会員アクセスの形態です。<em>Beta</em>が単純な名前であるのに対し、<em>Param</em>は通常の変数や部分式、あるいはカンマで区切られた部分式のリスト(関数のパラメータリストと同じ)です。<a href="Functions.htm#VariadicCall">変則的な呼び出し</a>が可能です。</p> <p><code>Alpha.%vBeta%</code>、<code>Alpha.%vBeta%[Param]</code>、および<code>Alpha.%vBeta%()</code>もメンバーアクセスですが、<em>vBeta</em>は変数または副式です。これにより、スクリプトの実行中にプロパティやメソッドの名前を決定することができます。この方法でメソッドを呼び出す場合は、括弧を付ける必要があります。</p> <p><code>Alpha[Index]</code>は、<code>Index</code>をパラメータとして、<code>Alpha</code>の<em>デフォルトのプロパティ</em>にアクセスします。この場合、<em>Alpha</em>と <em>Index</em>はいずれも変数であり、事実上あらゆる部分式に置き換えることができる。この構文は、通常、<a href="lib/Array.htm">Array</a>や <a href="lib/Map.htm">Map</a>の要素を取得するために使用されます。</p> <p id="array-literal"><code>[A, B, C]</code>は、初期内容A、B、C(この場合はすべて変数)を持つ<a href="lib/Array.htm">配列</a>を作成し、Aは要素1です。</p> <p id="object-literal"><code>{Prop1: Value1, Prop2:Value2}</code>文字通り<em>Prop1</em>と<em>Prop2</em>という名前のプロパティを持つ<a href="lib/Object.htm">Object</a>を作成します。値は、後で前述の<em>メンバーアクセス</em>構文を使用して取得することができます。プロパティ名を式として評価する場合は、パーセント記号で囲みます。例えば:<code>{%NameVar%: ValueVar}</code>。</p> <p><code>MyFunc(Params*)</code>は、<a href="Functions.htm#VariadicCall">可変長引数関数呼び出し</a>です。アスタリスクは、関数のパラメータリストの最後にある閉じ括弧の直前でなければなりません。<em>Params</em>は、<a href="lib/Array.htm">Array</a>または他の列挙可能なオブジェクトを返す変数または部分式でなければなりません。<code>Params*</code>はどこでも使えるわけではありませんが、配列リテラル(<code>[A, B, C, ArrayToAppend*]</code>)やプロパティのパラメータリスト(<code>Alpha.Beta[Params*]</code>や<code>Alpha[Params*]</code>)で使用することが可能です。</p> <h3 id="expression-statements">表現文</h3> <p>すべての表現が行内で単独で使用できるわけではありません。例えば、<code>21*2</code>や <code>"Some text"</code>だけで構成された行は、何の意味もなさない。式の<em>文</em>は、それ自体で使用される式で、通常はその副作用のために使用されます。副作用のある表現のほとんどはこの方法で使えるので、一般にこの項の詳細を覚える必要はない。</p> <p>ステートメントとして使用できるのは、次の種類の式です:</p> <p><code>x := y</code>のような代入、<code>x += y</code>のような複合代入、<code>++x</code>や<code>x--</code>のようなインクリメント/デクリメント演算子。</p> <p class="warning"><strong>既知の制限事項:</strong> <code>x++</code>と <code>x--</code>については、現在、変数名と演算子の間にスペースを入れることができません。</p> <p><code>MyFunc(Params)</code>のような関数呼び出し。ただし、単独の関数呼び出しには、関数宣言と混同されるため、(行末や次の行で)開波括弧<code>{</code>を付けることはできません。</p> <p><code>MyObj.MyMethod()</code>のようなメソッド呼び出しです。</p> <p><code>MyObj[Index]</code>のように角括弧を使ったメンバーアクセスは、関数呼び出しのような副作用がある場合があります。</p> <p>3項式、<code>x ? CallIfTrue() : CallIfFalse()</code>。ただし、式(または条件)を常に括弧で囲むという、以下のルールを利用するのが無難です。</p> <p class="warning"><strong>既知の制限事項:</strong> <a href="#function-call-statements">関数呼び出し文</a>があいまいなため、変数名とスペースで始まる条件(他の演算子も含む)は、括弧で囲む必要があります。例えば、<code>(x + 1) ? y : z</code>や<code>x+1 ? y : z </code>は、式ですが、<code>x + 1 ? y : z</code>は、関数呼び出し文です。</p> <p class="warning"><strong>注:</strong>条件は、<a href="Scripts.htm#continuation-line">継続行</a>と解釈されるため、<code>!</code>やその他の式演算子で始めることはできません。</p> <p>始まる表現<code>(</code>。しかし、通常、同じ行に一致する<code>)</code>がなければ、その行は<a href="Scripts.htm#continuation">継続セクション</a>の開始と解釈されます。</p> <p><code>%varname% := 1</code>のように、ダブルデフで始まる式。これは主に、実装の複雑さによるものです。</p> <p>簡略化のため、上記のいずれかで始まる表現(後述のものは除く)も可とします。例えば、<code>MyFunc()+1</code>は現在許可されていますが、<code>+1</code>は何の効果もなく、その結果は破棄されます。将来、エラーチェックの強化により、このような表現が無効となる可能性があります。</p> <p><a href="#function-call-statements">関数呼び出し文は</a>式文と似ていますが、技術的には純粋な式ではありません。例えば、<code>MsgBox "Hello, world!"</code>,<code>myGui.Show</code>または<code>x.y.z "my parameter"</code>などです。</p> <h2 id="control-flow">制御フロー文</h2> <p class="note">制御フローの一般的な説明については、<a href="Concepts.htm#control-flow">制御フロー</a>を参照してください。</p> <p><a href="Concepts.htm#statement">ステートメント</a>は、グループ化され <a href="lib/Block.htm"><em>ブロック</em></a>は、C言語やJavaScriptなどのように中括弧<code>{}</code>で囲むことで実現できますが、通常、中括弧は行頭に表示する必要があります。制御フロー文は、ブロック全体に適用することも、1つの文だけに適用することも可能です。</p> <p>制御フロー文の<a href="Concepts.htm#cf-body">本体</a>は、常に1つの文の<em>グループ</em>です。ブロックは、制御フロー文とその本体と同様に、1つの文のグループとしてカウントされます。また、以下の関連する文は、その本体とともに互いにグループ化されている:<code>If</code>と<code>Else</code>、<code>Loop</code>/<code>For</code>と<code>Until</code>または<code>Else</code>、<code>Try</code>と<code>Catch</code>または/および<code>Else</code>または/および<code>Finally</code>。つまり、これらの文のグループを全体として使用する場合、必ずしも中括弧で囲む必要はありません(ただし、コーディングスタイルによっては、わかりやすくするために中括弧を必ず入れるものもあります)。</p> <p>制御フロー文は、本文を持つため、必ず関連する文または文のグループが続く必要があります:<code>If</code>、<code>Else</code>、<code>Loop</code>、<code>While</code>、<code>For</code>、<code>Try</code>、<code>Catch</code>、<code>Finally</code>。</p> <p id="control-flow-list">以下のような制御フロー文が存在:</p> <ul> <li><a href="lib/Block.htm">ブロック</a>(中括弧のペア)は、0個以上のステートメントをグループ化して、1つのステートメントとして動作させるものです。</li> <li><a href="lib/If.htm">If文</a>は、条件によってその本体が実行されたりされなかったりします。その後に、条件が満たされなかった場合にのみ実行される<a href="lib/Else.htm">Else</a>文が続くこともあります。</li> <li><a href="lib/Goto.htm">Goto</a>は指定されたラベルにジャンプして実行を継続します。</li> <li><a href="lib/Return.htm">Return</a> 関数から戻り値を帰す。</li> <li><a href="#loop-statement">ループ文</a>(<a href="lib/Loop.htm">Loop</a>、<a href="lib/While.htm">While</a>、または、<a href="lib/For.htm">For</a>)は、その本体を繰り返し実行します。 <ul> <li><a href="lib/Break.htm">Break</a>は、ループを抜ける(終了させる)。</li> <li><a href="lib/Continue.htm">Continue</a>は、現在のループ反復の残りをスキップして、新しいループを開始します。</li> <li><a href="lib/Until.htm">Until</a>は、式がtrueと評価されたときにループを終了させる。式は、各反復の後に評価されます。</li> </ul></li> <li><a href="lib/Switch.htm">Switch</a>は、値を複数のケースと比較し、最初にマッチしたステートメントを実行します。</li> <li>例外処理: <ul> <li><a href="lib/Try.htm">Try</a>、実行時のエラーやthrow文によって投げられる値に対して本体をガードします。</li> <li><a href="lib/Catch.htm">Catch</a>は、try文の中で指定された型の例外が発生した場合に実行されます。</li> <li><a href="lib/Else.htm">Else</a>は、catch文の後に使用すると、try文の中で例外が発生しなかった場合にのみ実行されます。</li> <li><a href="lib/Finally.htm">Finally</a> try文やcatch文の本体から制御が移ったときに、本体を実行します。</li> <li><a href="lib/Throw.htm">Throw</a> try/catch や<a href="lib/OnError.htm">OnError</a>で処理される例外を、エラーダイアログを表示するためのものです。</li> </ul></li> </ul> <h3 id="control-flow-vs">コントロールフローとその他の文との比較</h3> <p>制御フロー文は、<a href="#function-call-statements">関数呼び出し文</a>といくつかの点で異なっています:</p> <ul> <li><a href="lib/Block.htm">ブロック</a>の開始ブレースは、<a href="lib/If.htm">If</a>、<a href="lib/Else.htm">Else</a>、<a href="#loop-statement">Loop</a>、<a href="lib/While.htm">While</a>、<a href="lib/For.htm">For</a>、<a href="lib/Try.htm">Try</a>、<a href="lib/Catch.htm">Catch</a>、<a href="lib/Finally.htm">Finally</a>文(基本的に<a href="Concepts.htm#cf-body">ボディ</a>を持つあらゆる制御フロー文)と同じ行末に書くことができます。これをOTB(One True Brace)スタイルと呼びます。</li> <li><a href="lib/Else.htm">Else</a>、<a href="lib/Try.htm">Try</a>、および、<a href="lib/Finally.htm">Finally</a>は、<a href="Concepts.htm#cf-body">本体</a>を必要とするがパラメータを持たないため、その右側に任意の有効な文を置くことができる。</li> <li><a href="lib/If.htm">If</a>、<a href="lib/While.htm">While</a>、<a href="lib/Return.htm">Return</a>、<a href="lib/Until.htm">Until</a>、<a href="lib/Loop.htm">Loop<em>Count</em></a>、および、<a href="lib/Goto.htm">Goto</a>では、名前の直後に開括弧を使用し、パラメータリスト全体を囲むことができます。これらは一見すると関数呼び出しのように見えますが、そうではなく、式の途中で使用することはできません。例えば、<code>if(expression)</code>。</li> <li>制御フロー文は、同名の関数を定義することで上書きすることはできません。</li> </ul> <h3 id="loop-statement">ループ文</h3> <p>ループ文にはいくつかの種類があります:</p> <ul> <li><a href="lib/Loop.htm">Loop <em>Count</em></a> executes a statement repeatedly: either the specified number of times or until Break is encountered.</li> <li><a href="lib/LoopReg.htm">Loop Reg</a>は、指定されたレジストリのサブキーの内容を1項目ずつ取得します。</li> <li><a href="lib/LoopFiles.htm">Loop Files</a>は、指定したファイルやフォルダを1つずつ取得します。</li> <li><a href="lib/LoopParse.htm">Loop Parse</a>は、文字列から部分文字列(フィールド)を1つずつ取り出します。</li> <li><a href="lib/LoopRead.htm">Loop Read</a>は、テキストファイルの行を1行ずつ取得します。</li> <li><a href="lib/While.htm">While</a>は、指定された式がfalseに評価されるまで、ステートメントを繰り返し実行します。式は、各反復の前に評価されます。</li> <li><a href="lib/For.htm">For</a>は、オブジェクトのキーと値のペアのように、列挙者が返す値や値のペアごとにステートメントを1回実行します。</li> </ul> <p><a href="lib/Break.htm">Break</a>は、ループを抜ける(終了する)ことで、ループのボディの次の行に効果的にジャンプすることができます。</p> <p><a href="lib/Continue.htm">Continue</a>は、現在のループ反復の残りをスキップして、新しいループを開始します。</p> <p><a href="lib/Until.htm">Until</a>は、式がtrueと評価されたときにループを終了させる。式は、各反復の後に評価されます。</p> <p id="named-loops"><a href="#labels">ラベル</a>は、<a href="lib/Continue.htm">Continue</a>や <a href="lib/Break.htm">Break</a>のループに「命名する」ために使うことができます。これにより、<a href="lib/Goto.htm">Goto</a>を使用しなくても、スクリプトを簡単に続行したり、任意の数の入れ子ループから抜け出したりすることができます。</p> <p>組込変数<strong>A_Index</strong>には、現在のループの繰り返し回数が格納されます。ループ本体が最初に実行されるときに1を含む。2回目には2が入り、以下同様です。内側ループが外側ループで囲まれている場合、内側ループが優先されます。A_Indexは、すべての種類のループの内部で機能しますが、ループの外部では0を含みます。</p> <p>一部のループタイプでは、他の組み込み変数が現在のループアイテム(レジストリキー/値、ファイル、部分文字列、テキスト行)に関する情報を返します。これらの変数は、A_LoopFileNameやA_LoopReadLineなど、<strong>A_Loop</strong>で始まる名前を持っています。これらの値は常に、該当するタイプの最も最近に開始された(しかしまだ停止していない)ループに対応します。例えば、A_LoopFieldは、ファイルやレジストリのループ内で使用されていても、最も内側の解析ループの現在の部分文字列を返します。</p> <pre>t := "column 1`tcolumn 2`nvalue 1`tvalue 2" Loop Parse t, "`n" { rowtext := A_LoopField rownum := A_Index <em>; 以下、2つ目のループで使用するために保存します。</em> Loop Parse rowtext, "`t" { MsgBox rownum ":" A_Index " = " A_LoopField } } </pre> <p>ループ変数は、ループ内から呼び出される関数など、ループ本体の外でも使用することができます。</p> <h3 id="not-control-flow">非制御</h3> <p>ディレクティブ、ラベル、ダブルコロンホットキーとホットストリングタグ、および割り当てのない宣言は、スクリプトがファイルからロードされるときに処理されるので、制御フローの対象にはなりません。つまり、スクリプトが制御フロー文を実行する前に、無条件で効果を発揮するのです。同様に、<a href="lib/_HotIf.htm">#HotIf</a>指示文は、制御フローに影響を与えることはできません。ホットキーの条件は、コード内で#HotIfディレクティブに遭遇したときではなく、押されるたびに評価されます。</p> <h2 id="structure-of-a-script">スクリプトの構成</h2> <h3 id="global-code">グローバルコード</h3> <p>スクリプトが読み込まれた後、<em>自動実行スレッド</em>は、スクリプトの先頭行で実行を開始し、<a href="lib/Return.htm">Return</a>、<a href="lib/ExitApp.htm">ExitApp</a>、<a href="lib/Exit.htm">Exit</a>などの停止指示があるまで実行を続ける。スクリプトの物理的な端は、<a href="lib/Exit.htm">Exit</a>としても機能します。</p> <p>グローバルコード(グローバル<a href="Concepts.htm#scope">スコープ</a>内のコード)とは、関数やクラス定義の内部にない実行可能なコードのことです。そこで参照される変数は、(適切な宣言があれば)どの関数からもアクセスできるため、<a href="Functions.htm#Global">グローバル</a>変数と呼ばれる。このようなコードは、新しく起動した<a href="misc/Threads.htm">スレッド</a>に適用される設定や、ホットキーやその他の機能で使用するグローバル変数の<a href="Concepts.htm#uninitialized-variables">初期化</a>などによく使用されます。</p> <p>起動時(スクリプトを起動した直後)に実行されるコードは、ファイルの先頭に配置されることが多い。しかし、このようなコードは、関数やクラス定義の間(内部ではない)に、ファイル全体に配置することができます。これは、各関数やクラス定義の本体が、実行中に遭遇するたびにスキップされるからです。場合によっては、スクリプトの目的全体をグローバルコードで遂行することもあります。</p> <p><strong>関連:</strong> <a href="Scripts.htm#auto">スクリプトの起動(自動実行のスレッド)</a></p> <h3 id="subroutines">サブルーチン</h3> <p><em>サブルーチン</em>(<em>sub</em>または<em>procedure</em>)は、要求に応じて実行できる再利用可能なコードブロックです。サブルーチンは、<em>関数</em>(後述)を定義することで作成されます。これらの用語は、関数がサブルーチンの唯一のタイプであるAutoHotkey v2では一般的に互換性があります。</p> <h3 id="functions">関数</h3> <p><strong>関連:</strong> <a href="Functions.htm">関数</a>(関数の定義についてのすべて)</p> <p>便利な<a href="lib/index.htm">定義済み関数</a>を呼び出すだけでなく、スクリプトは独自の関数を定義することができます。これらの機能は、一般的に2通りの使い方があります:</p> <ol> <li>関数は、スクリプト自身から呼び出すことができます。この種の機能は、繰り返しを避けるため、コードをより管理しやすくするため、あるいは他の目的で使用されるかもしれません。</li> <li>関数は、ユーザーがホットキーを押すなど、何らかの事象に反応してプログラムから呼び出されることがあります。例えば、各ホットキーには、そのホットキーが押されたときに実行される関数が関連付けられています。</li> </ol> <p>関数を定義する方法は複数あります:</p> <ul> <li>名前、括弧、コードの<a href="lib/Block.htm">ブロック</a>を組み合わせた<a href="Functions.htm">関数定義</a>です。これは、<a href="#function-calls">関数コール</a>または<a href="#function-call-statements">関数コールステートメント</a>で名前を指定して実行できる関数を定義します。事例: <pre>SayHello() <em>; SayHello関数を定義します。</em> { MsgBox "Hello!" } SayHello <em>; SayHello関数を呼び出す。</em></pre> </li> <li><a href="Hotkeys.htm">ホットキー</a>または<a href="Hotstrings.htm">ホットストリング</a>の定義で、ホットキーまたはホットストリングを1つの<a href="Concepts.htm#statement">ステートメント</a>またはコードの<a href="lib/Block.htm">ブロック</a>と組み合わせたものです。このタイプの関数は直接呼び出すことはできませんが、ホットキーまたはホットストリングがアクティブになるたびに実行されます。事例: <pre>#w::Run "wordpad" <em>; Win-Wを押してWordpadを実行します。</em> #n:: <em>; Win-Nを押してメモ帳を起動します。</em> { Run "notepad" }</pre> </li> <li><a href="Variables.htm#fat-arrow">ファットアロー式</a>は、コードのブロックを実行する代わりに、<a href="#expressions">式</a>を評価してその結果を<a href="Concepts.htm#return-a-value">返す</a>関数を定義します。このような関数は、他の関数に直接渡されるため、通常は名前を持ちません。事例: <pre>SetTimer () =&gt; MsgBox("Hello!"), -1000 <em>; 1秒後に"hello"を表示します。</em></pre> </li> <li>ファットアロー構文は、通常の関数やメソッド定義の略記として、式の外でも使用できます。例えば、以下は上記のSayHelloの定義と同等ですが、こちらは "OK"を返すことを除きます: <pre>SayHello() =&gt; MsgBox("Hello!")</pre> </li> </ul> <p>関数内の変数は、以下の場合を除き、デフォルトでその関数の<a href="Functions.htm#Local">ローカル</a>変数となります:</p> <ul> <li>機能が<a href="Functions.htm#AssumeGlobal">assume-global</a>の場合。</li> <li>変数が参照されているが、<a href="Variables.htm#AssignOp">代入</a>や参照演算子(<code>&amp;var</code>)の対象として使用されていない場合。</li> <li><a href="Functions.htm#nested">ネストした関数</a>の内部で、外側関数のローカル変数を参照する場合。</li> </ul> <p>関数は、オプションで<a href="Concepts.htm#parameters">パラメータを受け取る</a>ことができます。パラメータは、括弧の中に列挙することで定義されます。事例:</p> <pre>MyFunction(FirstParameter, Second, &amp;Third, Fourth:="") { <em>;...</em> return "a value" } </pre> <p>関数呼び出しと同様に、関数名とオープン括弧の間にはスペースを入れてはいけません。</p> <p>クローズパンテシスとオープンブレースの間の改行は任意です。2つの間に空白やコメントをいくら入れてもよい。</p> <p><a href="Functions.htm#ByRef">ByRef マーカ(&amp;)</a>は、呼び出し側が変数参照を渡さなければならないことを示します。関数内部では、パラメータへの参照は、実際には呼び出し元の変数にアクセスすることになります。これは、<code>&amp;</code>を省略して関数内で明示的にパラメータを<a href="Variables.htm#deref">再参照</a>する方法(例、<code>%Third%</code>)と似ていますが、この場合はパーセント記号が省略されています。パラメータがオプションで、呼び出し側がそれを省略した場合、パラメータは通常のローカル変数として動作します。</p> <p><a href="Functions.htm#optional">オプション</a>のパラメータは、パラメータ名の後に<code>:=</code>を付けて指定し、デフォルト値を指定します。この値は、リテラルな引用符で囲まれた文字列、数値、<code>true</code>、<code>false</code>、または<code>unset</code>でなければなりません。</p> <p>関数は、<a href="Functions.htm#return">値を返す</a>ことができます。そうでない場合、デフォルトの戻り値は空文字列となる。</p> <p>関数定義は、その関数への呼び出しの前にある必要はありません。</p> <p class="note">詳しくは<a href="Functions.htm">機能</a>をご覧ください。</p> <h3 id="-include">#Includeディレクティブ</h3> <p><a href="lib/_Include.htm">#Include</a>指令は、指定されたファイルの内容がこの正確な位置に存在するかのようにスクリプトを動作させるものです。これは、コードを別のファイルに整理したり、他のユーザーが書いたスクリプトライブラリを利用するためによく使われます。</p> <p>インクルードファイルには、<a href="Scripts.htm#auto">スクリプト起動</a>時に実行される<a href="#global-code">グローバルコード</a>を含めることができますが、メインスクリプトファイルのコードと同様に、そのようなコードは、#Include指令の前に自動実行スレッドが終了(無条件で<code>Return</code>など)されない場合にのみ実行されます。先行<code>Return</code>により実行できないコードがある場合、デフォルトで<a href="lib/_Warn.htm#Unreachable">警告</a>が表示されます。</p> <p>C/C++とは異なり、#Includeは、そのファイルが既に以前の指令によってインクルードされていた場合、何もしません。同じファイルの内容を複数回インクルードする場合は、<a href="lib/_Include.htm">#IncludeAgain</a>を使用します。</p> <p>スクリプトの共有を容易にするために、#Includeはライブラリスクリプトのいくつかの標準的な場所を検索することができます。詳しくは、<a href="Scripts.htm#lib">スクリプトライブラリフォルダ</a>を参照してください。</p> <h2 id="misc">その他</h2> <h3 id="dynamic-variables">ダイナミックな変数</h3> <p><em>動的変数参照</em>は、テキスト値を受け取り、それを変数名として解釈します。</p> <p class="note"><strong>注:</strong>動的参照によって変数を<em>作成</em>することはできませんが、既存の変数を割り当てることは可能です。これには、スクリプトが非動的な参照を含むすべての変数が含まれ、たとえ値が割り当てられていない場合でも、その変数が含まれます。</p> <p>動的変数参照の最も一般的な形式は、<em>二重参照</em>または<em>double-deref</em>と呼ばれます。二重参照を行う前に、対象となる変数名を第二の変数に格納します。そして、この第2変数を用いて、二重参照を用いて間接的に対象変数に値を代入することができる。事例:</p> <pre>target := 42 second := "target" MsgBox second <em>; 通常の(単一の)変数の参照⇒ターゲット</em> MsgBox %second% <em>; ダブルデフ⇒42</em> </pre> <p>現在、<code>second</code>の場合は必ず変数名を含む必要があり、任意の式はサポートされていません。</p> <p>動的変数参照は、1つまたは複数のリテラルテキストと1つまたは複数の変数の内容を取り、それらを結合して1つの変数名を形成することもできます。これは、名前とパーセントで囲まれた変数の断片を、空白を入れずに順番に書いていくだけです。例えば、<code>MyArray%A_Index%</code>や、または <code>MyGrid%X%_%Y%</code>。後述する<em>擬似配列</em>にアクセスするために使用します。</p> <p>これらのテクニックは、オブジェクトのプロパティやメソッドにも適用できます。事例:</p> <pre>clr := {} for n, component in ["red", "green", "blue"] clr.%component% := Random(0, 255) MsgBox clr.red "," clr.green "," clr.blue</pre> <h4 id="pseudo-arrays">疑似配列</h4> <p><em>擬似配列</em>は、実際には単なる離散変数の束ですが、配列の要素のように使用できるような命名パターンを持っています。事例:</p> <pre> MyArray1 := "A" MyArray2 := "B" MyArray3 := "C" Loop 3 MsgBox MyArray%A_Index% <em>; Aを表示し、次にBを表示し、次にCを表示します。</em> </pre> <p>最終的な変数名を形成するために使用される「インデックス」は数値である必要はなく、代わりに文字やキーワードを使用することができます。</p> <p>これらの理由から、一般的には擬似配列ではなく、<a href="Objects.htm#Usage_Simple_Arrays">Array</a>や <a href="Objects.htm#Usage_Associative_Arrays">Map</a>を使用することが推奨されます:</p> <ul> <li>個々の要素は通常の変数であるため、値の割り当てや取得は可能ですが、要素の<em>削除</em>や <em>挿入</em>はできません。</li> <li>疑似配列は概念的なものでしかなく、1つの値ではないため、関数に渡したり返したり、全体としてコピーすることはできません。</li> <li>擬似配列は全体として宣言できないので、ある「要素」は<a href="Functions.htm#Global">グローバル</a>(または<a href="Functions.htm#capture-var">キャプチャ</a>)変数に解決され、他の「要素」は解決されないことがあります。</li> <li>変数が非動的に参照され、動的にのみ割り当てられる場合、<a href="lib/_Warn.htm#VarUnset">ロードタイム警告</a>が表示される場合があります。このような警告は、エラーを検出するための非常に有効な手段であるため、無効にすることは推奨されません。</li> <li>現在のバージョンの言語では、新しい変数を動的に作成することはできません。これは、ベストプラクティスを奨励するためでもあり、関数内の動的変数参照と非動的変数参照との間の矛盾を避けるためでもあります。</li> </ul> <h3 id="labels">ラベル</h3> <p>ラベルはコード行を識別するもので、<a href="lib/Goto.htm">Goto</a>ターゲットとして使用したり、<a href="#named-loops">ループ</a>から抜け出したり継続する<a href="#named-loops">ループを指定</a>したりすることができます。ラベルは、<a href="Concepts.htm#names">名前</a>とコロンで構成されています:</p> <pre>this_is_a_label:</pre> <p>空白とコメントを除き、ラベルと同じ行に他のコードを記述することはできません。詳細は <a href="misc/Labels.htm">ラベル</a>をご覧ください。</p> </body> </html>