2023/10/14 オセロの「0」出力バグを観念する
ずっと引っかかってるMinimax戦略が最後の手になると盤面が埋まってるのに「0」の手を返してきて終わらない問題。0が出て来る場所は分かるのに原因が分からなくて詰まってたのですが、もう面倒なので終了手順に(zero? move)を追加しました。
これで解決!どうせ探索の学習なんだからとっとと諦めてこうやってりゃ良かった。
詰まってる間に読書として探索の続きを読んでるんですが・・なんかすごいところまで行くんですね。αβカット辺りまでは「なるほど」という感じだったんだけど、その後マシン内で時間をカウントして制限時間機能をつけたり世界最強のオセロアルゴリズムを簡易的に実装したり・・楽しみだ!と言っておこうか・・大変なのは一緒なんだから。
2023/10/13
話題その1 読書
Qiitaでオススメされていた本の一冊。Udemyの教材でWeb開発コースをやってればいずれはJSは出てくるのでコツみたいなのが予め分かってれば効率良いかな?と。まあ、読書に逃げてるって話もある(オセロの移植が難航してるので)。
話題その2 ASUS FlipC101PAを活用しないといけない
ということでChromeの機能であるLinux機能をちゃんと使えるようにイジってみる。とある理由でFirefoxとSimplescreenrecorderが使えると非常に助かるので試してみるが、まずFirefoxがどうしても入らない。公式でのやり方、Qiitaでのやり方も試すが駄目でどういうことだ?と。
結論から言うと101PAのCPUがArm系だったのが原因。
具体的にはterminalからapt searchでFirefoxを調べて詳細でArm64と入ってるアプリ名を記憶しておいてapt installで指定すればオッケイでした。
で、次はSimplescreenrecorder。これは普通にインストール出来たんですが、いざ録画してみようとすると真っ黒!ネットで調べるとカーネルのバージョンでそういう事になる模様。じゃあもうどうしようもないので諦める。うーん、惜しい。
話題その3 Debian norootの衝撃
2021年末に購入したKindleFireタブレット10インチ。PDFファイルの閲覧くらいしか活用できてなかったが、他に使いみちは無いものか?ゲームとかは専用機でやりたいタイプなので使わないし。
AndoroidOSを削除してLinuxを入れたり出来ないのか?とか思って調べたけど「不可能」とのこと。だが!なんとAndroid上でLinuxを動かしてしまうというアプリがあるという。マジで!?
マジでした。外付けマウスとキーボードが必要だけどインストール一発ちゃんと動いてます。
ただこうなるとFireの非力さが恨めしい。結局1万円程度の底辺タブレットであることには違いがないのでパワーが必要な作業では無理があるのだった。まあ、まだちゃんと使ってないけどウィンドウの移動のラグとか見てたら予想出来る。
将来的に高性能タブレットを買う意味が一つ発見できたというのはありがたいかな。
2023/10/12 オセロの問題
まだ詰まってます! うーん、なんでMinimaxの時だけ盤面が埋まってるのに指し手として0が出され続けてしまうのか?Minimaxをどう眺めてもMoveで0が返ってくる仕組みが分からない。
と、思ってたんだけど!通常停止ボタンを押してもすでに莫大な命令が実行されてしまった後なので見られなかった部分を発見
おいおい!この時点ですでに勝負がついてしまってると判定されてるじゃないか!
ほんで、その後で最後まで埋まって・・これは解決のヒントになると思われる。終了判定がおかしいんだな?
2023/10/08
話題その1 オセロの探索 うーん
うーん、駄目だ。探索で0が返ってくることがあるんだけど原因が分からない。0なんて返ってくるのはFinal-valueくらいしか無いんだけどなぁ・・
他人が作ったものを追っかけてても理解できそうな気がしないので、Minimax探索を別個で一度作ってみよう、と決意しました。
話題その2 バイト先PCのベタベタ天板をなんとかする
バイト先で(実際上)もらったパソコンThinkpad。画像ではちょっと分かりにくいけど天板がゴム加工されてたのが加水分解で超ベタベタ。以前からアルコールや洗剤でなんとかしようと思ってたんですけど全然駄目。
ネットで同様のことで困ってる人に対しての回答で
「リメイクシートを貼り付けるしか無い」
というものを見つける。なるほどリメイクシートか・・アルコールでキレイにしてもいずれまたベタベタになるらしいね。
というわけでバイト前にダイソーに寄って物色。おっ!なんか石材っぽいのがある。ということで早速貼り付けてみました。
画像ではちょっと分かりにくいかも知れないけど・・ムッチャ良いよコレ!天板は端にアールがついてるのでセロテープで外周を補強したけどシートが光沢素材なので気にならず。見た目も手触りも完璧!やる気が湧いてきたぜ〜
2023/10/06 Bodhi Linuxを7にした
愛用の超軽量Linuxの「Bodhi Linux」の最新版7が発表されていた。別に6で不具合があるわけでもなかったけど、容量がわからなくて色々と余計なものも入ってるので、この際キレイサッパリ入れ替えてしまうか!と。
バイト先に持っていってるマシンを持ち帰ってUSBに入れたBodhiのイメージからインストール。
更に自宅で使ってる元ChromebookのCB3-111Mにもインストール。こっちはバッテリーが生きてるので図書館で普段使いするソフトは全部入れました。その結果・・残りストレージ容量3.2GB!ギリギリ!もともと16GBしかないのでしょうがないけど最低限でも13GB近くもあるのか〜・・。
実はイメージの容量は半分の700MBくらいしかないBodhi-Linux5ってのもあるんですけど、そっちはPAE非対応だったかな?の本当に古いマシンでしかインストールできない模様なので泣く泣く諦める。けど7をちょっと使ってみた感じ特に6よりも遅いということは無いので全く問題は無いですけどね!いや〜Bodhi-Linux良いわ〜
2023/10/05 オセロもうちょっと?
前回、Bing(GPT4)の助けを借りてなんとかMinimaxが出来たような気がするところまで行きました。ただ、そのままだとストラテジーに使えないので中間のMinimax-searcherを用意しないといかんらしい。お手本をScheme(Racket)に翻訳する。えーと、Searcherの引数がPly Eval-fnで読み込まれて、内部のLambdaで追加のPlayer Boardも受け取れるようにすると。で、このPlayerとBoardはどこから来るかと言うと
メインであるOthelloの中で呼ばれるGet-moveのStrategyが今回はMinimax-searcherなので、そこで引数にPlyaer Board Printが呼ばれてて
更に元のGet-moveはこうなってるのでSearcherのLamda呼び出しに書けば束縛できるのだと。なるほどなぁ〜
話は戻ってLet-valuesにValueとMoveとして束縛してるんだけど、実際に返してるのはMoveだけか・・じゃあ元をMoveだけ返す関数にしても良さそうなものだけど・・?
そういう訳で、前回Bestだけを返してたトコロがこのままではSearcherに合わないのでエラーが出るので合わせないといけない。うーん・・
やっぱりどうせMoveしか返してないからBest-moveしか返さない方に合わせておく。なんか不具合でるかなぁ?
で、動かしてみると-3という手を選んでエラー。んなアホな?
前回Bingに作ってもらった部分を見返すと・・
Fuck!なんでLet loopでMoves best-move best-valにしてるのに後の呼び出しでLoop (cdr moves) val (car moves)になってるんだよw
AIもまだまだだなぁ・・こんなケアレスミスをやらかすとは・・というわけで書き換えると
まあ一応最後までは行ける。だがなんかおかしい・・
対Humanでやると違和感の正体が分かった。前に気になってたけど放置していた最初のターンのみBlack側のStrategyがWhiteにも適用されて、結果Strategyが入れ替わってしまう問題が発生しているのだった
じっくりと考えてようやく分かった。プレイヤー入れ替え時にGet-moveのストラテジー選択もIfで場合分けしないといけなかったのだ。名前付きLet*があったらなぁw 解決!ちゃんと正しいストラテジーが選ばれるようになった!
だが更に問題が。うまく終わる時もあれば、もうさせる場所がないのにゼロを返す場合もある。もちろんこんな事をするのはMinimax-gptなのだが・・0?0と言えば・・Loopの初期値がゼロ。怪しい・・ってところで今日はここまで
2023/10/04 オセロの探索にようやく光明
オセロの探索部分、何がツラいって「適正な挙動」が分からない事。判定とループが入れ子になっててCLのLoopが分かってないのが悪いんですがね!
そこで何とかGPTにSchemeかRacketでのちゃんとした挙動をするサンプルを作ってもらおうと思ったんですが・・無理。
じゃあ人力でPAIPを移植してる人いないのか?とネットを探し回ったけどPythonにしてる人はいる!そしてSchemeにしてる人もいたんだけど・・オセロのある18章だけ見事に飛ばしてるんだよなぁ・・やっぱり難しいんじゃないか!?
ここで思いついた。そう言えばまだBARDとBINGがあるじゃないか?
まずGoogleのチャットAI「BARD」にお願いしてみる。結果、クソコードしか返ってきませんでした(ちゃんと注意してるのにNilとか破壊的変更が入った上に動かないコードを返してくる)。
じゃあ次はダメ元でBingで・・・あれ?なんか良さげじゃないか?僕が手書きしたのに非常に似てる
実際動かしてみると・・深度7の先読みで−24。なんだよ−って?
深度5で今度は一転46。これは最適な手(46に打てという事)ぽいなぁ
同じ条件で自分で書いたのと結果を比べてみる。深度3の結果は0
Bing(GPT4)の結果は−3。何だよ−って・・?うーん、考えられるのはFinal-valueが積み重なった結果かなぁ?
Bingでこの盤面からだと−3・・
この盤面からだと−2
この盤面からだと43。これは43に打つのが最適って事だろう
この状態で深度0を放り込むと最終手持ちコマの合計が返って来る
既に勝敗は決してるのに更に先読みをしようとすると0が返ってしまう(これは本来ありえない状況だけど)
ここの部分は僕が書いたコードでも一緒
けど、このような状態だと同じ先読み条件で実行しても結果が違う。Bing版では76というWを挟める場所の指定が行われる。
結論、Bing版が本来の挙動をしてると思われる!
そこで俺版とBing版の違う部分に着目して学習することが可能になったワケだ。違うのはこの名前付きLetでのLoop部分。これ、俺版
そしてBing版の該当部分。ifのワケ方が問題のようだ・・明日以降でちゃんと考えてみよう。今日のところはとりあえず・・
Bingにお礼を言っておくか!
2023/10/03まで
話題その1 Udemyで買ったコースを(気分転換に)始めてみる
とりあえず世界で70万人が受講・・てのを始めてみる。セールで1200円の時に買ったんだけど無茶苦茶なボリューム。とりあえずHtmlのところまで終了。やっぱりちゃんと基本から聞いてみるとタメになるな〜。
ところでUdemyって結構な数の「無料」講座があるんですよね。少なくとも多少の英語学習にはなるはずなので、試しまくるのも良いかも知れない。
真ん中のはUnityの代替エンジンとして話題になってたGodotの超基礎コース(同じ作者がもっとボリュームがあって有料のものをリリースしてる)。合う合わないを判定するのにも無料のコースやりまくってみるか?まあ、その前にWeb Developper Bootcampちゃんとやらないと!だけど。1200円で無限に遊べるぜ!
話題その2 Bohdi-LinuxにVScoeを入れる
HtmlとかCSSの学習、普通にテキストエディタで打ち込んでも良いんだけど折角なのでVScodeを使いたいな、と。が、Bohdi-Linuxの場合SnapdとかFlatpakがデフォルトで入ってないのでインストールできないのだ(と言うことを知るのもちょっと大変だった)。
で、その後はココの内容をそのままターミナルでコピペすればオッケイでした。SnapdとFlatpak両方共試したけど絶対にFlatpakがイイっすね!
2023/09/30まで オセロ Minimax戦略とやらが難問、これちゃんと動いてるのか?
前回まででランダムストラテジーと次の手で出来る限り枚数を取れるストラテジーを実装完了しました。
今回はまずオセロ特有の有利な箇所を優先的に取る重み付けストラテジー。まずはCL用コードをGPTに放り込んでコメントをつけてもらう。ふんふん
ついでなのでちょっとCLのLoop構文について教えてもらう。ふ〜む・・まあこれくらいだったら名前付きLetで行けそうですが・・確かLand of Lispで見開きまるまる使ったLoopの機能一覧みたいなのがあったはずなので、こんなものではないはず。またLoL読むか・・メルカリで買っても良い!
ま、それは置いといて・・重み付けVectorを用意しまして・・
とりあえず名前付きLetで作ったRacket版を走らせてみる。あれ?いきなりちゃんと動いてるっぽい?
続いて・・これが難問、Minimax戦略を扱うための関数。まずはGPTに放り込んでコメントをつけてもらう(これが一番助かるわ〜)
まず補助関数を作りまして・・Signumとか要るか?って感じだけど、まあこの際なので。Final-valueもなんでわざわざ?って感じだけど、まあ本体を作っていく内に分かるのだろう、か? Losing-valueとWinning-valueはCL独自の最大・最小整数みたいなのを設定する事になってるけどRacketには無いみたいだし、別に0で良くない?って感じなので一応0に。うーん、今から考えると駄目な気がするなw
でまあ、一応「こうじゃねぇかなぁ?」という感じで書いたことは書いたんです。Minimax関数。本番ではValuesで多値を返すんですがテストなのでそれぞれ返すようにしたんですが・・0か〜w。つまり初期値から変わらずでいきなりMovesがNullになってるということ?気になるのは(- の部分。これって数値を反転させるわけだよね?うーん・・そもそも普通の再帰の中に名前付きLetを入れ込むって時点で私の(現在の・・としておこう)理解能力を超えている!!曲がりなりにも値が返って来てることだけでも拍手!と言える、と思う。
(- 部分を取り除いたらどうなるか?ということで実験。む!?これだとそれっぽい値が返って来る。つまり75番目に置くべきということ
んで、その時の重み付け得点が66点ということか・・?
同じ盤面をWhiteでやってみると46に置けという。それっぽい記がする
で、その時の値が53ということか・・・?
うーん・・ダイクストラの時も結局、本当には理解できてなかったと思うしこの探索系の書き方・動き方の理解は中ボス登場って感じやでホンマ
2023/09/24 オセロ 自動対戦問題
ではいよいよ探索か!?と思ったのだけど、その前に新たな問題が立ちはだかった。
COMのRandom-strategyで適切な手が返ってこない問題。本来Strategyでは適法な手の座標(空で最低1枚でも相手のコマが挟める座標)が返って来る予定なのにずっとイリールな手ばかり返してくる。個別でチェックすると・・ここか・・・
やっぱり自分で設計したわけではないので返り値がどうなってるのかを理解できてなかった。コレで良し!
結果、Human vs Random-strategyで最後まで動くようになったぜ!
続いて新たなCOMのStratgy、Maximize-differenceの作成に入る。とりあえずCL版をそのまま打ち込んで、逐一でRacketチックに書き直してみる。
うーん、なんだこの書き方は?
そしてMaximize関数が作っているクロージャ部分を読み込んで納得、なるほど今後Count-difference以外の評価関数(?)も組み込んで「最大」を選別出来るようにするため「ユニット化」させる書き方だったのか・・
うーん、このいきなりLambdaで引数を取り込む書き方はマスターせなアカンで!カッコいい!
で、次はStrategy部分。どうやらCount-differenceは複数の手がある場合、その中で(次の手限定で)一番多い枚数をひっくり返せる手を選ぶようなので・・まあ、カウンターをつけて数値を返せればエエんやろと
テストしてみたところ、黒は次の手番で5箇所適法な手があって、その中で座標75を選んだ場合に7枚の黒を持つ盤面が期待できる、と。
ところが実際に動かしてみると問題発生。盤面の生成は終了してるのに終了処理がないため(多分)、既にEmptyが無いのに探そうとしてRandom 0なんて出来ないぞ!と怒られる。例外処理で?とやったけどうまくいかず。
同様に場合によってはココで同様のエラーが出ることもある。終了処理が必要だ・・多分
要するに終了処理が一手遅いのでは?と仮説を立てる。盤面にEmptyがゼロになってるのに、そこでまだ手を考えてるから0を対象にしてしまうのでは?と。なので終了処理を元の{not player)(両プレイヤーが打つ手無し)で終わるんじゃなくて盤面からEmptyが消えた時点で終わらせるようにしてみる。エラーは出ないが次は最後の一手を打たないで終わってしまう。うーん、、
そこで、終了条件としてGe-move関数部分(次の手が有効であればそこに打った盤面を返す関数)にMoveを渡すのだが、打つ手がない場合には#fを渡すようにして、それを捕まえる条件式を挿入、即座に結果発表するEnd関数をぶっ込んでみる。
End関数はこう言う感じで。これで強制終了させられるのでは?と
ところが半分くらいの割合でBoardがVectorじゃないぞ!とエラーが出る。なんでうまく動く時もあれば駄目な時もあるのか・・2時間位試行錯誤する。
うーん・・・なんでVetor型じゃなくなってしまうのか?そんな事あり得るか〜?
何度もいじっている内に、前に他のゲームでVoidになったのってDisplayをかましたところだったよな〜・・と思いだして、ハッ!?
あ、End関数、副作用しか起こしてない!
試しにBoardを返すようにしてみると・・ヘンテコではあるがエラーは無い。そして結果発表が二度出ている。つまり打つ手が無い時点とPlayerが2つとも#fになった時点。そうか・・今までさんざん言ってもらってたのに、今度こそようやく分かった!と思う。
これがオッケイなのはIfが「真」を返す働きがあるからだな!?多分!
というわけで、一応Human Random-strategy Maximize-difference、全部動くようになったのでココに置いておきます。苦闘の跡が楽しめるように清書しないママになっております(^o^)
いや〜今回も勉強になったわ〜
2023/09/20 まだオセロ 複数ひっくり返す問題
さて、前回挟んだ時のひっくり返し処理が複数ラインあった場合に最初の1つしか実行されない・・という問題が発覚、まあFold的な処理をすれば大丈夫だろう・・というところまで来てました。
が、その後更に問題が発覚。上のような状態から白が57へコマを置くと間に入ってる黒が2つともひっくり返るのが通常のオセロですが
うっ!これまた最初の1つしかひっくり返らない。参ったなぁもう・・まあOthelloじゃなくてOthell-o(オセル・オー)だから!と言い張っても良いんだけど直していきますか・・
問題は多分、このWould-flip?とその補助関数Find-braketing-place
それらを使うMake-moveとその補助関数Make-flips辺りにあるのだろう
んで、どうすっかなぁ・・と思ったんですが、もう返り値の仕様を根本から変えさせてもらう事にする。もともとは再帰で間のひっくり返るコマを指定する仕様なのかと思ってたけど、Accを作って間にあるコマ(ひっくり返る予定)の座標をリストで返して、後でまとめて裏返そうと。
Foldを使って座標部分をまとめて変更するテスト。書き方忘れてたんでw
んで、各関数が予定通りのリストを返してくれるかチェックして・・
Foldを使って1ラインの座標をまとめてひっくり返すように改造して・・
先程と同じようなシチュエーションから白を57番へ・・
よっしゃキタコレ!
後はこれを更にFoldでAll-directionsに当てはめたらエエんやな?と
非常に分かりづらいけど75番目に黒を置くと複数ラインで裏返りが発生する盤面データを作りまして
For/list部分により複数(ラインごと)の盤面データが出力されてることを確認。要するにこれを1つにまとめて渡せば良いわけだけど・・この複数盤面を統合するよりも最初からひっくり返る座標をまとめて渡したほうがスマートなので、その方向で考える
という訳でBracketerに束縛する座標のリストを全ラインぶっ込むように改造する。途中で発生する#fをまずFilterで取り除いて、Appendで結合。だがこれだと((74) (55 65))という形になってしまう。そもそも#fを返さない形にすれば良いんだけど面倒なので・・Kanta-Oで作った入れ子の数値リストから数値だけを引っ張り出してくる例のアレに出張してもらう
これにて望む形の座標データが得られたので
対人戦でテスト。ここで52に白を置くと42と43が白になるはず・・
キターッ!
あ〜やっとこさコレで探索とか重み付け選択の段階に入ることが出来るな〜。
2023/09/17 オセロ
というわけで一応、探索まであと一歩!のところまで来てるんじゃないかと。いや〜進行が遅いですね!何故なら「読書」と「ゲーム」も並行してやってるからなんですね!ゲームはDSのシレン2やってます。やっぱりゲームを作るとなると最終的にローグライクっぽい仕組みになると思うんで!(言い訳ですが)。
前回までで作ったパーツを合体させまして、恐る恐る起動・・・どうせエラー出まくってバグ取りで夜を過ごすのか・・
と、思ってたのにオオッ!?普通に動いている・・今回パーツごとにちゃんとテストしたのが功を奏したか〜。
で、本家の方では表示で横に10 20 30 ... と番号が振られていた理由が分かった!自分が打つ場所の数値が分からねぇ(^_^;) そういうことか〜
適当に数字を入れたところエラーで入力し直し。マジでちゃんと動いているじゃないか(・_・;)
打てる場所に置いたら本当のエラー発生。日記にも書いてたけど変更後のボードを返す時に「ベクターのリスト」にしてて「なんか妙だなぁ」と引っかかってたところが正に問題でした。ということでCarで抜く
そして56にBlackを置くと・・おおっ!やった!
だが同時に複数ラインで取れる置き方をしてもall-directionの早い順番の1つだけが反映されておしまい、ギャーッ!
いやまあ、実は書いてる時に「これって変だよな」とは思ってたんですけどね。うーん・・変えるBoardをFoldしてひっくり返った状態を上書きしていったら行けそうかな?
次回はそこんところ直します。けど、Othello関数部分はテストしてなかったのにちゃんと動いてちょっと感動。CLの謎文法Loop使わなくても名前付きLetで全然いいじゃないか
一応動くのでコード置いときます
2023/09/13
話題その1 X68000プログラミング
インターネットアーカイブをぶらついていてある書籍を発見。X68000プログラミングの本なんですけど・・DLしなきゃ大丈夫なんだよね?ということで中身を拝見。ちょっと面白い(まだ途中)。
なんか解説がハードの構成に力を入れていてメモリバスとかアドレス空間とか・・本格的なプログラミングを考えるとそこまで考慮しないといかんのかもな、とスルー。
へぇ~Basicインタプリタモードとかあったのか!当時はそんなことも知りませんでした・・
この辺も興味深かったですね。X-BASICはC言語にスムーズに移行できるように狙ったのでは?と思しき構造になってると。実際、X-BASICで作られたプログラムはCに変換出来るとのこと。当時ちゃんと学習してればなぁ・・
まだ途中なんですけど、関数も作れるし再帰的な書き方も出来るらしい。実際に書くかどうかは別にして別言語の角度から見るのも面白かろうということで最後まで読んでみますかねぇ。なんかアセンブラとかの章もある。
実は同じくインターネットアーカイブにX68000のプログラミング言語「X-BASIC2.0」のマニュアルも落ちてたりするので・・エミュレーターで何か作るのもありかも?と思ったけど・・無いか~・・やりたいこと山積みだからなぁ(マイクロソフトがC#の公式チュートリアルを発表したというニュースもあったし)。うーん、1000年くらい寿命が欲しいな(^o^)
話題その2 オセロ、まだやってます
というか、まだ探索まで行き着いてません(^_^;) 先週はマンガウィークだったんで。
あ、その前に!前の部分で「Would-flip?が斜めで機能してない!」とか書いたんですけど、初期配置では斜めで取ることは出来ませんでしたw 斜めで取れる配置にしたらちゃんと機能しましたわ。
今回手間取っているのがコチラ。やっぱりCLはLoopが難解だのう。Thenって何だよ、forも2つあるしw ということでGPTに問い合わせをしてみる。Thenはイテレーションごとに値を変化させることが出来るのだとか。はぁ、なるほど・・まあこれはLet loopで出来そうだな。んで、Forの2つ目は1つ目のForの内容によって変化させることが出来る別の・・束縛みたいなもんか?
とりあえず、この関数が何をしてるのか、返り値を求めているのかを知るために結局先に補助関数を見ていく事にするか・・
一応Racket用に書き直したつもりで未テストのものはOk?とつけておくか。この関数のためにAny-ligal-move?を見ないと
ま、見るまでも無かったか。一つでも#tだったら#tってだけの話。Someは前回作ったのでそのまま使用。
これもテストしてみないと何とも・・今見たらWarnって何だよ、と。後で作ってるのかと思ったけど作ってなかったので調べたらCLには最初からあるメッセージを表示する関数らしい。Formatで良くない?と思うけど、色が変わるとかあんのかな。後で変更しないと
あとコマゴマしたのも作る。Random-eltはテスト済。
出ましたLoop。Collectって何だよ、って感じだけどListにまとめるだけっぽい?じゃあ・・
Forかな?と思って書いたけど(上)、あ、For/listか。テストで最小構成のものを作って返り値を確認後(下)、清書する段階で24時を過ぎたので今日はここまでにしといたるわ!と。
あと、declareという関数が出たので調べたら・・CLってわざわざこういう事までするんですねぇ・・Racketだといらなさそうなのでスルーしておきましたが