Top/Tips/C言語利用者のためのヒント
  トップページへ   [ 一覧 | 検索 | 最終更新 ]   [ 差分 | バックアップ ]

* この記事は何? [#k095082b]

AYAは、C like で整理された文法、単純な(レイヤーの薄い)仕様、~
強力なプログラミング能力という特徴から、C系の言語習得者にとっては~
マニュアルを殆ど見ずとも使えてしまうSHIORIです。

しかし、その特徴が逆に、思わぬ罠となる事があります。

要するに私の過去の失敗メモです。~
その殆どはマニュアルをきちんと読んでいれば回避できたものなのですが・・・

(文責:[[ひと:浮子屋]])


&color(Red){※以下の文章はAYA5について書かれたものです。YAYAには当てはまらない項目があるかもしれません。};

* 基本の基本 [#h2a99a72]

- C と違って、関数で戻り値を返す際に return を使わない。
- 関数の戻り値はそれまでに出力された候補から選ばれる。
- 従って、何かの間違いで空文字が候補に入っていたりすると、たまに何も喋らない、等の見つけにくいバグになる。&color(Red){注意せよ。};
- それを防ぐには、 void や出力確定子 -- を有効利用できる。

* 文字列展開 [#c182b4f6]

- "" は文字列中の変数や関数を展開する。
- Cに慣れているとつい文字列リテラルは " で書きたくなるが、' が文字列だと覚えておいたほうがよい。&color(Red){注意せよ。};
- 但し、内部的には%を含まない文字列は、中間コード生成時に ' と同等にリテラルとして扱われるようだ。
- "abc%(hemo)efg" は、'abc'+EVAL('hemo')+'efg' と書くのと(たぶん)ほぼ同じである。
- 従って、「たくさんの候補から択一する」ような関数の場合、全ての候補を展開するのは無駄である。
- 候補が決まってから EVAL で埋め込みの展開を行えばよい。[[Tips/高速化]]
- 特別な理由が無い限り%()で範囲を明示すべきである。%だけの名称最長一致展開は重い。
- "abc%hemoefg" はたぶん中間コード生成時に 'abc'+"%hemoefg"となり、実行時に "%hemoefg" を解決しなくてはならない。

* 変数、演算 [#c7c211bb]

- 変数はグローバルとローカルがある。ローカル変数は _で始まる変数である。
- グローバル変数は、SHIORIロード・アンロード時にファイルに保存・ファイルから読み込みされる。
- 従って、保存する必要のないグローバル変数は ERASEVAR で消しておいたほうがよい。
- 変数の初期値は空文字である。「0または空文字」ではない。&color(Red){注意せよ。};
- 文字と数値の演算結果は、加算なら文字列、それ以外なら空文字となる。
- 従って、存在しない変数が数式に混じると結果は文字列か空文字となる。&color(Red){注意せよ。};
- カウントアップしていくような変数は、最初に数値で初期化しないと思わぬエラーを招く。
- 例えば i++ というコードが、上のロジックに従い "11111" というような文字列になる。&color(Red){注意せよ。};
- 変数が数値で初期化されているかどうか迷うような場合は CVINT で強制的に数値にする方法もある。
- ローカル変数のスコープは&color(Red){「現在、およびそれより深い{ }内のみで有効」};である。
- 上記仕様は、思わぬエラーを招く場合がある。次のコード例を見よ。&color(Red){特に注意せよ。};


 hogehoge{
   // ここに _sum=0 が必要。無いとこの関数の結果は空文字
   for _i=0 ; _i<10 ; _i++ {
     _sum+=_i
   }
   _sum
 }

- 比較演算 == で数値と文字列を比較した場合、結果は偽になる。
- 比較演算 == で未定義変数と '' を比較した場合、結果は真になる。


* フロー制御 [#h5fa73df]

- C言語の else if に近いのは elseif である。
- C言語の switch に近いのは、switchではなく case 〜 when である。
- C言語の switch に近いのは、switchではなく case ~ when である。
- for _i = 1; _i < 11; _i++ というような表記で、_i ではなく i と書くと大抵無限ループになり凍る。
- よって、ループで凍ったら _ を注意して探せ。忘れがちなので&color(Red){注意せよ。};

* ゴーストテンプレート(aya_shiori3.dic) [#f6034599]

- OnAiTalk は AYAの独自イベント。OnSecondChangeを契機に aya_shiori3.dic から aitalkinterval 秒毎に通知される。
- チェインはゴースト側の辞書の、OnAiTalk内の条件分岐と、テンプレート側のChainTalkによってなされる。
- よって、ゴースト側の辞書のOnAiTalkを無闇に書き換えるとチェインの仕組みを壊す
- res_reference0 は一見普通の変数だが、値を入れるとテンプレート内でリクエスト応答に Reference?: を入れる働きをする
- つまり、値を入れるとコミュニケートが発動する。&color(Red){注意せよ。};
- ghostexlist / ghostexcount は 本体の otherghostname 通知を元にしているため、正確でない場合がある
- On_otherghostname と On_hwnd は aya_shiori3.dic でなく、ゴースト側の *_string.dic にある。
- 独自イベントを使う際、先頭が「On」で無い場合は、自動的に「On_」が付加された関数名が呼ばれる。
- SAORIの戻り値は適切な型に型変換されて返る。文字列中のバイト値1はカンマになる。
- その際の優先順位は CVINT→CVREAL→文字列 である。

* その他 [#sac398bf]

- SAORIのロードは初回に使う際、アンロードはSHIORIのアンロードの際に行われる。
- つまり、SSPでゴーストキャッシュが有効な場合、SHIORIがキャッシュされるため、ゴーストが終了してもSAORIのアンロードが行われない場合があることに&color(Red){注意せよ。};[[Tips/ゴーストの起動と終了に確実に何かする]]
- ゴーストが終了した際に終らせる必要のあるSAORIは、UNLOADLIBで明示的に終らせる必要がある(SHIORI3FW.SaoriUnloadAllもつかえる)
- C言語の頭になっていると、関数名や変数名を、実行時にEVALで動的に組み立て可能ということになかなか気付かない。
- ある変数の値に応じて、対応する関数を呼びたいのであれば、EVAL("func_%(_var)") という構文が有効。[[Tips/選択肢をいきなり独立した関数で書く]]
- ある変数が %() を含む文字列である場合、それを後で展開したければ EVAL(CHR(0x22)+_var+CHR(0x22)) という構文が有効。[[Tips/高速化]]