見出し画像

Retro-gaming and so on

RE: プログラミング日記 2022/02/11〜

星田さんの記事に対するコメント。

ところで気になるのが各プロシージャの仮引数「w」。これなんなん?と。

平たく言うと、環境情報、です。


まず、大枠から言うとbig-bangはマクロ、です。
これはGUI系のフレームワークで言うトコロの「イベントループ」を生成するマクロです。
GUIは基本的に、イベントループと言われるモノで例えばキーの入力情報とか、マウスの動きとかをキャッチする。

Alan Gauld氏のLearning to Programのサイトから、イベントループの概念図。GUI上ではキーボードの入力やマウスの動き、クリック情報等を纏めて「イベント」と称する。Event Loopはループしながら随時、これらの情報を受け取って処理する。

で、構造的に言うと、実はこれもREPL(READ-EVAL-PRINT LOOP)の一種です。
ただし、通常これはユーザーは作れない。
一般的には、通常のプログラミング言語層が動くレイヤーよりもかなり下の層で作られる(いわゆる端末用の「標準入出力」よりもっと原始的な入出力を扱うから)。
極端な話、ハードウェアレベルくらいの入出力を使って作られていて、そうでもなければ、OSレベルでハードウェアとの直接的なやり取りをその上で動くプログラムに渡す仕組みをAPI(Application Programming Interface)と言うんですが、それらを使って構築されます。
んで、big-bangはどうやら、そういうかなり低レベルな機構をマクロでラッピングして、Racketプログラマ向けに「明示的なREPL」として提供するマクロっぽいのね。
そう、もう一回言うけど、big-bangはゲーム作成用Read-Eval-Print Loopになってます。

んで、中にローカルマクロ、例えばon-tickとかon-keyとか、を仕込む。目的別にここに関数をハメ込むようになってるわけ。
もう一回big-bangの構文を見るけど、

(big-bang 環境情報 ローカルマクロ群・・・)

ってなってる。
それで、big-bangの第一引数、「環境情報」ってのが問題のwなの。
このブログでは古いPDF、How to Design Worldsって文書に従ってWorld構造体、とか作ってやってたけど、これが環境情報。それで、ローカルマクロ群が引き連れる「関数」にこの環境情報を手渡します。
んで、実際は構造体じゃなくても良いのね。リストでも良いし。整数でも良い。
いずれにせよ、何らかの「ゲームの現在時点の情報」ってのを纏めてて、それを最終的には定義した関数に「渡す」と。
従って、big-bangのローカルマクロに仕込む関数には必ず「環境情報を受ける」引数がないとならない、と言うデザインになってるみたいです。



こっちはUFOの時のものですが、この時も「current-state」が謎だったんですよね。どこにも定義されてないし組み込みの定数とかでも無い。

そう、そこのcurrent-stateってのがbig-bangの環境情報を受け取る引数です。
そしてadd-3-to-statebig-bangの環境情報に3を足して、返す。結果、big-bangの環境情報は更新される。
そしてstate-is-300は、big-bangの環境情報が300を超えたかどうか判断する述語でしょ。こっちの方もcurrent-state引数でbig-bangの環境情報を随時受け取ってる。



 UFOの時のbig-bangの引数として「0」が置かれていて、これが怪しい・・。初期値として渡された後は、各プロシージャの実行ごとに変数として更新され続けるって事か?

そう、その通り。
big-bangの環境情報の初期値は0でスタートする。on-tickは時間をカウントするマクロだから、カウントされる度add-to-stateは環境情報に3を足して返す。
だからbig-bang上の環境情報は0 -> 3 -> 6 ->....と増えていく。
そしてstop-whenマクロはゲームの終了条件を司るマクロだから、state-is-300にも逐一big-bangの環境情報を渡します。そして環境情報が300を超えた時、ゲームは終了となる。


 で、今回のGUI版GuessNumberのBig-bangだけど初期値として構造体「interval」を取り込むって事か・・?「lower」 「upper」も。 

取り込む、と言うより「そこでinterval構造体の具体的なデータを定義してる」って事かな。
12歳からはじめる ゼロからの Racketゲームプログラミング教室(大嘘) その2」でも書いたけど、big-bangってマクロは事実上、名前付きletの変種、だと考えて良いです。
つまり、

(define (start lower upper)
 (let big-bang ((w (interval lower upper)))
  ...
  ...
  ...))

って書いてるのと事実上は同じ(もちろんこのコードでは動かないんだけど)。
違いは名前付きletの場合、データ定義の際に「名前を付けないとならない」(この場合はwにしている)んだけど、big-bangは暗黙になんらかの名前を付けてるのね。こっち側からは知りようがないんだけど。
いずれにせよ、何かしらの「暗黙の名称」を用いて、ローカルマクロに(このケースでは構造体intervalを用いて作成した)「環境情報」を手渡してる。

が、その後にあらゆるプロシージャで「w」ってがの出てるのが分からない。Racketの関連の矢印?で見てもプロシージャ内でしか線が繋がってないし。

もう一回繰り返しますが、「big-bang内で使われてるローカルマクロが使う関数」は全部引数にbig-bangの環境情報を取らないとならないです。
wは全部それ、ですね。たとえそれを本体内で利用しなくてもbig-bangは「そういう関数のスタイル」を要求してます。


 試しにbiggerだけ仮引数を「o」にしてみたけど別に何事もなく動くし。うーん・・?

そう、仮引数はどんな名前にしても良い、からね。

Big-bang内で実行されるプロシージャは引数を自動で(今回は構造体から)取り入れて動くって事・・なのか?

そうそう、そう考えて良いです。
実際は、big-bang内のon-keyとかto-drawなんかのローカルマクロが関数が形作ってるクロージャに情報を送っています。

ここらへんの考え方は凄かった・・こういうのを思いつくのがプログラミングの醍醐味なんですかね!

まぁ、「思いつく」と言うよか、関数型プログラミングのセオリー通り、って事かな。
慣れればすぐ出てきますよ。
ただ、「PythonでC言語的な書き方」を指南されたままだと出てこない、ってだけの話です。
「プログラムはフィルタリングするように書け」って事ですかね(※1)。

※1: C言語の名誉の為に言っておくと、元々UNIX上でのCプログラミング指南も「プログラミングはデータをフィルタリングするように書け」であった。
言い換えると、C言語の本来の使い方も「データの改変」は良くない、と言う意識があったのだ。
結局、これは、大学のミニコンと言う、(当時の)パソコンよりも遥かに優れた環境だから成せる技だった為、DOS辺りに降りてきたC言語環境では、そういう「UNIXが指南してたプログラミング上の哲学」は伝わらなく、「破壊的変更だらけ」のプログラムを書くようになって、それが今にも伝わっているわけだ。
  • Xでシェアする
  • Facebookでシェアする
  • はてなブックマークに追加する
  • LINEでシェアする

最近の「RE: プログラミング日記」カテゴリーもっと見る

最近の記事
バックナンバー
人気記事