![]() |
|
| トップページへ | [ 一覧 | 検索 | 最終更新 ] [ 差分 | 履歴 ] |
|
|
関数†基礎の基礎†YAYAにおける「関数」とは、
処理の集まりです。 引数の数は、変数 _argc、各引数は、変数 _argv[n] に格納されています。 出力候補とは、関数内に直接書かれた文字列や数値、変数名など、左辺値(「=」の左側)が無いものの集まりです。 また、同名の関数が複数存在するとエラーになります。(特に既存のゴーストをベースに改編する場合に注意) 次の「基礎」の章は、汎用言語DLLとしてのYAYAにとっての「関数」です。良く分からない場合は読み飛ばしてかまいません。 基礎†request実行時に"Hello World"という文字列を返すプログラムコードの全体を以下に示します。 request
{
"Hello World"
}
文をロードしたモジュールがHGLOBAL request(HGLOBAL h, long *len)を実行すると、このスクリプトが実行され、"Hello World"が
返されます。
loadとunloadも同様です。 loadとrequestはひとつの引数を持っています。これは変数で取り出せます。 _argc†引数の数。loadとrequestでは引数はひとつの文字列ですから1となります。unloadは引数を持たないので、この値は0となります。 _argv†引数の実体が格納されています。これは_argc個の要素を持つ配列です。各要素へのアクセスは演算子[i]で行います。 基礎編のまとめとして、loadでは変数strに"Hello"を格納し、requestで引数として渡された文字列とstrを結合して返すプログラムコードを 示します。~これまでの説明を踏まえて読んでみてください。 load
{
str = "Hello"
}
request
{
str + " " + _argv[0] + "!"
}
処理対象文字列を"World"としてrequestを実行すると、結果として"Hello World!"が得られます。 書式†以下の則があります。
つまり先に挙げたHello Worldコードは以下のように1行に詰めて書くことが出来ます。 request{"Hello World"}
では以下のように書いてもいいのか? もちろん。問題なく動作します。(ただしこんな風に書くのは感心できない!) req/
uest {
"/
Hello World" }
/の次の行(新たに結合される行)先頭にある空白文字はインデント文字と見なされ、消されます。 "ABCD EFG" 第4項を説明します。 request
{
answer = 1 + 2
"答えは" + answer + "です。"
}
セミコロンを使用して以下のように書けます。 request
{
answer = 1 + 2; "答えは" + answer + "です。"
}
セミコロンは過剰に書いても問題ありません。それらは無視され、動作に影響は与えません。 ユーザー関数の定義と実行†load、unload、request以外に好きな名前の関数を作成できます。 request
{
hello
}
hello
{
"Hello World"
}
上に示したのはもっとも単純な例です。requestは結果として"Hello World"を返します。 同じ結果が得られるもう少し複雑な例を、以下に示します。 request
{
combine("Hello", "World")
}
combine
{
_argv[0] + " " + _argv[1]
}
関数名の後ろに( )をつけて、その中にカンマで値を並べて書くと、これらは該関数に渡される引数として扱われます。
すなわち変数_argvと_argcに値が格納されて、該関数内で参照できるようになります。
関数は再帰呼び出しが可能です。 request
{
factorial(5)
}
factorial
{
if !_argv[0]
1
else
factorial(_argv[0] - 1)*_argv[0]
}
requestは120を返します。 択一†request
{
"Hello World"
"こんにちは世界"
"Hallo Welt"
}
このように列挙すると、これらは平等な「出力候補」として扱われ、出力はこれらのうちのいずれかひとつになります。 下記のいずれかを選ぶことができます。ただし、voidとarray / pool_arrayは特殊な用途のみで使用します。 poolがらみはTc563-1以降での実装になります。 指定なし / random / pool†デフォルトでは無作為に選択します。 poolは下記のようなコードにおいて… request : nonoverlap
{
"Hello World"
if 1 {
"こんにちは世界"
"Hallo Welt"
}
}
中括弧に囲まれた部分は本来random選択された後で候補に加えられますが、pool指定では囲まれない部分と同列に扱うことができます。
以降の nonoverlap_pool / sequential_pool / pool_array も考え方は同じになります。 nonoverlap / nonoverlap_pool†できるだけ直前と同じ候補を選択しなくなります。 request : nonoverlap
{
"Hello World"
"こんにちは世界"
"Hallo Welt"
}
上のように、関数名の後ろに ": nonoverlap" か ": nonoverlap_pool" を付け加えます。 sequential / sequential_pool†記述された順に出力します。最後まで出力したらまた先頭に戻ります。 request : sequential
{
"Hello World"
"こんにちは世界"
"Hallo Welt"
}
上のように、関数名の後ろに ": sequential" か ": sequential_pool" を付け加えます。 void†何も出力しなくなります。 request : void
{
"Hello World"
"こんにちは世界"
"Hallo Welt"
}
「何も実行しない」ではなく、「何も出力しない」であることに注意してください。 increment_i : void
{
i++
i
}
上の関数increment_iはiに1を加算します。voidが無い場合、この関数は加算結果を返しますが、voidを指定すると値を返さず、 ただ加算を行うのみとなります。 array / array_pool†出力候補をすべて結合した汎用配列を関数の返値とします。 request : array
{
"This is a pen."
("A","B","C")
3.14
}
出力は汎用配列 ("This is a pen.", "A", "B", "C", 3.14) となります。 nonoverlap・sequential・arrayとそのpool版は、出力確定子が存在する場合でも取り得るすべての組み合わせに対して正常に機能します。 たとえばsequentialは、 request : sequential
{
"1"
"2"
"3"
--
"A"
"B"
}
requestは以下の順序で出力を発生します。 "1A" "2A" "3A" "1B" "2B" "3B" "1A" "2A" … たとえばarrayは、 request : array
{
"1"
"2"
"3"
--
"A"
"B"
}
上記関数は、 ("1A","1B","1C","2A","2B","2C") という汎用配列を出力します。 関数によっては実行毎に出力候補の数が変動します。~たとえば以下の関数は、変数iの値によって候補数は2個もしくは4個に変化します。 request : sequential
{
if i {
"1"
"2"
}
"3"
"4"
}
候補数が変化した場合、nonoverlapとsequentialの巡回順序は初期化され、最初からやり直しになります。この時に限って、前回と同じ値が重複して 出力されることはあり得ます。 入れ子†request
{
{
"Hello World"
"こんにちは世界"
}
"Hallo Welt"
}
{ } は階層的にいくつでも重ねて書くことが出来ます。動きは最上層の{ }と同じです。すなわち、包含される候補からひとつを選択して出力します。 出力確定子†request
{
"Hello"
"Perfect"
"Peaceful"
--
" Wor"
--
"ld"
"th"
}
‐‐は出力確定子というもので、選択候補はここを区切りとしてグループ分けされます。そして、グループごとに選ばれた結果がひとつの文字列に結合されます。 "Hello World" "Perfect World" "Peaceful World" "Hello Worth" "Perfect Worth" "Peaceful Worth" nonoverlap、sequential、arrayと組み合わせて使用した場合、(グループ単位ではなく)関数が取り得る全ての組み合わせに対して動作します。 出力確定子はどこでも問題なく使用できます。{ }入れ子の深い位置でも使えます。 文は文字列のほかに数値なども扱えますが、出力確定子は結合する際にそれらをすべて文字列に変換し、文字列として結合します。 |