3回話しかけると襲い掛かってくる村人をコルーチンで表現する話

最初にちょっとしたSAS絡みのニュース
①SASユーザー総会のサイトがオープンした。聴講するより発表した方が楽しいので、アブストラクトだしましょうという話
http://www.sascom.jp/sug17/

②生物統計ハンドブックが12年ぶりに新版で内容変わるみたいなので、医薬系ユーザーは会社にねだって買って貰っとこうという話
http://www.scientist-press.com/11_339.html

さて、本題、例えばSASでロールプレイングゲームを作ろうと思います。
ある村人に話しかけると、村の名前を言ってくれるのですが、三回同じように話しかけると会話内容が変わって戦闘になるというイベントを作りたいと思います。
この3回話しかけると処理が変わるという機能をSASで実装するにはどうしますか?
今までは村人の会話挙動をSASマクロで実装して、村人に話しかけた回数をグローバルマクロ変数かSASデータセットに保存する必要がありました。
しかし、たかだか村人一人の挙動制御のためにグローバルマクロ変数を一つ作っているとキリがないです。
何がいいたいかというと、SASマクロの弱点は、ある機能に紐づく値をその機能自信に保持させれないということです。だってローカルマクロ変数は実行終わると消えちゃうんだもん。

そこでProc Luaの出番です。以下のコードで村人の挙動を作成します

proc lua;
submit;
function murabito()
    print("ここはSASむらです。")
    coroutine.yield()
    print("ここはSASむらです。")
    coroutine.yield()
    print("しつこいな、ころしてやる")
    return "----戦闘開始-----"
end
-- コルーチンを作成
co=coroutine.wrap(murabito)
endsubmit;
quit;

で、実際に3回話しかけてみると

proc lua;
 submit;
 -- 1回目話しかける
 print(co())
 -- 2回目話しかける
 print(co())
 -- 3回目話しかける
 print(co())
 endsubmit;
quit;












これがLuaのコルーチンです。色々あって奥が深いんですけど、とりあえず簡単な例です。
ようはcoroutine.yield()と書いたポイントで、一旦処理を中断して、戻すことができるわけです。次に呼び出された際はcoroutine.yield()の次の行から実行されます。
ちなみに戻り値も設定できます。
関数をコルーチンにするにはcoroutine.wrapを使えばOKです。

実は、ある機能自体に状態を記憶させるのは、コルーチン以外にもクロージャという機能で実装できます。
詳しくは過去記事「クロージャってなんじゃろ?」
http://sas-tumesas.blogspot.jp/2016/11/blog-post.html
をどうぞ。

どっちを使えばよいかは、好みとケースバイケースですが、今回みたいな単純な処理の場合、コルーチンの方がわかりやすいかもですね。カウント変数いらないし。


0 件のコメント:

コメントを投稿