星田オステオパシー

プログラミング学習日記 2023/06/02〜

2023/07/27 Fear of Macrosの続き
 Syntaxの記述がなんか納得できなかったので実験。あ、””で囲めば()はいらんのか・・

 例文を見てテンプレート部分をRaketで打ち込んで見る。ふーん・・ドキュメントでSyntax->で検索してみたけどテンプレート以外に使い道ないっぽいかなぁ・・

 ふーん・・なるほど。((_ の部分はパターンマッチなんだな(今更)。なるほどなるほど・・

 と、ここで「パターン変数」って言葉が気になったので検索。したところ、なんか見たようなページが。えっ?これはFear of Macrosの日本語版?なんか機械翻訳っぽいけど有志が作ってくれてるみたい。

 というわけで、折角なので復習を兼ねて頭から見直してみる。ふーむ・・結局syntax~ってのは内部を表すプロパティ情報の型みたいなもんなのか?

 ふんふん・・

 ふーむ・・最終的にはSyntax-rulesを使うので必要ないのかな?Syntax-rulesのサンプルでは見たこと無いような。まあでも本来はこういう仕組みになっててどんどん便利になって来て根本のレベルでの動作を意識しないで済むようになって来てると。

 一段階便利になるとこうなると。

 これはまだ動かないコードなんだけど・・えっ!#'a #'bの#'ってSyntaxだったのか・・なんかFormatの感覚的には普通のSymbolで良さそうな気がするんだけど。(後でsyntax->datumしないとは言え)もともとはこうやってSyntax
を使わないと呼び出せないものなのか?

 んで、動く版。内側のSyntax-caseでローカルな?Syntaxを作るということらしい?うーん・・まずSTXをパターンマッチで分解して、それを利用して内部のSyntax-caseでシンボルをFormatを使って作って、それをNameとしてまるごとマッチさせて生成する・・と言うのは分かる気がするのだが

 この#'aって何なんだ・・

 無いと駄目だが・・・

 パターン変数であれば何でも通ってしまうbody0でも通るなんて

 いくら考えても分からないのでGPTに聞いてみる。ほぉ・・コンテキスト?

 うーん・・取り出された要素からスコープとかの情報を取り出してマクロに適用するための仕組みらしい・・のか?まあ、そういうものだと丸覚えしても良いんだけどねぇ

 うーん、もう24時半なので寝る~。明日の田和龍虎が解決してくれるだろうきっと
 


2023/07/23 Syntax-rulesあれこれ->fear of macros
 どうも田和龍虎です!昨日はCametanさんの「Syntax-rulesあれこれ」の記事を読ませていただいて、「Syntax-caseは難しい」というところが気になって検索したら面白いページを発見しました。Racketのオンラインドュメントと同じページ構成のサイトなので公式の一部なんだろうか?


 どうやらRacketでSyntax-rules系の事を基本から(英語で)解説してくれてるようなので、この際挑戦しよう!と。いきなり興味深い部分にブチ当たりました。ぬっ!?これは・・・なんか面白いことが出来そうな機能ではないでしょうか?プログラム中に(read-line)で読み込んで直接式として評価させることが出来るとか?



 ifがマクロじゃないと駄目ってのもこの例がわかりやすかった

 パターンマッチングに持っていく流れとか(for-syntaxとやらを導入しないと動かないのですが)

 で、ここからようやくSyntax-case。同じことをもっと簡単に書けるでしょ?ということらしい(?)
 
 そしてもっと簡単に書けるのがdefine-syntax-ruleだ、と。あれ?でもdefine-syntax ... syntax-rules () ...とどう違うんだ?

 ここでChat-GPT。なるほど!言われてみればsyntax-rulesって複数形になってるわ。はぁ〜なるほどねぇ!

 という訳で明日も続けて読んでいこうと思います。






2023/07/19
 どうも、田和龍虎です!本当は手書きで馴染むまで書きまくるのが良いんだろうけど、まあオイオイやっていきます。

話題その1 またしてもCametanさんにお世話になってしまった
 例の拡張Caseマクロ。正直、あのまま自分で考えてても絶対に解決できなかった自信がある!あああありがとうございます!

 例によって書いていただいたコードを日本語訳していくスタイルで・・。
 とりあえずCondの定義から・・相当(自分なりに)考えて帰納的にちょっと理解できた気がする。e0の部分が(= 5 5)のような式って事か、と。すごく基本的なことなんですけど、このシンボルが式だってのが分かって無かったんで混乱してたんだな、と。
 しかし偽の場合にelse節がないのにエラーにならんのか?というのが疑問。うーん、もしかして実際に展開されるまで評価されないってのと関連してるのか・・この場合、実行は可能で単純に#fが返ってくるだけって事かなぁ・・
 で、節がいくつかある場合ってのも実はかなり考えてやっとこさ推理する。c1ってのは ...文法でいうと(e0 e1 e2 ...)まるごとの省略形って事か・・な。だとしたら挙動が理解できる。

 続いて通常のCaseパターン。これを翻訳してるうちにCondの推理が立てられていった感じでした。

 なるほど・・<ってどうやって判定しようと思ってたんですけど確かにProcだ!

 で、拡張版Caseも翻訳する。そうか・・単発パターンの場合、該当なしだったら何も無いんだから別に良いのか・・・なるほどなるほど・・
 いや、勉強になりました!なんか今回こそはようやくちょっと掴めてきた気がする。
 この状態で明日はCametanさんの「syntax-rulesあれこれ」の記事をもう一度見直してみようと思います!

話題その2 Udemyのセールで物は試しと買ってみた
 なんか滅多矢鱈と評判が良い(らしい)Udemyの講座。WEBアプリを作るのに最低限必要な事柄が学べるという謳い文句で、セールで
  90%オフΣ(´∀`;)
 の2200円くらいだったので・・買ってしまった。コレがロクなモンじゃなかったら今後Udemyは一切無視するからな、覚悟しろ!

 うーん、やりたいことが多すぎる!


2023/07/16
どうも!田和龍虎です。今日もプログラミング学習やっていきます。改名したのでなじませるために毎回挨拶していくことにします!

話題その1 ラテン方陣のお題
 Cametanさんのところでお題が出ていたので・・
 なるほど・・・出先でChromebookしかなかったのでPaizaでやると・・


 Read-lineで列の数を入力するようにしようと思ったんだけどなんか出来なかったので・・(^_^;)
 あと、RacketだったらFold使うんですけど・・(と言い訳)。
 明日これを日記で書いてから解答見ます〜
 アッ!answerがanserになってるwこれは恥ずかしいw

話題その2 Caseの拡張(挫折編)
 4人のキングを書いててたびたび

 Caseでこういう、条件式を混ぜた書き方が出来たら楽なのに・・と思いまして、もしかしてSyntax-rulesを使ったら書けるのかも?と挑戦

 正直、Syntax-rulesの事は例によってスッパリ脳から消え去ってるのでちょっとChat-GPTでたたき台を作ってもらう。珍しくちゃんと動く作例を出してくれました。
 で・・とりあえず昨夜は駄目でした。うーん、(cond ... のところに(orを噛ましてPatternが複数の要素を持つ場合には条件式と判断して・・ってできそうな気がするんだけど・・もうちょっと粘ります。


2023/07/14 4人のキング、もう少しで下書きが終わる、か
 コツコツとコードを書いててようやくCQ(クラブのクイーン)まで到着。
 と、思ったらなんだよこれ〜(^_^;) 仲間を入れてパーティを組めるというのは分かってたんでバトルシステム部分に頑張って入れたわけだけど、一回限りのカプセル怪獣的な傭兵システムが突然登場。当然のように使い捨てのシステムなので他に応用は出来ない(ついでに言うと今作ってる「四人のジャック」には仲パーティが組めるイベントは無い)。

 ちょっと考えた結果、傭兵は「アイテム」扱いにして持ってる場合には戦闘時に代理戦闘可能関数を呼び出して判定させるようにするか・・・と。
 防具は常時装備形式にして、武器は戦闘ターンごとにどの武器を選ぶかを指定するゲームブックのラピュタに近い方式にすれば、装備の煩わしさと「研ぎ屋システム(なんてのもあるのだ)」の処理も楽になる。

 とにかくイベントごとに独自の処理を求められるんで、ナウシカ・ラピュタのゲームブックと違って毎回考えるので・・ある意味楽しいかな。データ処理の連鎖とか「あ〜ハイハイ」って感じで抵抗は感じなくなってきましたねぇ。そういう意味で言うと、ナウシカ→ラピュタ→四人のキングってのは意図したわけではないけど上手い具合に段々と複雑性が上がってるので学習としては良かったなぁ〜と。

 とりあえず今やってる(四人のキングって本の中の)「四人のジャック」が終わったら、他の言語で「四人のキング」「四人のクイーン」を書く挑戦をしてみると良い学習になりそうだな?出来るだけ思想が違ってる言語が良いはずだろうから候補はRUSTとPYTHONあたりかな?

2023/07/10
話題その1 CoA終了
 カースオブアジュアボンド、やっとこさクリアした!これで多少はプログラミング学習に時間を割ける・・かなと思ったんですけど、まあ4部作だからなぁ・・。Secret of silver bladesとPool of Darknessまではプレイしないとケリをつけることにならないか・・

 ところで・・ラスボス撃破後の流れなんですが、画面をキャプチャして後でゆっくり翻訳しながら読むといういつものつもりでいたら、本編ではEnterキーで行われるメッセージ送りがAnyキーになってたものだからキャプチャキーで送られてしまってキャプチャできてないじゃないか!Youtubeで攻略動画を探して確認するか・・

話題その2 四人のキング進捗
 ようやく四人のキング、ハートのキングまでの下書きが終わった。後はクローバーのキングまで作ったら実際にカードデータを作りながら清書とテストをやっていこう。しかし人間の柔軟さを前提に作られてるシステムなので、イベントごとに例外だらけで・・Fold-Evalシステムでやると決めたけど、どうしても対応できないのは一つのクロージャに様々な機能を詰め込むことになってしまって・・汚いコードになりそうだぁ。

2023/07/04 生存報告
 なんだかんだで忙しくてちょっと前みたいに腰を据えてとコーディングが出来ない・・・忙しいって言っても宿直先で「しっかり眠る」とかFODで「アニメを見る」とかなんですけど(^_^;)
 4人のキングは現在クロージャ作成でハートの8。もうすぐハートが終わってクラブをやって一応終了。そこからはテストと、カード&アイテムデータの作成って感じですか。
 ハートの8は呪いの館。お金を払って(マルチプレイの場合は)敵プレイヤーに呪いをかけることが出来るのだw
 うーん・・ステータスはスロット一個にシンボルをリストで追加していって、Main-readで毎回読み込んでバッドステータスで条件ワケして・・と予定してるんだけど・・とにかくナウシカとかラピュタの時に比べてイベントが多彩なんで、ちゃんと覚えておいて後で対応した形に整えていけるのかが不安だな〜。こういうものこそ一気に作ってしまうべきなんでしょうね。


2023/06/29
話題その1 CametanさんのUNIX話
 非常に興味深い話だった。実はコンピューターの歴史とか好きなんですよね!

 いや〜・・ゲームをしたいという理由でOSを作るって・・プログラミングガチ勢は違いますね(^_^;)
 ちなみに、僕のプログラミング学習の近況ですが・・相変わらずで4人のキングのイベント用クロージャをPaizaで下書きしてRacketで清書して・・というのを続けてます。宿直中はAD&DのCoAをやってるんでちょっとリズムがずれてしまってますけど。CoAは3つ目の入れ墨を消すことに成功しました。
 こんな感じで既存の組み合わせで作れない部分をどんどん追加してってる感じ。

 Wordstar!聞いたことありますね!なんか海外ドラマ「Game of thrones」の脚本家が今でもDOS版のWordstarを使って脚本を執筆しているとか?いや、分かる分かる・・僕も昔NECのモバイルギアってのを使って毎日日記を書いてたんだけど(毎日大量に書くので手書きでは追っつかないのだ)、初代のいわゆる「DOSモバ」が昇天してしまった後にWindowsCE採用の次世代機を使ったら微妙なラグで気持ち悪くて仕方がなかった。DOSのPCなんてメモリ640KBとかでしたもんねぇ・・今や8GBが当たり前なんだからそりゃテキスト入力(しかも変換なし)だったらDOSで十分ですよねぇ

 重い・軽いで言えば・・こないだ試した知り合いの関わったゲーム「ブライト・トレーサー」、あれ我が家の最強マシンでも全然話になりませんでした。もっと軽い環境でも遊べるものにした方が試しに遊んでもらえる率も俄然高くなると思うんですけどね。最近のゲーム、あんまりにもグラフィックに重きを置きすぎじゃないですかねぇ?最近のニュースでファミコンを始めとしたレトロゲームが人気で中古価格高騰ってのがありましたけど、そういう事なんじゃないですかね?グラボなんて120Wとか電力食ったりしますもんねぇ・・環境破壊待ったなし!その点ニンテンドーSwitchとかは初代ファミコンと同じ4Wとかなんですよね、エラい!

 (^^) そう言われてみれば本の表紙デザインも思わせぶりではありますねぇ!

 なるほど!VAIOは分解の経験が無いですが、NECのノートやThinkpadは確かにパーツ交換のためのアクセスが非常に良かったですね!一方でパナソニックのレッツノートはほぼ全バラシにしないとCPUの交換がままならないということでジャンク界隈では嫌われてる模様。


2023/06/25
話題その1 SlimeとかRacket用コードブラウザ
 例によってCametanさんから色々と教えていただきましたm(_ _)m
 Racketの▼からそんな機能が呼び出せたとは・・Paiza-ioの時もそうでしたけど折角用意されてる機能を全然使えてないな、マニュアルを読まないクセを改めようと思いました。
 とりあえずリンク先はザーッとチェックしてみます!ありがとうございます〜
 この記事のコメント部分にたっぷり書いて頂いてるので興味有る方は是非どうぞ!

話題その2 プログラミング続けてます
 Paiza-ioで下書きをして、Radketにコピーして仕上げ・・というのをコツコツ続けています。
 だが!FODのアニメと再生PCでのゲームで時間が減ってるのも事実。結局最後は時間の使い方か〜。
 あ!
 
 Cametanさんオススメの囲碁ゲーもスマホに入れました。雨宿り中にちょっとプレイ。囲碁ってこういうルールだったのかw ヒカルの碁は全巻読んだんですけどねぇ(アニメ見るまで佐為って女だと思ってた)。

話題その3 知り合いの作ったゲーム
 何度か話題にした知り合いの女の子が昨年からゲーム制作会社に勤め始めてます。この5月についにプログラマーとして関わった新人グループが(恐らく研修の一環として)開発したゲームがSteamにて無料配信されてるというのをお聞きして早速チェック!

 その名は「ブライトトレーサー」。サイバー&3D版初代マリオみたいな感じかな?まずド派手な画面に圧倒される!ふ(←ペンギン)とかの世界とは全く別次元だw
 早速例のもらいものゲーミングパソコンにインストール!クリアして感想でも報告するか!と思ったのだが・・ドラクエベンチ3400程度のマシンではOPTION画面で画質を落とすのさえもクソムズい!一応チュートリアルを開始することは出来たのだけどとてもじゃないけどまともなプレイは不可能なのだった(-_-;)
 Core-i73632QMマシンならばもうちょっとマシだろうか?試してみるかなぁ・・本当はSteamとか入れたくないのだけど。

 もしよかったらご覧のみなさんもプレイしてどうぞ(^o^)


2023/06/21 Bing-Chat(ChatGPT4)にDrRacketについて訊いてみる
 前に書いたけどRacketのIDE、DrRacketで1つのファイルを擬似的に別ブロックに分けて管理する事は出来ないのか?もしかして誰か作ってくれたりしてないか?と思ったので尋ねる。
 うーん?なんかトンチンカンな事を言われてるような?特にScribbleについてはただのドキュメントエディタっぽいな。SLIMEはLisp関係で聞いたことがあるのでちょっと調べてみるかなぁ・・(確かCametanさんがEmacsでCommon-lispを使うのに紹介してくださってたような)。

 ちょっと食い下がってみる。DrRacket自体もRacketで書かれているということなので、もっと学習を進めれば自分でいじったり出来るようになるのだろうか?まあ、壮大な目標ではあるが。

 上の質問に対してBing-Chatの返答。いや、そういうのを求めているわけでは・・と思ったんだけど、これ面白いな!なるほどマクロで入力時の書式を整えて関数かデータか(あるいは更に他の何か)を明確に区別するというアイデアを示してくれている。これは理解しやすくて効果も目に見えるマクロの使い方だな!


2023/06/19 4人のキング、前のスタイルに戻す
 考えた結果、今回はコード量を減らす方向で・・。全部クロージャを貫くパターンはいつか自分で何かを作る時に使えそうではあるので良い学習にはなったしヨシ!
 あ、各クロージャの分岐は書式を統一するために、IFが真の場合には別クロージャを呼び出す、偽の場合にはスルーさせるとしました。気持ち良い!

 高速WIFI使い放題、自宅から徒歩2分の図書館のテラスにて、YoutubeでジャンクPC修理動画を流しつつPaiza.ioで細かいことを考えずにリラックスしてテキトーに「4人のキング」の関数やらデータを下書き。天国かな?



2023/06/18 4人のキングの全クロージャ貫きスタイル実験
 スペードのAで使うクロージャは全部でこんだけあります。これを全部貫通するように書いていくとどうなるか?

 あ、ちなみに前までselectからの脱出で直接Main-readを呼び出してましたけどこれもクロージャにしまして・・

 前は引数をもたせる必要がなかったSelectですが、判定の結果が真なら引数の0番目、偽なら1番目を選ばせてWORLDインスタンスの使ってないスロットWORLD-WINに次に動かしたいクロージャを忍ばせるように変更


 CARD-F-LISTの次のクロージャに送られるのですが、このときにクロージャ内でWORDL-WINに入ってるクロージャと現在のクロージャが一致すれば実行され、一致しないとスルーで次のクロージャに回される・・という仕組みで行けそうな気がした。

 WORLD-WINにクロージャを入れておいて、各クロージャには冒頭で自身のクロージャとWINを比べて一致していれば実行、していなければスルーさせるようにしておけば可能っぽい

 実際はこういう感じかな?うーん、テンプレとしてしまえば気にはならないかも知れない。あ~どうすっかな~・・まあ、こっちの方が一貫性があると言えばある・・気もする。
 ただまあ、明らかにコードの量は増えるよなぁ。スタイルとしては面白そうな気がするんだが。
 


2023/06/12 どこでもプログラミング
 昨夜はWIFI完備の宿直だったんだけど今週は週7宿直の上に清掃バイトに子守に呼ばれて全力で遊んで、お風呂清掃で張り切って天井のカビトリをやったら一気に眠気が!あ〜何も出来なかった。
 という訳で本日、ちょっとでも進めようとC200MAを持ち込みました。こいつはChromebookなのでもちろんRacketを使えないのですが、モニタ問題さえ解決すればアレがあるじゃないですかアレ

 そう、懐かしのPaiza.io!クラウド形式のエディタです。こいつはSchemeも使えるから好きだ。もちろんRacket文法は実行できないんだけど、対応()の表示に自動インデント、共通している関数は色も変わるし地味に画面上に入ってる単語についてはオートコンプリートもあるという充実ぶり。これなら下書きとして十分すぎるほど使えますね!Pomeraはやっぱり無理があった(-_-;) Pomera(初代)は文字コードもShift-jisだけだったし。
 この調子でC200MAを使い倒してやるわい!

 あ、ところでPaiza.ioがもっと便利になるワザを発見した!Paizaのエディタが気に入らなかった理由としてエディタ以外の部分の無駄な表示部分の存在があった。もっとエディタ部分を広く使わせてくれよ!と。
 でもワタシ気づいちゃった・・ブラウザの表示を75%くらいに縮小して、エディタの設定でフォントサイズをデカくすれば良いじゃない・・ということに。上の画像は75%にしたものですが、かなり使いやすそうになってるでしょ?これで蘇ったC200MAの8時間バッテリーが真の力を発揮できるぜ!


2023/06/09 四人のキング、CARD構造体スロットが汚すぎる問題
 四人のキングは通常バトル部分が一応終わったので、次に懸念のメインREPLでのCARD構造体の処理を考えていかないといけない。暫定でこんな感じで作ってたけど・・自分で言うのもナンだけど吐き気がするほど意味不明だ。CARDで発生するイベントが「戦闘を受けるかどうか」「運試し」「戦闘」「降参あり戦闘」などなど不定数で順番も一定しない処理の連続で出来てるためだ。そのため、CARDインスタンスごとに各スロットの役割がマゼコゼになって行く確信がある。いや〜・・なんつーか、こう・・ブロック化された関数を好きな順番で組み合わせてもちゃんと動くシステムって出来ないのか?と。

 例えばこれは戦闘を受けるかどうかの関数、Select-battleなんだけど・・こういうのを引数と返り値を標準化してパーツにして組み合わせて使えるようにしたい

 思いつかないので、とりあえず最低いくつスロットがあれば全部のパターンを網羅できるのかを考えたり・・うーん、違うな

 要するにこういう感じでそれこそ関数型言語のREPLみたいにリレーしていければ・・ハッ!?

 そうか、FOLD!CametanさんにGUIの表示の時に教えてもらったアレだ!クロージャーをリストにしてスロットにセット、それぞれのクロージャが必要とするデータのリストのリストを別のスロットにセット、必ずWORLD構造体を初期値として受け取り、同じくWORLD構造体を返り値として返すようにすればCARDインスタンスのスロットは2つでいくらでも処理が出来るッ!

 グヘヘ、むちゃくちゃ興奮してきたぜ・・

 そのためにはやはりENEMYデータはWORLD構造体に収納できるように書き換えないといけないが、一気に展望が開けたぜ!



2023/06/08
話題その1 四人のキングバトル反省編
 昨日、四人のキングの動作を振り返っていて気づいた。
 しまった〜!WORLD構造体に通常’()のスロットをENEMIESを持たせておいて戦闘発生となった時点でCARDから読み込めば毎回別にENEMYを引数にして回す必要なかったじゃないか・・。考えたらナウシカのときにはすでにその方法でやってたのにしくじったなぁ・・。
 ということで昨夜追加した状態で書き直そうかと途中までやったんですけど、結果「まあ、もう書き終わったし良いか」となりました。次から気をつけよう!

 CARDインスタンスをSetで破壊的に変更するが楽なんだけど・・それをやめるとなると・・カードと同じ数の真偽要素を持つリストをWORLD構造体に作り、CARD-FLIPを参照してPlayerが訪れたあとに#fにするかどうかを決めて変更後のリストを返す、とせねばなるまい。SHOPなどはプレイヤーが離れても何度でも利用可能なのでカードは取り除かれない、つまりCARD-FLIPは#fとなる。PLYAERが訪れたカードと同じIndex番目の真偽値リストが#fとなっている場合にはカードが取り除かれた状態なのでイベントが発生しないと。これもナウシカの時にすでにやってたような。出来るだけ毎回別の方法を使ってみたいと思ってたけど、結局同じ発想になってしまった(-_-;)

話題その2 Racketの亜種IDEがあったら良いな
 Racketでデバッグしていて思ったけど、ソースをカテゴリに分けたファイル別(つまりタブ別)で管理するのが大変な気がする。テストするのにも複数のファイルとの依存関係があったりしてこんがらがるし、使用されてる関数ザッと検索する事も出来ないし。
 ・アウトラインエディタ的に縦長で一元的に管理できて左のカラムか検索で一発移動
 ・役割ごとに別段落として任意にブロック化
 ・ファイル上は1つのファイルに書かれている扱いで依存を気にする必要もなく
 ・定義はどこに書いてもちゃんと読み込まれるような・・

 そんな感じにならんかなぁ?


2023/06/03 Apply2
 カメタンさんにApplyについて興味深い話を書いていただいた。え!?なんだこのダヴィンチコードみたいな隠しメッセージは (・_・;)
 非常にソソられる!早速GPTにApplyの興味深い使い方を聞いてみよう

 あ、はい・・。普通だな!

 うーん・・これも普通だな?

 結局(apply map list '(..))のような驚きを得られるような例は出なかったな。でも、「ユーザーが作ることは出来ない」一方で「Evalと違ってバンバン使っていい」という対の関係が興味深いなぁ。使い方は分かったような気がするけど理屈に興味があるので引き続き探求を続けよう。


2023/06/02 Apply

 現在チョコチョコと四人のキングの戦闘部分を書いてて、複数vs複数の処理をやってます。戦闘結果はこのようなリストとして返ってくるのですが、これを元に敵味方のHPを増減させて新たなPLAYERとENEMYのインスタンスのリストを作らないといけない

 そこのところをdamage-apply関数としてBattle-evalに組み込むか・・とここまで作ってはたと気づいた!PlayerとEnemyって同じ関数内で回すこと能わずじゃない!?
 つまり、battle-result-listtってPlayerを中心にしたリストなので普通にCdrで回したらEnemyは串刺し出来ないわけ(ということに書き始めてようやく気づいた)。まあ、Playerの同一性はリストと対応するけど、Enemyの場合は各リストのIndexに対応するわけですね(ということ書き始めてようやく気づいた)。

 これをどうするか・・なんとか頭をひねって無理やりカウンタを設定してLoopとMapで作ったんだけど、どう考えてもスマートではない。こんな簡単そうなことなのにまたしても思い浮かばない。
 一応、自力で結果だけは出るものがひねり出せたので・・・教えてくれChatGPT!

 え?

 なんスかこれ?全くワケが分からない。どうしても理解できないのでステップバイステップで説明してくれとお願いする

 ほうほう・・なんと!

 特にココ!!カメタンさんがおっしゃってた()を外すってそういうことか!ついついList→Map→Applyと言う連鎖で考えてたけどMapに食わせる前に介入していたとは〜。なるほどこれだと非常によく分かる!思わず「バッチリ理解できました、ありがとう!」とChatGPTにお礼を書いてしまったくらい。なるほどねぇ〜。ちょっと次回はApplyのおもしろ活用法みたいなのを調べてみよう(自分では思いつかないので)。


コメント一覧

田和龍虎
@cametan_42 いつもありがとうございます!
えっ!フランス人!?タイトル画像のホラーめいた猫の画像とか公式ドキュメントに寄せてるデザインとか・・気が合うかも知れんなと思いました。
「はじめに」の中で書かれてましたけど、元々C++とか長年やってた人が気に入ってるってのと「最後にマクロと継承が理解の上で問題として残った」ってあるのが・・興味深いと言うか胸を撫で下ろしたと言うか・・
なんとまるまる(多少不自然ですが)日本語訳したページを発見したので、もう一度頭からやりなおしてます(^o^)
cametan_42
>  そう言えば、リファレンスマニュアルと仕様書(=ドキュメント?)の違いなんて考えたことがなかったです(-_-;)

もう一回改めて。
リファレンスマニュアルってのは「その言語実装に備えられてる機能の」説明書です。まあ、文字通りマニュアルだ。
一方、「仕様書」ってのはそこに書かれてある通りにプログラムを組むと、「その言語実装を自然と組み上げる」性質のドキュメントです。
この2つって似てるようでちと違う。前者はあくまで「ある特定実装の」機能の説明であり、「言語仕様」を説明してるものじゃないんです。後者は「言語仕様」を説明している。
言い方を変えると、「リファレンスマニュアル」ってのは「言語仕様書」の下にくるもので、言語実装は最低でも仕様書が要求する機能を「全部」実装してないとならない。そして「実装独自の拡張機能」に関しては「リファレンスマニュアル」が扱ってる、と。

厳密に言うとRacketは「既にSchemeではない」、言い換えると「Scheme言語仕様書(R7RS)」には「違反してる」んで、Racketの機能を調べるのにR7RSを調べるのは「間違ってて」(笑)、本来ならリファレンスマニュアルを読んだ方がいい言語です。Pythonと変わんない。
ただ、R7RS-largeがどうなるか分からんし、デファクトスタンダードのR5RSとある程度互換性を持ってる、んで、まぁ、グローバルな「Scheme」としてのパースペクティヴを持つのもいいかな、とは思っています。
そしてGaucheは「世界的には珍しく」R7RS準拠処理系なんで、この2つを行ったり来たりするにはある程度「仕様ではどうなんだ」ってのは把握しておくに越した事はないですね。

なお、ここで書くのも何だか、って話ですが、結局件のサイトを書いた「C言語脳」な人やら、一般の、特に優れてもいない「C言語プログラマ」は、ここで書いてるように「C言語の仕様書」なんざまず読んでない。
彼らは例えば「Visual Studio」の旧いC言語実装の「リファレンスマニュアル」だけを読んでて、それで「C言語を知った」つもりになっている。
それじゃダメなんだ、ってのをなかなか彼らは学ぼうとしないわけです。

>  精読って言うんですか・・厳密に定義をとらえながらの読解をしてこなかったんで、これを機会に癖をつけるように挑戦してみます!

まぁ、精読、って程せんでもいいです(笑)。
ただ、「何か疑問があったら」リファレンスマニュアルだけじゃなくって「仕様書をチェックする」ってクセを付けた方が良いのは確かです。
Python/Rustじゃどーしよーもないけど、今後、例えばC言語を使う、なんつー事があっても、実装の「マニュアル」だけじゃなくって「仕様書を確認する」と言うクセは役に立つ事でしょう。

> FEAR OF MACROS

面白いページを発見しましたね。
・・・フランス人が書いてんのかな?多分。

>> Racketのオンラインドュメントと同じページ構成のサイトなので公式の一部なんだろうか?

いや、公式じゃないですね、多分。
これ、Racketのオンラインドキュメントを作ってるCMS(コンテント・マネージメント・システム: ブログとかSNS等のWebページを構築するエンジン)と同じブツ使ってんじゃないかな、多分。
恐らくracoのパッケージでそのシステムが公開されていて、それを個人サーバーで使ってページ構築してるんじゃないかしらん。

CMSってのは色々あって、例えばPHPならブログを構築するWordPressとかWikipediaを作ってるMediaWikiとか、あるいはかつてTwitterを構築してたRubyのRuby on Railsとか、それこそGaucheで書かれたWilikiなんつーWikiを作るCMSもある(注)。
いずれにせよ、確認してないんだけど、racoのパッケージでRacketのドキュメントサイトを構築してるCMSが提供されてんじゃないかな。
それを利用してサイトを作った、って事なんじゃないか、って思います。


注: Wilikiが川合史朗さんの「Practical Scheme」と言うページを作ってるエンジン、だと思う。確か。
あと、川合史朗さんのブログ「island life」なんかも多分お手製のGauche製のブログエンジンを使ってるんじゃなかろうか。多分。よう知らんけど。
なお、2000年代にWikiが流行りだした際、その「機能」にプログラマ達がコーフンして、結構「あらゆる言語」でWikiが書かれました。この時期のWikiの登場数は凄い。
日本だとPHPで書かれたPukiWikiってのが有名で、これもあらゆるトコで使われてある種デファクトスタンダードになった。
他にもRubyで書かれたWikiなんつーのもあって(もっともRuby自体はブログシステムのtdiaryで有名になった)、あっちもこっちもWikiだらけだったのね・・・一般には殆ど知名度はなかったんだけど(笑)。
まあ、結果、今はWiki人気は落ち着いて、代表例のWikipediaくらいしか知名度がないんだけど、いずれにせよ「ブログよりも実装目的で流行ったCMS」がWikiなんです。

また「✗✗を作るには△△言語じゃなきゃいけない」って事はなくって、流行りとか作りやすい/作りづらいとかデファクトスタンダードやらはともかくとして、「サーバーで動かす前提なら何でも良い」ってのはポール・グレアムが書いてた通りで、それこそCMSなんかはJavaScript、Ruby、Python、ANSI Common LispやSchemeだろうと「何でも作れる」って実例です。
結局「流行りの言語を使った方がいい」ってのは無料レンタルサーバーとか、使用言語を制限してるサービスだと限界があるよ、って程度の話でしかないです。
田和龍虎
@cametan_42 >cametanさん

 ( ゚д゚)ハッ! 

 そう言えば、リファレンスマニュアルと仕様書(=ドキュメント?)の違いなんて考えたことがなかったです(-_-;)

 精読って言うんですか・・厳密に定義をとらえながらの読解をしてこなかったんで、これを機会に癖をつけるように挑戦してみます!ありがとうございます~
cametan_42
> 返り値あるなしもそうですけど、こういう細かい(?)違いでエラー地獄になることもありそうですね・・恐ろしい。

ありますね。
と言うか、「一つの実装だけ」を使ってる場合は問題が生じづらいんだけど、一方「ポータブルなコード」を書こうとするとネックになる事が多い。
Racketで書いたコードをGaucheに持っていく、とかその逆をやる、って場合にトラブルが生じやすい・・・まぁ、ぶっちゃけ、Schemeはあんまポータビリティが高くない、って言い方も出来るけど。

例えばwhenの返り値は「未規定」、つまり返り値をどうするか、ってのは「実装依存で良い」っつってる。
って事は、実装で次のようにしてもいい、って事を言外に言ってるわけです。

(when #t
 (+ 2 3)
 (* 3 5))

=> 5

一番目の式を返り値にする、と。これはSchemeの仕様上「アリ」なわけ。
となると、「最後の式を返り値としてる」実装にコードを持っていくと「同じ計算結果にならない」って事は重々あるわけです。

また、これも有名な話だけど押さえておけばいいトリビアは(笑)、実はSchemeの「引数評価順」は規定されてません。

"メモ: 他の Lisp 方言と異なり評価順は規定されていません。また
演算子の式と被演算子の式は常に同じ評価規則で評価されます。
メモ: 評価順は規定されていませんが、演算子と被演算子の式を
並列的に評価する場合は何らかの逐次的な評価順と一貫性を持た
なければならないという制約があります。評価順は手続き呼び出
しのたびに異なっていても構いません。"

つまり、

(+ 3 4)

と言う式を評価する際に、

3 + 4

なのか

4 + 3

なのか、ってのは「実装によって異なる」って事です。
この辺が実は「現実的なエンジニアリング言語」であるANSI Common Lispと違う辺りで、「言語実装の実験場」を意図してるSchemeの特徴です。根源的なトコで「共通動作の保証」が成されてないんで、まぁ、ある種やっぱポータビリティは捨ててるんですよね。

> 図らずも大変勉強になりました、いや~スッキリした!ありがとうございます(^o^)

いやいや。
でも、「権威ある仕様書」がないにせよ、Lispを学ぶ大きな利点は「仕様書を読む」とか「仕様書を意識する」トコにあるんじゃないかな、とか思います。
他の言語だと仕様書があろうとなかろうと「リファレンスマニュアルさえ読めばいい」ってなっちゃいそうなんだけど、Lispの場合は「仕様書の存在」の価値が他言語に比べて大きい。
仕様書には「どうしてそうしてるのか」の根拠が書いてある。これを読めるのはデカい。
ホント慣れてくと「仕様書が無い言語」を使うのが不安になる。「どうしてそうなのか」に対して「実装上の都合です」とか言われると頭に来るようになる(笑)。いいか悪いかは置いておいて(笑)。
Pythonなんかでも「どうしてそうなるんだ」ってのに対して明解な理由は提示されないからね。仕様書がないから。
いずれにせよ、「何かあったら仕様書をあたる」ってのはとても良い「癖」になると思います。
田和龍虎
@cametan_42 >Cametanさん
 はぇ~なるほど!!Paiza(Scheme)のundefとRacketの下のツッコミの違いが全然分かってませんでした。返り値あるなしもそうですけど、こういう細かい(?)違いでエラー地獄になることもありそうですね・・恐ろしい。
 図らずも大変勉強になりました、いや~スッキリした!ありがとうございます(^o^)
cametan_42
> しかし偽の場合にelse節がないのにエラーにならんのか?というのが疑問。うーん、もしかして実際に展開されるまで評価されないってのと関連してるのか・・この場合、実行は可能で単純に#fが返ってくるだけって事かなぁ・・

うん、ここだけは補足。
まず、Schemeの仕様書を見てみよう。

if:
http://milkpot.sakura.ne.jp/scheme/r7rs.pdf#7a

"構文: ⟨test⟩、⟨consequent⟩ および ⟨alternate⟩ は式です。
意味論: if 式は以下のように評価されます。まず ⟨test⟩ が
評価されます。その結果が真の値 (6.3 節を参照) であった
場合、⟨consequent⟩ が評価され、その値が返されます。そ
うでなければ ⟨alternate⟩ が評価され、その値が返されます。
⟨test⟩ の結果が偽の値であり、⟨alternate⟩ が指定されていな
い場合、式の結果は規定されていません。"

つまり、だ。Gaucheなんかで確かめて欲しいんだけど、例えば、

(if (< 6 5) 'hoge)

の結果は「未規定」と言う事になる。「処理系依存」なんだよ。

gosh> (if (< 6 5) 'hoge)
#<undef> ;; 「未規定」、つまり「決められてない」の意。
gosh>

ところが、だ。
Racketは「既にSchemeじゃない」。そしてSchemeで言うトコの「⟨alternate⟩がない」ifってのはRacketじゃ許されてない、んだ。

if:
https://docs.racket-lang.org/reference/if.html#%28form._%28%28quote._~23~25kernel%29._if%29%29

(if test-expr then-expr else-expr)

;; Racketの場合
> (if (< 6 5) 'hoge)
. if: missing an "else" expression in: (if (< 6 5) (quote hoge))
>

繰り返すけど、RacketはSchemeと違って⟨alternate⟩、あるいはelse-exprは「絶対無ければならない」。
んで、⟨alternate⟩/else-exprがないifを使いたい場合はRacketではwhenを使わざるを得ないんだ。

when(R7RS):
http://milkpot.sakura.ne.jp/scheme/r7rs.pdf#7b

"(when ⟨test⟩ ⟨expression1⟩ ⟨expression2⟩ : : : ) 構文
構文: ⟨test⟩ は式です。
意味論: ⟨test⟩ が評価され、それが真の値に評価された場合、
⟨expression⟩ が順番に評価されます。when 式の戻り値は規
定されていません。"

しかし、R7RSのwhenの場合、「when式の戻り値は規定されてない」。つまり、実はR7RSでのwhenは「副作用前提の構文」って事になっている。
そして「戻り値が規定されてない」と言う事は、例えば次の式の「返り値」は分からん、って事だ。
Gaucheだと、

gosh> (when (< 1 2)
(+ 1 2))
3

なんだけど、これは「Gaucheがサービスでやってる」って意味だ(未規定、って事は実装が自由に結果を決めても良い、って意味)。
実はこの「結果」は実装依存だ、って事を仕様書は言ってる。

エラー状態と未規定の動作:
http://milkpot.sakura.ne.jp/scheme/r7rs.pdf

一方、Racketのwhen。

when(Racket):
https://docs.racket-lang.org/reference/when_unless.html#%28form._%28%28lib._racket%2Fprivate%2Fletstx-scheme..rkt%29._when%29%29

(when test-expr body ...+)

Racketの場合、test-exprが#fの時「返り値は#<void>(つまり「無い」)」だし、text-exprが#tの時「返り値は最後の式の値」とハッキリ書いている。
この辺、ちとややこしいんだけど、「標準Scheme」とRacketだと完全に食い違ってます。
よって、条件分岐は基本なんだけど、改めて「標準Scheme」とRacketのそれらの違い、ってのを押さえよう。

また、ANSI Common Lispだと「必ず返り値はある」設計になってるんで、

CL-USER> (if (< 6 5) 'hoge)
NIL
CL-USER> (when (< 6 5)
     (+ 2 3))
NIL

なんで、実は龍虎氏が言う

> 単純に#fが返ってくるだけ

ってのは、Scheme/Racketの動作なんじゃなくって、直感的にはANSI Common Lispの動作、なんだ(CLのNILはScheme/Racketの#fだ)。
cametan_42
>> 龍虎さん

面白いからこれからコッチ使おう(笑)。

>  Caseでこういう、条件式を混ぜた書き方が出来たら楽なのに・・と思いまして

うん、いい判断です。
「言語が持ってる機能に不満があった場合」、その解決策を提供するのがマクロ、なんで、発想はその通り。

> Syntax-rulesを使ったら書けるのかも?

書けます、ね。

まずはcaseの仕組みなんだけど、まずはcondのsyntax-rulesによる仕組みを押さえてみる。

https://www.scheme.com/tspl4/syntax.html#./syntax:h2

んで、このcondの定義を改造して、caseを書いてみよう。

(define-syntax my-case
 (syntax-rules (else)
  ((_ test-key (else e1 e2 ...)) (begin e1 e2 ...))
  ((_ test-key ((key e0 ...) e1 e2 ...))
   (when (member test-key '(key e0 ...))
    (begin e1 e2 ...)))
  ((_ test-key ((key e0 ...) e1 e2 ...) c1 c2 ...)
   (if (member test-key '(key e0 ...))
     (begin e1 e2 ...)
     (my-case test-key c1 c2 ...)))))

まず、最終的にはifに展開される。そしてmy-caseを使った再帰になる、と。
節が1つしかない場合(2番目のケース)、voidを返すか#fを返すか、ってのはまぁ好みなんだけど、これでcaseが書ける、と。
で、問題は、my-caseの節の第0番目が述語なのか否か、と。
述語自体は判定出来ないんで、procedure?を使う。

procedure?:
http://milkpot.sakura.ne.jp/scheme/r7rs.pdf#82

つまり、my-caseの節の第0番目がprocedureだった場合、残りの部分にそのprocedureを適用してしまうように書けばいい。
従って、my-caseは、

(define-syntax my-case
 (syntax-rules (else)
  ((_ test-key (else e1 e2 ...))
   (begin e1 e2 ...))
  ((_ test-key ((key e0 ...) e1 e2 ...))
   (when (if (procedure? key)
        (key test-key e0 ...)
        (member? test-key '(key e0 ...)))
    (begin e1 e2 ...)))
  ((_ test-key ((key e0 ...) e1 e2 ...) c1 c2 ...)
   (if (if (procedure? key)
       (key test-key e0 ...)
       (member test-key '(key e0 ...)))
     (begin e1 e2 ...)
     (my-case test-key c1 c2 ...)))))

となるでしょう。
ギョッとするかもしんないけど、条件分岐の条件節に条件分岐を「ツッコんでいい」んだ。
論理的に間違ってなければ「実行してくれるのが」Lisp。
これでマクロ展開してくれて、ifまでレダクションが行われる。
多分こういう事したいんでしょ?

> (let ((answer 1))
(my-case answer
       ((0) 'dekiruyan)
       ((< 3) 'koretukaitai)
       ((6) 'yatta!)
       (else 'gehehe)))
'koretukaitai
> (let ((answer 2))
     (my-case answer
       ((0) 'dekiruyan)
       ((< 3) 'koretukaitai)
       ((6) 'yatta!)
       (else 'gehehe)))
'koretukaitai

ローカル変数answerが0より大きく3より小さければ返り値はシンボル'koretukaitaiになる。3の場合はelse節が実行されて'geheheになります。

> (let ((answer 3))
    (my-case answer
       ((0) 'dekiruyan)
       ((< 3) 'koretukaitai)
       ((6) 'yatta!)
       (else 'gehehe)))
'gehehe

こういう事がしたいんでしょ?
龍虎氏の目論見は間違ってない。まさしく「マクロ作成」場面です。

>> nichikon2 さん

> 貴ブログで紹介された以下の書籍を買いました!

おお、Welcome to the World of Lisp!

でも一応Lisp経験者ではあるのかな?ブログを見る限りAutoLispって言うマクロ言語使ってた事があるようなんで・・・・・・。
AutoLispはAutoCadのマクロ言語でしょ?(ExcelのVBAみてぇなもん・笑)
AutoLispはXLispって言うCommon Lispのサブセットの改造版だと思うんで、AutoLispを経験してるならCommon Lispはさほど難しくないと思います。

XLisp:
https://en.wikipedia.org/wiki/XLISP

Lispを学べばPythonなんかもかなり「分かってくる」と思います。「実用Common Lisp」の著者、人工知能学者のピーター・ノーヴィック先生(現在はGoogleにいる)も現在はPythonを使ってるので、色々とPythonとLispを比較して見ればコツが掴めますよ。
何度かブログで言及してるけど、この記事を片手にどうぞ。

Lisp プログラマのための Python 入門 by Peter Norvig:
https://www.unixuser.org/~euske/doc/python/python-lisp-j.html

まぁ、僕のブログは我ながら結構メチャクチャ、っつーか過激な事書いてんだけど(笑)、いずれにせよ「C言語のようにPythonを書く」のはあまり上手い手じゃないです。「Lispのように」Pythonを使った方が上達は早い。
よってLispを直接使わなくてもLispを知ってるとアドバンテージがある。
RustにしてもLispを知ってた方が理解が早いでしょう。と言うより、プログラミング言語のトレンドはLisp等の関数型言語に近づいて行ってる。僕は良く知らんのですが、Cしか知らないとC#のLINQを理解するのが骨だ、ってみんな言う。Lispや関数型言語を知ってればこの辺の理解はラクなようです。
いずれにせよ、Lispは「プログラミング言語の高級な機能」を理解する手助けをしてくれる。概念が色々と詰まってるんで。

あと、これもブログで何度も書いてるけど、Read-Eval-Print Loop(REPL)を理解するのもLispが手っ取り早い。PythonもREPLで動いてるし、ソフトウェアには皆REPLがある。
REPLを知ってるのと知らないのでは雲泥の差、です。これもLispなら押さえやすい。

頑張ってください。Happy Hacking!
hosidaosuteo
@nichikon2 cametanさんにお便り来てます(^o^)
nichikon2
>>cametan_42さん

貴ブログで紹介された以下の書籍を買いました!
[Paradigms of Artificial Intelligence Programming: Case Studies in Common Lisp / Peter Norvig]
これがLISPだ/J.R.アンダーソン(著者),玉井浩(著者)

今流行りのAIの原理についてさらっと書かれてあるみたいなので、勉強してみます。
hosidaosuteo
@cametan_42 うおお!ありがとうございます!片っ端から読んでみます(^o^)
今のレベルでも「いくつ関数作ってるんだ?」って感じなんで探すので不安になってたんですわ〜。現実問題としては▼になるかと思うんですけど、Slime関係も折角なので一通りさらっておこうかと〜

毎度助けていただいてありがとうございます(^o^)
cametan_42
> SLIMEはLisp関係で聞いたことがあるのでちょっと調べてみるかなぁ・・(確かCametanさんがEmacsでCommon-lispを使うのに紹介してくださってたような)。

うん、基本はANSI Common Lisp用のツールですね。
Emacsが対象だったんだけど、今はviとか、下手すればEclipseとかVSCodeとかと連携が取れるようになってるかもしんない。
また、あまりに強力なんで、Clojureとか新手のLisp用にも使えるような拡張が提供されてるみたい。
その辺はよう知りませんが。

Scheme + Emacsの場合、有名なのが、

Quack:
http://community.schemewiki.org/?Quack

これは、僕がSpacemacs使う前は愛用してました。
あとはSpacemacsで採用されているGeiserかな。

Geiser:
https://www.nongnu.org/geiser/

> 前に書いたけどRacketのIDE、DrRacketで1つのファイルを擬似的に別ブロックに分けて管理する事は出来ないのか?もしかして誰か作ってくれたりしてないか?と思ったので尋ねる。どRacketのIDE、DrRacketで1つのファイルを擬似的に別ブロックに分けて管理する事は出来ないのか?もしかして誰か作ってくれたりしてないか?と思ったので尋ねる。

多分「コードブラウザ」って言われる類のツールが欲しいのよね。
Emacsでもこういう拡張ファイルがある。

Emacs Code Brower(ECB):
https://ecb.sourceforge.net/screenshots/index.html

こういうのは確かに便利なんだわ。でもLinux系の人は「Windows臭い」っつって嫌う(笑)。
伝統的にはCtagsってのを使ってる人たちが異様に多いんだ。

Ctags:
https://ja.wikipedia.org/wiki/Ctags

んで、Racketの場合。
Racketにはコードブラウザがない。
問題は、ファイルが大きくなってきた時、定義した関数に「飛びたい」。そういう事だと思うんだけど。
Racketの「ファイル」「編集」「表示」と言うメニューの下に

ファイル名▼(define ...)▼

ってのが並んでると思う。
この右側の(define ...)▼ってのがコードブラウザ代わりなんだ。
(define ...)▼ってのをクリックするとプルダウンメニューが開くんだけど、そこに「ファイル上で定義された」関数名がズラッと並ぶと思う。
そしてそこで関数名をクリックすると、「好きな関数名の場所」に飛べるようになっている。
ちと分かりづらいんだけどね。DrRacketでの「コード内ジャンプ」はそうやって行います。
名前:
コメント:

※文字化け等の原因になりますので顔文字の投稿はお控えください。

コメント利用規約に同意の上コメント投稿を行ってください。

 

※ブログ作成者から承認されるまでコメントは反映されません。

  • Xでシェアする
  • Facebookでシェアする
  • はてなブックマークに追加する
  • LINEでシェアする

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

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