星田オステオパシー

プログラミング学習日記 2024/07/04~

2024/09/03 RustでBrain*uck、ループ部分を作り始める
 別に凝っても仕方がないのでClaude先生に書いてもらったものを丸写しする。内容は見ての通りで・・仕様メソッドが分かってれば、ま、なんとか。結局、型ごとにどんなメソッドがあるのかを調べるのが一番面倒という事かなぁ・・あと、所有権。テストの為にメソッドじゃなくて関数として実装して・・

 動くかチェック、オッケイ


 で、構想としては[]で括った内部を新たな文字列としてスライスして、ポインタにある数値回数分だけ繰り返した文字列(コマンド)を作成し、]の次からの残りのコマンドに合体させてメソッドchange_memoryに送り込む・・というものを考えた。なので関数の返り値として]の次のIndexが欲しい。よって返り値の型をVec内タプルにしておくと(これ、ただのタプルで良いだろw)。


 良いんでない?あれ?そう言えばインデックスは0からなので1つ多いか


 で、コマンド内に[があった場合に呼び出すメソッドを書く。テストはまだだけどコンパイルは通るっぽい(Playgroundなので知らんけど)・・というところで時間切れ。明日こそは入れ子無しループ部分は完成させてしまおう。警告は出まくりだけどエラーは出ないBrain*uckプログラム完成はもう目前だ!

 ということで、そろそろ次にすることを考えないといけないのだけど・・一応、何かゲームっぽいのをRustで書けたらな?とゲームエンジンを探したんだけど、日本語がちゃんと用意されてるものが無いっぽいんだよなぁ・・Bevyとか言うのが現実的っぽいんだけど全然まとまった情報がない。本も出てないし・・ここで二択。英語とRustの勉強だと思ってまだ仕様もちゃんと決まってないようなBavyで何か作ってみる、か、(Rustは良い経験になったと一旦ケリをつけて)メジャーなUnityとかGodotで動くものを作る。

 ま~今のところ後者を考えてます。あ、その前にそもそもRust開始のキッカケだった「Rustでライフゲーム」の記事を読まないとな。



2024/09/02 RustでBrain*uck、ループ部分を考え始める
 と、その前に・・前回のポインタ部分に文字入力→i32格納って言う動作のメソッド、もうちょっとシンプルな書き方が判明したのでメモ。結局Result型はちゃんと定番の方法で受けよう!って事かな。それとちょっと意外な気もするけどイテレータに対して.next()で最初の要素になるってのも。


 []でのループ、Claude先生の提案する書き方をちょっとだけ、本当にちょっとだけ見たらイメージするものと全然違っていた。前にRacket、Pythonで書いたのは完璧に忘れてるので改めて考えてみると・・[]で囲まれてる部分を取り出して(どうせ破壊的変更なんだから)、ポインタ回数分だけその新たな文字列を使っていつもの処理をすれば良くない?という事で抜き出し方を教わる。あ、入れ子ループはとりあえず考えないものとする


 で、提案されたのがコチラ。うーん、長いな!こういう役割のテキスト処理ライブラリあっても良さそうなのになぁ?

 今更だけどStringと&strってどう違うのか?と質問。

 そういう事だったのか・・分かった(気がする)。やっぱりもっと早く、ドキュメントを読みながらBrain*uckを書き始めるべきだったかなぁ・・

 結構例文も良いんですよねぇ

 で、そのままだとエラーだらけだったので一応実行でエラーが出ない形に修正した結果がこちら。目論見としては、返り値のresultの0に抜き出した文字列、1にend+1(下の文字列の続きのindex)をつけて返して、ループ内コマンドを実行したあとに続きのコマンドを実行する手がかりにする・・と。
 というのが昨日まで。今から単体でちゃんと返ってくるのかテストしてLoopメソッドに組み入れる予定、と。

2024/08/30 RustでBrain*uck、データ表示・格納部分
 現在のポインタのデータをAsciiで表示する部分。まあ、変換メソッドはClaude先生に聞いたそのままです。引数も要らないしこれはラクラク

 でも+を65個入力するのが大変だったw


 次に格納部分。文字入力を促して、それを整数値に変換して格納するってことか?これはRacketの時もPythonの時も実装してなかった気がする。

 イメージとしてはこういう感じになるのかな?空の文字列型変数を作って標準入力、それを整数値にキャストする・・ただ、文字列入力だと複数文字の入力が可能なわけで、それを例外処理したりしないといけないんだが・・例によって「注意深く入力する」って解決策を取るってので良いか?

 それよりも一文字だけ入力するという方法があるかも知れないと思って質問。あるじゃない!けど、この面倒くささ・・これはお断りしたい。まあ、ゆくゆくはオリジナルトレイト?として作ってみても良いかも知れないが・・

 紆余曲折あって、とりあえず動くものは出来た。面倒なのが返り値が「Result型」って場合で、わざわざOkとErrに分けて書かないといけないってのが・・・まあ、それがRustの売りなんだろうけどココは敢えてその利点を無視して書くぜ!どうも.unwrap()ってのがResult型の返り値を無視出来る方法っぽいな?.as_byte()[0]で戦闘の文字をバイトコードに変換してるっぽいか?そこまでやってやっとこさChar型に変換できて、それをi32に変換、と。
 時間がなくて解説をまだ聞いてないので、次回は上の検証をして・・いよいよループ部分に突入するという事に。ループができれば完成だから、次に何をするか決めておかないとな!


2024/08/29 RustでBrain*uck、やっとこさコマンド部分
 コマンドは文字列で入力してCharsで一文字ずつのイテレータを作ってFor、と。Change_pointerはまあ良いんだけど、Change_valueで問題が・・・Vecの最後尾をPointerにしてるもんだからインデックスで指定したいけど・・なんだこの見た目はw

 しょうがないので諦めてMemory構造体にVecと別でポインタ用スロットを作る。

 それに対応してメソッドを書き換えて・・


 これで4つ目の要素が3になるはずだが・・?

 なんとポインタが1に!どういうこっちゃ!?
 もしやForで回しての破壊的変更だと不具合が発生するのか!?とか疑って色々と悩んでたんですが・・
 前の実験でポインタを-5にしてたのを放置してたのと、メソッドで +=にしないといけないのに=にしてたというね・・パソコンサンデーのDr.パソコン宮永さんもびっくりの間抜けぶり・・
 

 というわけで次はDisplay部分とデータ格納部分を書いて・・[]でのループを作って終わりと

2024/08/28 RustでBrain*uck、イテレータ化メソッド
 メソッド内でメソッドを呼び出せることは分かったけど・・なんとなくだけど引数の所有権が問題になりそうな予感。ということで聞いてみる。ん~?


 つまり全部&mut selfにすれば良いのでは?

 意外にもほぼ問題がないと判明。ま、個人でなにかする場合にはって条件で。気になるのはデメリット2の並行性か・・それって何?

 もう全部&mut selfで行く気になってたけど、出してもらったサンプルが分かりやすかったので気が変わった。なんだ、こんだけの事だったのか。

 「同時に」ってどういう事?


 は~ん、ザックリと言うとスコープの範囲内ということか



 そうなると、スコープの範囲を超えてのデータの移動ってどうすんの?と、なんだこのlet data;の部分


 クロージャみたいなものか?と思ったが違ったか。はぁ~・・そういう使い方が出来るのか!これは関数内で構造を作って整理がしやすくなる気がする!覚えておかないと・・

 ジェネリック型の理解があやふやなのでまた聞く。


 解説を聞くと、何でもオッケイなのがジェネリック型に思えるけど使うのに適さない場合とかあるのだろうか?と。なるほど、適さない場合の為にトレイト境界(←ネーミングが悪いと思う)があるのか・・


 なるほどなるほど


 面倒くさいとは思うけど、超ゆるゆる体質の僕としては体質改善にもなるだろうし受け入れるかw

 で、やっとこさコマンドをイテレータとして使う段階に突入。余計な空白とかを削ぐメソッドを聞く

 別解も見る。あ、LambdaとFilterか~

 うーん、じゃあこういう感じで書き始めたら良いのかな? この段階でClaude先生に聞いてみる。Claude駆動型開発やな~

 ほう!まあ、1は問題外として興味深いダメ出しが出たな


 へぇ~!こういう細かい仕様とか・・多分コンパイル時にエラーが出るんだろうけど、意味不明だったりするだろうしClaude駆動型が使えて良かった。
 Racketの時はダメダメだったけど、Rustでのアドバイスとかサンプルコードは99%OKって印象。Racketの学習サンプルが電脳世界に少なすぎたのか、時間が経って改善されたのか知らないけど、昔じゃ考えられない学習環境ですわ(最近、大昔のパソコンサンデー動画を見てるので特にそう思う)。

 というわけで、次こそ心臓部分に取り掛かります


2024/08/27 RustでBrain*uck、メソッド実装中
 とりあえずメソッドで手軽に作れそうなポインタの数値を変更するものを書いてみる。けど書いてから入力した文字列をコマンドとしてメモリを操作する中の一つなんだから独立してく作ってもしょうがないか?と。同じ構造体の別メソッドから関数みたいに呼び出して使えるんだろうか?

 メインで標準入力を使ってコマンド文字列を保存して・・あれ?そう言えば標準入力っていくつか種類があるな?あと、文字列をバラしてイテレータにする方法が分からん

 おお、なるほど!

 うーん・・とりあえずRead_lineで良さそうかな。

 あとは文字列.char()で作ったイテレータをForで回してMatchで場合分けしてループさせるようにしたら良さそうかな?寄り道ばっかりして全然進まないのであった



2024/08/26 RustでBrain*uck、まだメモリ構造体

 一夜明けて、昨日書いたものをまた書いてみる。ま、また書けない・・全然身についてないじゃないかw



 Vecの最後尾をピンポイントで狙うメソッドがあるということで、それを使ってポインタ(Vecの最後尾をポインタに使う)の数を操作するメソッドを書いてみようと挑戦。が、激しくエラー

 先生に聞いてみると・・ボロボロw

 所有権云々ってのが指摘されてたけど、Debugで表示してるだけなのに所有権移動するのか?と疑問に思って質問。あ、Claude先生の間違いだったか


 Plusメソッドの返り値の型が不要ということで質問、もしやと思ったけど破壊的変更だと不要なのか・・中途半端に関数型の書き方をしてしまった

 関数型っぽく新たな構造体を返すという方法も書いてくれるClaude先生、これが見たかった!なるほど・・最初にCloneで新たな構造体を作って結局スコープ内で破壊的変更するんかいって感じだけど。最後にMemory(new_vec)って返すトコロ、覚えておこう


 というわけで、ちゃんとした(?)バージョンはこう。*lastの参照外しは覚えておかないとな・・けど、ドキュメントで全然分からなかった参照外しがちょっと分かったわ。

 こちらMain部分。メソッドの書き方ってこうだったかw。なんだよ面白くなった来た!


2024/08/25 RustでBrain*uck、メモリ構造体

 昼、図書館で。夜、宿直Bの最中に・・と、Brain*uck用のMemory構造体をVecで作って、それを表示するというのを作り直す。なぜならRustPlaygroundはPaiza.ioみたいにはデータをクラウド上で共有できないから・・

 けどまあ、白紙テストみたいなもので何も見なくても書けるようになってるか?ってのを確かめる事になるので結果オーライ、書けるようになるまでは何度でも繰り返そう。

 昼間書いたばっかりなのに、夜書いてみようとすると全然書けないという状態で自分でも呆れるで・・

 メソッドを導入するためにMemory構造体内にはVec要素だけを入れるというつもりだったけど、Claude先生にBrain*uckのルールを確認したときにサービスで書いてくれたサンプルがちらっと目に入ってしまった。そこにあったMemory構造体内にVec型で出来たメモリ部分と、整数型で作るポインタ部分の2つの要素にするってのがあって、そりゃそうか!と。

 うーん、けどPythonでもVecの最後尾をカウンタに使ってたので、同じ形で作るか・・と考えてバイトが終わる


2024/08/24
 じゃあメソッドで操作可能なメモリー構造体を作るか?ってことで定義。普通に構造体を作るだけだと表示が出来なかったので、DebugをDeriveしてトレイトを導入する?ことで表示できるようにする・・と。

 メイン部分はこういう感じになるけど・・けどDebugを使うのもどうなんだろうな?と思いつつ実行。するとエラーが出る。おかしいところは無いと思うのだが・・

 出たのはエラーではなくて警告だった。インスタンスを作っておきながらどこからも参照されてないのでデッドコードだと判定されてるらしい。そんなことまで教えてくれるんかw

 ついでにFn main()の中に関数の定義とか出来るのかを聞いてみる(今まで中でやってるの見たことなかったので)。あ、やっぱり駄目なのか・・

 うーん、Displayトレイト?を使用したものに変更するか・・と思ってるところで甥っ子からラインで「マイクラやりたい」と呼び出されて今日は終了。次回はDisplayのパターンを書いて他のメソッドを追加していくか・・Foldで一気に処理できるような気がするが?


2024/08/22 Rust、入力部分
 Claude先生に聞いて標準入力のサンプルを貰ってMemory用に書いてみる・・が、エラー。i32の型がおかしいのだとか

 問題はココでusize型にしないと駄目なのだった。



どうもvec![0; num]で0で埋めたベクターを作るnum部分がusizeでないと駄目だからとか。なるほどね!

 オッケイ


 関数で済ませても良いけどどうせならメソッドを実装してみるか・・けどベクターにメソッドって無理だし?と思ったら、なるほど!ここで型の自作か

 ふーん、成る程。こういう感じで作っていけば良いのか・・ってことはBrain*uckってほぼメソッドで完結する感じかな?




2024/08/20 RustでBrain*uckに挑戦(やっとw)

 やっとこさRustの日本語ドキュメントに目を滑らし終わった!(読んだとは言えないな〜)

 というわけで、いよいよBrain*uckに挑戦しようと!うーん、誰もが「こいつ諦めたな」と思ってただろうな〜

 しかし言うまでもなく、もはや第一章なんか忘れてるのでRust by example(日本語版)を読み進めつつ、その都度「使えそう」って部分を参考にして実装していくというスタイルで復習を兼ねて作っていこうと!


 まずはメッセージを表示するところからやってくか・・今まではprintln!でやってたのでそれでも良いんだけど

 なんか例文で妙な書き方が出てたのでこれを使ってみるか・・と


 全く意味が分からなかったのでClaude先生にしつこく質問する。どうもこのDisplayトレイトに特有の書き方、お作法みたいなものらしいので丸呑みにするしかないな・・

 というわけでRustからダメ出しを10回くらいいただきながら書いたのがコレだ!
 fmtライブラリからDisplayトレイトを呼び出してderiveでラクして実装、(別にやらんでいいけど勉強のために)Messages構造体を作ってfmt::Formatterを利用する形式で無理やり活用してみる。
 最初ライフタイムをつけずにやって動かなかったのでエラーメッセージに従ってそのままつけて動くようになったけど理由がわからない

 例によってClaude先生に質問。あ、なんだ参照のときには絶対にライフタイムがいるんかい



 for Messagesにもライフタイムが必要な理由、なるほど納得!ドキュメント読んでても全然だったけど、自分で書こうと思ったら一発で分かったわ


 というわけでmain部分。出力成功!イメージ的にはfmt::Display(message)って感じで呼び出すのかと思ってのだけど、println!で変数を呼び出したら文字列が返ってくるって仕組みになってるのか・・ま、そういうもんだと丸呑みするしかないな。

 ってわけで、ようやくオモシロ部分に到達することが出来た〜 下積み(の下積み)長かったわ〜
 次回は多分標準入力とvec!を使ってメモリ部分を作っていくことになりそう


2024/08/06 Rust
 この章でここしばらくウロウロしてます!毎日マイクラを強制2時間プレイしないといけない、ドラマ「軍師連盟 司馬懿仲達」を見ないといけない、マンガも読んでる、宿直入りまくり・・ってのもあるんですが。やっぱり宿直Bの厨房仕事が入ったのがデカいなぁ・・


 関連関数に関してで特に思ったんですけど、結局名前問題解決のためなんですね~

 まあ、7回読み通し法のつもりで何度も読むか!(白紙テスト法はw?)

 あ、「Rustでつくる・・」は公式ドキュメント理解が前提って感じだからClaude先生にイチイチ聞きながらやってます。
 

2024/07/30「Rustでつくるプログラミング言語」を借りた
 ネットで読んだ記事に紹介されていたので地元の図書館でリクエスト。おお、また買ってくれてる。交野市やりますねぇ!
 (超)ある程度文法が分かってきたので、今なら書籍も役に立つのでは。とりあえずの目的だったBrain*uckをもっと本格的にやろうって話だから無駄にはなるまい!
 先週から漫画読みまくりなのもあって全然学習が進まないけど・・ま、人生100年時代って事でゆるりと行こう。響きは悪いけど結局全ては自己満ですしね・・・


2024/07/23 「脳に収まるコードの書き方」読了

 と言っても、知らない言語だし具体的なテクニックとかは置いといて気になったところを読んで調べるって感じですが。

・依存は7つまでにする(マジカルナンバー)・・関数内での使用ライブラリとか補助関数を脳に収まる数にする、と。まあ小分けにしろってのに具体的な数が示されてると良いかも
・同じ頻度で変更されるものは一緒にし、違う頻度のものは分ける
・カプセル化最大の要諦は「無効な状態にならないこと」である。想定してない返り値が無いようにするってことかな
・レッド・グリーン・リファクタリングを使う、まず失敗するテストを書く→全てのテストが成功する小さな変更を行う→リファクタリング・・を繰り返す。よくわからんが次になにか作った時には試してみよう。
・ドキュメントには判断の結果よりも「なぜそうしたか」という理由を書く。これは確かに。試しにKanta-Oのコードを久々に見たけど、さっぱり分からなかったw
・「関数型コア・命令形シェル」 を推奨。これは分からんのでClaude先生に聞く。関数型の逐次処理の方がオブジェクト指向のネスト構造よりも脳に収まりやすいとのこと、確かに

 以下、Claude先生に質問のコーナー
 なるほど・・OOPって構造体のそれぞれに機能をもたせてるような感じだからなぁ(トンチンカンな事を言ってるかも)。関数型言語(しかやってないが)は依存の広がりが追いやすいと

 まあよく分からんけど、想像するに1は確かに・・って気がする。

 やっぱりGUI関連での制御に有効っぽいと言うか、他にはゲームのオブジェクト制御くらいしか思いつかんかな。ちなみに、Claude先生は最後にこうやって質問を振ってくるパターンが多い

 ふんふん・・1と5が今後自分に関係ありそうかなぁ

 Racketでモンスターを自動生成して戦わせようとした時に失敗した理由がコレっぽいな。今から考えたら出来そうな気がするけど・・



 何となく分かるけど、これは一度動くものを作ってみないことには・・覚えておこう。

 この例だと全部関数型で良くない?とか思えてしまう


 試しにOOPを使った言語で作るとどうなんの?と聞いたが・・分からんw


 本で見た「デコレータ」ってのが分からないので質問。とりあえずSchemeでやってみてとお願い。パッと見た感じで関数の合成でインターフェイスを整えてるだけ?と思ったんだけど



 違うぞと


 うーん、挙動が分からん・・



 あ、そういうこと!逆だと思ってた。だって実際はUnreliable_functionを呼び出してるからこっちがメインなのかと誤解してたと。けど、仮引数はどうなってんだ!と

 そしたら*args **kwargsで可変長の引数が受け取れるんだ!と。なるほどねぇ・・いや、もう死ぬまで学習しても終わらないよ。

 Rustは並行処理の部分を読んでます。17章のOOPと18章のパターンマッチングまで読んだら、もう、いい加減で、Brain*uckに挑戦して、その後は、ゲームエンジンを適当に選んで、なんか、動くものを、作ろう!Rustにもゲームエンジンあるみたいだけど情報が少なすぎるのでやっぱりUnityとかかなぁ・・Godotが軽くて良さげなんだけど。

2024/07/18 Rust、クロージャ
 えっ!?
 これは・・クロージャで取り込む「環境」ってそういう意味だったのか!当然Lisp系でもそういう意味だよなぁ・・なんと、今回初めて知りました。クロージャと同じスコープ内の変数を利用できる・・だから「環境」を取り込むって言ってたのか!
 いや、Katan-Oとか書いてる時にクロージャ形式で書いてたけど不思議だったんだよなぁ~・・これ関数と一緒やん、と。変数に束縛して、それに引数を食わせって形だけのためにやってると思ってたから、クロージャの定義もわざわざ使う変数をあらかじめ想定して仮引数を用意して、その順番どおりに実引数を渡してましたわ。なるほど納得、同列スコープ内の変数を読み込み無しで自由に使えるってんなら、そりゃ便利に決まってるっつーの!


 なんかネットで見て良さげだったので(自分で買わずに)買ってもらいました、交野市に。いや~交野市素晴らしい!今までのパターンから「大阪府下の図書館に存在せず」「購入可能」で「為になりそう」な本であれば買ってくれる・・という事っぽい。こうなったらオライリーの新刊、出たら即座にリクエストするようにして、交野市をプログラミング技術書の要塞にするというのはどうだろう。ちょっと読んでますけど面白そう


2024/07/09 Rust、ライフタイムか~
 一通り読んだけど面倒なので、回避する方法がないのか聞いてみる


 なるほど・・数当てゲームの時には参照が単数だったから推論してもらえたのか。所有権の移動も分かりやすいかな



 ただ、このStaticライフタイムとは?



 構造体を使う場合、複数入力→より少ない出力の場合は必要と。しかしトレイト境界とか・・ドキュメントで読んだけど全然分かってない

 4の場合も複数入力やら構造体の場合と似たようなものっぽいか。クロージャはまだやってないのでとりあえず飛ばして・・

 Staticライフタイムって結局定数みたいなものなのか?と質問。まあ、変更も出来るけどプログラム全体で使うってことでOK




 あ、そうだグローバル変数って呼び方があったなw
 使いすぎるとプログラムが重たくなるという事か・・
 コンパイル時に評価される定数?それにそれぞれ書き方が違うのはなんでか?




 うーん・・定数として使うならConstで良いのかな。グローバル変数として使うならStatic mutかねぇ?
 型注釈が不要なのはLet &'staticだけっぽいので結局ライフタイムは使うことになりそうだなぁ

 明日以降は理解がペラペラのトレイト境界、ジェネリックコードについてClaudeに質問して・・そこそこ理解したら次に行こうか。とっとと12は飛ばして13の関数型言語の機能のところまでやって動くものを書こう!




2024/07/04 Rust、こっそり続けてます
 10-2、トレイト辺りまで来てます。今日でアマプラが終わったのでペースアップ出来るかと・・



 本筋とは違うんですけど、Println!に渡すトレイトの部分。このsummerize部分の定義が


 こういう感じになってるけど、どういう値が返ってOKなんだ?と気になって


 この挿入部分と同じ機能でFormat!で渡せるわけか・・



 Formatの:が余計だったけど、なるほど1つの文字列として渡せるわけか。覚えとこう、とか



 ここしばらく「トレイト」と「シグニチャ」の意味を確定させずに読んでて気分が悪くなってきてたのでClaude先生に確認。スッキリした!


 とりあえずとっとと13章の「関数型言語の機能」部分までやったら実際にBrainF☆ckとか動くものを作っていくとしよう

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

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

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