call文
call 文は、別のトークや関数をその場で呼び出します。
呼び出された側が出力したセリフは、call を書いた位置にそのままつながります。
書き方
call 名前
名前 にはトーク名か関数名を書きます。引数のリストや () は付けません。
トークを呼ぶ
イベント名に限らず、任意の名前でトークを定義できます。
それを call で呼び出せます。
挨拶 => {
湊: こんにちは。
}
OnBoot => {
call 挨拶
湊: 今日もよろしくお願いします。
}
出力は \0こんにちは。今日もよろしくお願いします。 のように、call した位置に展開されます。
話者が同じ間はスコープタグ(\0)が繰り返されないので、呼ばれたトークのセリフと call の後のセリフは、そのままつながります。
話者が変わったときは、通常どおりタグが入ります。
呼ばれたトークは、通常のイベントと同じように次の処理が行われます。
- 同じ名前のトークが複数あれば、条件フィルタ(
if(...))で絞り込んだうえで、ランダムにひとつ選ばれます - 選ばれたトークが
returnで値を返すと、その値もセリフとして出力されます
挨拶 if((save.訪問回数 ?? 0) == 0) => {
湊: はじめまして。
}
挨拶 => {
湊: また会いましたね。
}
すべての候補が除外されたとき
call したトークの候補が、if(...) によってすべて除外されると、何も出力されません。
このときは「候補が全てcondで除外され、何も出力されませんでした」という notice が記録されます。
関数を呼ぶ
func で定義した関数も call で呼べます。
関数の中でセリフを書いていれば、その出力が call の位置に出ます。
return で返した値も、出力に加わります。
func 挨拶する() {
湊: こんにちは。
}
OnBoot => {
call 挨拶する
}
call は引数を渡せません。引数付きで呼びたいときは、次の 名前(引数) の書き方を使います。
名前() の書き方
文の位置(行の先頭)に 名前(引数) と書くと、call 名前 とほぼ同じ動作になります。
トークでも関数でも呼べ、関数には引数を渡せます。
func add(a, b) {
湊: ${a}と${b}
}
OnBoot => {
add(1, 2) // 湊: 1と2
}
log(...) のようなビルトイン関数を文の位置に書いた場合は、副作用だけが実行され、戻り値は出力されません。
OnBoot => {
log('起動しました') // 何も出力されない
湊: こんにちは。
}
呼び出す名前は、ユーザー定義の関数、トーク、ビルトイン関数の順に探されます。
なお、${挨拶する()} や let v = 挨拶する() のように式の中で書いた場合は、
戻り値が値として使われます。セリフの出力は call や文位置の 名前() のときだけです。
動的なcall
変数に入っている文字列を名前として呼ぶこともできます。
reference.0(SSPから渡されたreference)のように、実行時に名前が決まる場合に使えます。
OnBoot => {
let target = "挨拶"
call target // 「挨拶」トークを呼ぶ
}
変数の値が文字列でないか空のときは、変数名そのものがトーク名・関数名として探されます。
その名前のトークも関数も存在しない場合は、何も起こりません。
定義されていない名前を call すると、静的チェックで notice が出ます
(動的callの場合は無視して構いません)。
call OnUpdate.OnTypo のようなドット付きの名前は、call reference.0 などの動的callと見分けられないため、
通常は静的チェックの対象外です。ただし、OnUpdate.OnDownloadBegin のように同じ「OnUpdate.」で始まるトークが
定義されているのに、その名前だけが無い場合は、打ち間違いの可能性が高いとして notice が出ます。
呼び出しの深さ
call の入れ子(トークが別のトークを呼ぶ、関数が関数を呼ぶ)は、深さ約100が上限です(正確には、最初の呼び出しから数えて101段目までです)。
上限を超えた呼び出しは実行されません。