20250601 Imperative

今日ものんびり起きてDota2、コードリーディング、天気が回復したので布団カバーの洗濯などをしていた。論理午前中にジムで軽く有酸素し、また近所の新デパートに行ってみたが今日も激混みだったので食事は諦め、6月分の二郎枠を消費してきた。ミニ・ニンニク少なめ・アブラ少なめが丁度いい。

帰宅して、極上の昼寝。普段はロフトベッドで寝ているがたまには布団を床におろしてちゃぶ台にお茶を置いて1時間くらいゴロゴロしていた。これが贅沢というものだ。

今日もGeminiとプログラミングについて対話していた。ある処理のあとに別の処理を行うという命令を、JavaScriptでは

f1();
f2();

と書けるが、これ全然自明じゃないよね、みたいな話をしていた。SQLとか、Haskellの遅延評価とかね。JavaScriptの言語仕様の範囲内でもこれの次にこれを行えという指示は上記以外に

f2(f1());

とか

f1().f2();

とか書き方がある。これがf1, f2が非同期処理になったり失敗しうるようになったりするとそれぞれ進化していくが、やはり基本は一番上の命令形になるだろう。

ところでGeminiとずっと話していると思うのは、会話が単線的なのはポテンシャルを浪費しているのではないかということだ。一般的なAIチャットのUIは人間同士で会話するLINEのように自分の発言と相手の発言が交互に時系列的に並ぶだけのシンプルなものだ。しかし、特にAIが得意とする論理的に込み入った会話では、論点Aから生じた論点B、論点Cに対してそれぞれ別々の会話ブランチを伸ばしていきたいことがある。もちろん私は同時に1つの文章しか入力できないから並列性を上げられるわけではないが、あとから見直して話の筋がわかりやすくなる。コンピュータ上で行う会話なら、そのように進化しても良いはずだ。

冷静にこれSlackのスレッドじゃん。

JavaScriptのyield*は移譲先ジェネレーターがreturnした値はyieldしない

本記事は https://developer.mozilla.org/ja/docs/Web/JavaScript/Reference/Operators/yield*#%E4%BE%8Byield* 式自体の値 に例示されているものを改めて考えつつ説明したものです。

https://github.com/susisu/tskaigi2025 のコードリーディングをしていて、ここがわからなくてしばらく詰まっていた。

it("ジェネレータから yield された Promise が fulfill されたらその位置から再開する", async () => {
  function* myFunc(): Comp<number> {
    const a = yield* waitFor(Promise.resolve(1));
    const b = yield* waitFor(Promise.resolve(2));
    return a + b;
  }
  const promise = run(myFunc());
  await expect(promise).resolves.toEqual(3);
});

JavaScriptには yield* という構文がある。

https://developer.mozilla.org/ja/docs/Web/JavaScript/Reference/Operators/yield*

これはジェネレーターの中で使い、別のiterableに制御を移譲するために使う。とてもわかりやすい例があったので引用させてもらう。
https://stackoverflow.com/questions/17491779/delegated-yield-yield-star-yield-in-generator-functions

function* someGenerator() {
    yield 0;
    yield [1, 2, 3];
    yield* [4, 5, 6];
}

for (v of someGenerator()) {
    console.log(v);
}
// 0, [1, 2, 3], 4, 5, 6

yield [1, 2, 3];[1, 2, 3] をそのままyieldする。一方で yield* [4, 5, 6];[4, 5, 6] がiterableなオブジェクトならば、その生成値を1つずつyieldする。移譲すると書いたが、someGeneratorの呼び出し側から見ると、内側の内側にあるiterable([4, 5, 6] のこと)を透過的に扱えるとも言えそうだ。

ところでジェネレーターの中ではyieldの他にreturnも使える。returnに到達すると値を返しつつジェネレーターは終了する。

const gen = function* () {
  yield 1;
  return 2;
}()

console.log(gen.next()); // { done: false, value: 1 }
console.log(gen.next()); // { done: true, value: 2 }
console.log(gen.next()); // { done: true, value: undefined }

では yield* で移譲されたジェネレーターがreturnしたとき何が起きるのか。僕はなんとなくreturnされた値も透過的に外側から触れると思っていたが、触れない。

const g_inner = function* () {
    yield 1;
    return 2;
}();

const g_outer = function* () {
    const a = yield* g_inner;
    yield 3;
    return 4;
}()

console.log(g_outer.next()); // { done: false, value: 1 }
console.log(g_outer.next()); // { done: false, value: 3 }
console.log(g_outer.next()); // { done: true, value: 4 }

なんとなく出てくる値は 1, 2, 3, 4 になりそうな気がしたが(俺だけか?)、正解は1, 3, 4だ。MDNに

yield* は式であり、文ではありません。そのため、値に評価されます。

とサラリと書かれている通り、g_innerのreturnで返される値はg_outerのaに束縛される。それだけで、g_outerの呼び出し側には返されない。

ここで逆に考えてみる。移譲先のreturnで停止すると仮定すると、どのような問題が起きるだろうか?

まず、yieldの機能として、呼び出し側からnextに引数を与えることで、値を受け渡すことができる。

const gen = (function* () {
  const a = yield 1;
  const b = yield 2;
  return a + b;
})();

console.log(gen.next());     // { value: 1, done: false }
console.log(gen.next(10)); // { value: 2, done: false }
console.log(gen.next(20)); // { value, 30, done: true}

初回呼び出し後にyield 1;で停止しているジェネレーターに対して10を与えて再開させ、次にyield 2;で停止しているジェネレーターに20を与えて再開させている。3回目のnext呼び出しの後はreturn a+bに到達して30を返して終了する。

これは yield* で移譲された内側のジェネレーターにも機能するのだが、returnで停止すると仮定してシミュレーションしてみる。

const g_inner = function* () {
    const a = yield 1; // aに10が入る
    return 2; // ここで停止すると仮定
}();

const g_outer = function* () {
    const x = yield* g_inner;
    yield 3;
    return 4;
}()

console.log(g_outer.next());     // { done: false, value: 1 }
console.log(g_outer.next(10)); // { done: false, value: 2 } が返ると仮定する
console.log(g_outer.next(20)); // { done: false, value: 3 } このnextに渡した20はどこへ…?
console.log(g_outer.next());     // { done: true, value: 4 }

return 2で停止すると仮定すると、そのときnextに渡された値はどこに行くのだろう?xにはg_innerから返された値が入ることになっているので行き場がない。捨てるしかない。そうなると、g_outerを利用する側は中でg_innerに処理を移譲しているなんて本来知る必要がないのに、それを知らないと何回目かのnextに渡した値が勝手に捨てられてしまうことになる。インターフェースとしての安定性が失われている。

そういう意味で、returnでは停止しないのは筋が通っている。割と非直感的だと思ったんだけど、MDNだとサラッと1行説明されて例が1つあるだけで終わるので難しかった。普段からジェネレーターを使ってる人(いますか?)には自明な動作なのかもしれない。

一般のジェネレーターにおいてreturnは停止して値を返すという点でyieldと同じように見えるが、その見方は間違っているのだろう。yieldが明確に停止を意図した機能である一方で、returnは終了だから結果的に停止に見えてしまっているだけで、その本質はただ値とともに処理を返すことだけだ。yield* のようにその後も外側のジェネレーターに制御を戻して続行できるのであれば停止しないように見えるのは必然なのだろう。

20250530 褒められ欲

項目 内容 得点 換算点
睡眠時間 6時間26分 77 10.0/13.0
起床 7:19 100 8.0/8.0
散歩 実施・ゴミ拾いなし 100 5.0/5.0
朝食の栄養カバレッジ 3色カバー 100 5.0/5.0
体操 ノー 0 0.0/5.0
労働 passion: 80点, discipline: 75点 78 18.7/24.0
ジム 休養日 100 12.0/12.0
勉強会 参加 100 12.0/12.0
個人開発 実施 100 7.0/7.0
あすけん - 60 5.4/9.0
総合 1日の総合評価 - 83

今週はTSKaigiのモチベバフと睡眠好調が相まってかなりモーレツ気味(当社比)で働いていたけど、金曜日はさすがに疲労を感じる。意外と体は習慣通りに動きそうなんだけど、精神力が上がりきらない。

https://github.com/susisu/tskaigi2025

これがめっちゃ難しくてClaudeに解説させながら読んでる。AI教師、対応範囲が(人間よりは)広いし能力は間違いないし時間も場所も感情も気にする必要ないし優しいのでかなりすごい。AIに褒められて褒められ欲(結構ある)の充足を感じるけどこれでいいのかなあと疑問。でも確実に僕の役に立っているしなんなら僕を賢くしている。

明日は久々の完全オフ。ジム以外特にすることなさそうなのでのんびり布団でも干すかな。うまいものも食いたい。食いに行きたい。休養だけでなくリフレッシュの気持ちになっているのもモーレツの反動かもしれない。

20250529 『モナ王』/sort-package-json3.2.0でソートアルゴリズムが変わったっぽい

項目 内容 得点 換算点
睡眠時間 7時間19分 100 13.0/13.0
起床 8:08 93 7.4/8.0
散歩 実施・ゴミ拾いあり 100 5.0/5.0
朝食の栄養カバレッジ 3色カバー 100 5.0/5.0
体操 実施 100 5.0/5.0
労働 passion: 85点, discipline: 75点 80 19.2/24.0
ジム 有酸素 100 12.0/12.0
勉強会 参加 100 12.0/12.0
個人開発 実施 100 7.0/7.0
あすけん - 80 7.2/9.0
総合 1日の総合評価 - 93

今日の仕事は並列度が高くてあまり集中できなかったな。

『モナ王』

『モナ王』を食べた。『チョコモナカジャンボ』の隣に並んでいたらまず選ばない商品だが、だからこそ食べておくかということで食べた。結論から言うと特に選ぶ理由はない。チョコの風味が要らない、パリパリが要らない、そんなムーディーな気分の日ならいいかもしれない。

sort-package-json3.2.0でソートアルゴリズムが変わったっぽい

sort-package-jsonというライブラリがある。その名の通りpackage.jsonをソートすることで秩序をもたらすツールである。最近npmのソートアルゴリズムに合わせるということで変更が入ったのだが

https://github.com/keithamus/sort-package-json/pull/358

これがyarnのソートアルゴリズムとは違っており、しかも間の悪いことにyarnは yarn install を実行するたびにpackage.jsonをソートし直すので、sort-package-jsonとの共存が実質的に不可能である(開発中に yarn install をするたびに意味のない差分が発生し、commitするときにlint-stagedで消える)。じゃあsort-package-jsonの代わりに yarn install を使えばいいのでは?とも思うが、コマンドの意味・副作用からしてかなり正しくない度が高い解決だ。苦しい。

https://github.com/keithamus/sort-package-json/issues/363

ソートアルゴリズムの違いというのはどうやらこういう違いのようだ。

https://github.com/keithamus/sort-package-json/issues/355#issuecomment-2848325132

// yarn
> ["a", "b", "A", "B"].sort()
[ 'A', 'B', 'a', 'b' ]
// npm, sort-package-json
> ["a", "b", "A", "B"].sort((a,b) => a.localeCompare(b, "en"))
[ 'a', 'A', 'b', 'B' ]

実はnpmではパッケージ名に大文字を使ってはいけない。昔は使えたのかも知れないが、今は大文字名でinstallしようとすると404で弾かれる。だからこの問題は内製パッケージを使っていたりエイリアスを付けていたりしないと表面化しにくい(一応 -_ とかでも差が出てしまうらしい?)。

まあそこまで重大な違いではないように思えるが、sort-package-jsonは結構な人気があるパッケージなので、そこそこ困っている人がいるかもしれない。

20250528 一生は長いが一日は短い

項目 内容 得点 換算点
睡眠時間 6時間53分 95 12.3/13.0
起床 7:37 100 8.0/8.0
散歩 実施・ゴミ拾いなし 100 5.0/5.0
朝食の栄養カバレッジ 3色カバー 100 5.0/5.0
体操 実施 100 5.0/5.0
労働 passion: 90点, discipline: 85点 88 21.1/24.0
ジム 有酸素+筋トレ 100 12.0/12.0
勉強会 参加 100 12.0/12.0
個人開発 実施 100 7.0/7.0
あすけん - 65 5.8/9.0
総合 1日の総合評価 - 93

今日もかなり良い。やはり睡眠が基本だ。朝は散歩しながらプログラミングのフローについて考えていた。TypeScriptを第一言語とする僕にとっては、関数の連続は

const a = f1();
const b = f2(a);
const c = f3(b);

のように書かれた方がわかりやすい。

const c = f3(f2(f1()));

は厳しい。上から下に流れること、得た値を束縛すること。この2点がだいぶ馴染みがある感に寄与している。手続き的と宣言的と言ってもいいのかもしれない。あるいはメソッドを生やしてやって

const c = f1().then(f2).then(f3);

という考え方もあるかもしれない。同じプログラムの流れであっても、それがどこに表現あるいは隠蔽されているのかというのがいろいろ違うよねという話。そして流れの理解が重要なプログラムを書くときに、流れを隠蔽するような記法を使って良いのか?

これがまあ f3(a, b) になったりPromiseになったりResultになったりするとどんどんゴチャってきて、その場合どれがベストなのか…!という話になる。言語がデザインする書き方もあるし、個人・チームの慣れ・志向もある。

人生が長いか短いかはまだわからない(どちらかと言えば長い寄りの感覚でいる)が、一日は間違いなく短いということを最近感じる。ちゃんと寝て、起きて働いてやるべきことやって、その上で遊びの時間も取るというのは、かなりのテクと意思が必要だ。31歳なのでね。幸いやりたいことが減ってくれて、集中できる。

20250524 TSKaigi 2025 Day 2

TypeScriptネイティブ移植観察レポート TSKaigi 2025

https://2025.tskaigi.org/talks/berlysia

https://speakerdeck.com/berlysia/typescript-native-porting-observation-tskaigi-2025

tsgoの歩みについてのレポート。コンテキストから細部までよくわかる話だった。Compiler APIどうなっちゃうんだろうなあ。

フロントエンドがTypeScriptなら、バックエンドはPHPでもいいじゃない

https://2025.tskaigi.org/talks/hanhan1978

https://speakerdeck.com/hanhan1978/php-is-not-bad

TSKaigiとしては異色の発表。ベテランバックエンドエンジニアの視点から、バックエンド/フロントエンドの歴史について振り返る。後半はPHPの圧倒的なシェアの高さを見せた上でのPHPはいいぞという話。トーク力が素晴らしく、楽しみながら頭に入ってくる発表だった。

Pragmatic Functional Programming in TypeScript

https://2025.tskaigi.org/talks/_yasaichi

TSのプロジェクトにFPを導入したいということはよくあるが、チームとしてそれを採用する判断ができるかは難しい。まず単純化した5つの原則とその嬉しさを把握し、実利ベースで導入を進めていこうというのがPragmaticということ。

君だけのオリジナル async / await を作ろう

https://2025.tskaigi.org/talks/susisu2413

https://speakerdeck.com/susisu/tskaigi-2025

ジェネレータにおけるyieldを文脈から値を取り出す処理?と捉えて、async/awaitのみならずResult、エフェクトシステムまで実装してしまう話。とても難しいが興味のある分野なのでよく読み直したい。プログラミング理解の足腰が強い人は「結局こういうことなんだよね」と抽象化して裏返して思いもよらない使い方を編み出したり、足りない場所に気づいて埋めに行ったりする。基礎力だなあ。

TS特化Clineプログラミング

https://2025.tskaigi.org/talks/mizchi

https://tskaigi.mizchi.workers.dev

効くプロンプトとうまくいかないプロンプトの事例集。AIエージェントを使い倒してる発表者ならではの、AIとはどのような学習の結果何ができて何ができないのか考察が深い。

OST (Open Space Technology)

参加者がテーマごとの10のグループに別れて自由にディスカッションする企画。僕はフロントエンドのディレクトリ構造のグループに参加した。自分たちのチームが採用している構造についてあまりうまく話せなかったのは後悔が残るところだが、いろいろな人の重視するポイントが聞けて面白かった。

総括

TypeScriptの領域は広く深く、仕事でwebアプリケーションを開発してるだけでは浅瀬もいいところなんだなと感じた。いろいろな分野で非常に深く研究している人がいてかっこいいなあ。久しく忘れていたすごいエンジニアはカッコいいという感情を思い出した。そう思うと同時に、いくらやっていきを得ても全部ガチるのは無理なので、どこに軸足を置いてやっていくかを冷静に見極める必要がある。現状のプログラミングに満足しちゃいけないな。もっと楽にできる、もっと安全にできるという強い気持ちを持つべきだ。

2日間ガッツリ参加して学ぶというのはそこそこ大変。移動も大変。弁当は美味しかった。いろいろな縁がある人に会えたり新たに縁が生まれたりというのは物理会場ならではの良さだったな。

20250523 TSKaigi 2025 Day 1

n円払って有給取って行ってきました。

SignalとObservable―新たなデータモデルを解きほぐす

https://x.com/laco2net

https://docs.google.com/presentation/d/1c7fYqn7-v3hnbKtmwXHbvwuCs6cNq_ThLKVDZ7rvbA0/preview?slide=id.g260298bad6d_0_77

UI開発における状態管理の話に始まり、歴代の状態管理ライブラリを概観しつつ「結局やりたいのって状態+派生状態+イベントドリブンな副作用なんだよね」と整理する(mobxが言及されて嬉しい)。さらにそれを「値の生産」というレベルにまで抽象化し、見慣れた同期/非同期・単一/複数という軸に新たにpull/pushという軸を加えることで、Signalの話とObservableの話はFunctionやIterator、Promiseから全部つながっていたんだと最後に納得させられる大回転。

すごいことをすごいスピードで流し込まれたのでわかったようなつもりで大してわかってないんだけど、すごいので忘れない。きっと必要なときに思い出せると思う。すごすぎてこんな顔になった。

Language Serverと喋ろう

https://x.com/pizzacat83b

https://speakerdeck.com/pizzacat83/language-server-todie-rou-tskaigi-2025

Language Serverとは何か、意義、使い方、応用、AIなど幅広く理解できた。なぜLanguage Serverを使うのかという点も発表者のバックグラウンドから納得のいく説明がなされて、TSだけ書いていてはわかりにくい一段階高い視点が得られて有意義だった。

AI Coding Agent Enablement in TypeScript

https://x.com/yukukotani

https://speakerdeck.com/yukukotani/ai-coding-agents-enablement-in-typescript

AIコーディングエージェントを速く正確に動かすため、我々は何をすればよいのか。意味があることとないことが最新の研究成果の引用とともに紹介され、基本的な結論はそりゃそうだよねという感じでありつつも、そこに至る筋道が明確で非常に参考になった。「入力方法はどうでもいい(中略)大事なのは入力に値する情報の整備」は名言。開発を効率化するという包括的な視点の中でツールチェインに対しても考察されており良い。

fast-checkとneverthrowのPBT+Result型で堅牢なビジネスロジックを実現する

https://2025.tskaigi.org/talks/kueda

TSにはthrow型が無いのが辛い、という積年の問題について、現状を分析した上でneverthrowのようなライブラリをどのような形で、どこになら導入できるのかというのが経験に基づいて丁寧に考察されており、同じ問題に苦労している人間として地に足がついた報告が参考になった。さらにPBTという独特な手法についても知ることができた。

Rust製JavaScript/TypeScript Linterにおけるプラグイン実装の裏側

https://x.com/unvalley_

https://speakerdeck.com/unvalley/typescript-linters

Rust製LinterはESLintをパフォーマンスで上回るものの、ESLintが支持される理由であるプラグインシステムの再現にはRustがRustであるがゆえの困難がある。針の穴を通すような技術的な挑戦が僕らが日常的に使うツールチェーンを支えていることが実感される感動的な発表だった。yukukotani氏の発表でLinterの速度の重要性を再認識したところでこの発表が出るというのもアツかった。

その他

そこそこ知り合いがいたのと、スポンサーブースが普通に盛り上がっていて楽しい。エンジニアは問題を解きたがりなのでわかるかな?的な挑戦問題の掲示が多かった。お弁当おいしい。30分単位の発表は長くはないけど連打されるとそこそこ疲れる。集中してるし。自分的安牌みたいな発表を聞きがちだけど裏でトンデモアイデアみたいな発表もあったりして分身したい。数年前なら全然わかんねえよって話題ばっかりだったと思うけど、今はどの話題もそこそこ意義やポイントが理解できるので成長したなという実感がある。楽しいね。

20250516 髪map

歯科定期検診→上中里でちょっと用事して昼食。また帰ってきて散髪。

上中里、めっちゃ電波悪い。

用事をまとめて3つ片付けていい休暇だったような気がしないでもないが、夜はもう暇でしょうがなかった。何をしても楽しくないし、そういうときに何かをしようと思うとカスみたいなニュースを見てしまって一層嫌な気持ちになるんだよな。自由な時間というのは本当にろくなもんじゃない。かと言って寝たいとも思わない(早く寝ることによって明日の時間を増やそうとも思わない)。

散髪ってmapかなって考えてた。僕はいつも3cm短くしてと言うので

hairs.map(hair => ({ ...hair, len: hair.len - 30 }))

なんですよ。ただ、JavaScriptで考えるとmapは新しい配列を再生成するのだが、髪はinplaceで変更する。なので

hairs.forEach(hair => hair.cut(30))

の方が良さそう?でも実際は散髪ってmapじゃないんですよ。全部の要素に同じ処理は行えない。毛根が頭皮座標系において2次元的に、空間座標系においては3次元的に分布している一方でハサミの切断部分は線分として存在しており、ハサミを使って複数の毛髪に同じ切断操作を行うことはできないし、そもそも髪にできる操作って「ncm切る」ではなく「切った後の長さがこのくらいになる」なんですよね。

毛根が切断線分を軸とする円筒面上に分布すれば一発で同じ長さに揃えることはできるだろう

hairs.forEach(hair => hair.setLength(40))

しかし頭部は基本的に凸構造だ。凹構造の人体と言えば…そう、消化管!

オチはない。

20250430 @ピザ/Effect

項目 内容 得点 換算点
睡眠時間 6時間11分 67 8.7/13.0
起床 8:38 68 5.4/8.0
散歩 ノー 0 0.0/5.0
朝食の栄養カバレッジ 3色カバー 100 5.0/5.0
体操 ノー 0 0.0/5.0
労働 passion: 75点, discipline: 65点 70 16.8/24.0
ジム 有酸素 100 12.0/12.0
勉強会 参加 100 12.0/12.0
個人開発 ノー 0 0.0/7.0
あすけん - 80 7.2/9.0
総合 1日の総合評価 - 67

近所のスーパーは頻繁に冷凍食品3品買うと5%引きセールをやる。あすけんのポイント調整のために食事にちょい足しするための冷凍食品として今川焼・肉まんを常備しているが、これらには脂質が不足しがちという弱点がある。なのでこの前のセールで小型ピザを買ってみた。これがなかなか良かったので報告する。

調理の手間はイマイチ(冷凍食品の調理の手間をレビューするな)。1枚加熱するのは多すぎるので1/4枚単位で量を調節することになるが、凍った状態で切るのに包丁が必要だ。レンジ加熱時も皿を使わないと溶けたチーズが庫内に付着するという点で肉まんにやや劣る。ただし加熱時間は肉まん1分に対して45秒ほどで短くて済む。栄養としてまあまあの脂質と豊富なカルシウムを持つ。チーズのおかげだ。僕は牛乳が嫌いなのでこれは助かる。

なんとなくTechnology Radarを見ていたらEffectが載っていて驚いた。fp-tsの開発が緩やかに停止した一方で後継?ライブラリとして存在を認知していたがだいぶ存在感を増しているようだ。一見した印象だとTypeScriptの知識と一般的な関数型プログラミングの知識があれば太刀打ちできたfp-tsに比べて、更にインターフェースの独自性が強まっており、Effectの使い方をかなり勉強しなければならなそうだったのだが、いよいよ自分で手を動かしてリサーチしてみる必要がありそうだ。

20250422 フロントエンドDDDの記事を読んで思うこと

項目 内容 得点
睡眠時間 6時間39分 86
起床 7:47 100
散歩 実施・ゴミ拾いなし・犬遭遇3匹(プープーパピ?) 130
朝食の栄養カバレッジ 3色カバー 100
体操 実施 100
労働 した・passion: 75点, discipline: 85点 80
ジム 休養日 100
勉強会 参加 100
個人開発 実施 100
あすけん - 22
総合 1日の総合評価 88

今日はよく眠れた。そのせいか労働は特に気合が入っていたというわけでもないが自然体でスムーズによく進んだ。そうそう、これが僕の本当の能力よ。

いい気分になったのでお菓子を大量に食べてしまった。すまん、あすけん女。

イーサネットフレーム

個人開発ではパケットキャプチャを進めた。久々にRustのBoxやdynのことを思い出していた。Rustはコンパイル時にあらゆるデータのサイズが決まらなくてはいけないので、関数の返り値としてトレイトを返すことは原則できない。なぜならトレイトはその実装ごとに型とサイズが違うからだ。しかしその返り値への参照を返すという作りにすれば参照のサイズは固定だから問題なく、その方法を使ってトレイトを返り値にするときに dyn traitname と書くのだ。

まあなんか書くときの感覚よりもメモリ管理のルールが優先されるのはいかにもRustだよね。

今日は生のイーサネットフレームを得るところまで成功した。 u8[] で得られたのでそのままGeminiに放り込んでみたら普通にパースできてすごい。

フロントエンドDDDの記事を読んで思うこと

そう言えば今日は フロントエンドDDD という記事を読んだ。クラスなりなんなりで豊かなデータ構造を作ってそこにドメインロジックを集約するという考え方はとても良く、業界でも重厚なフロント作っている方だと自認している私としてもぜひ見習いたい考え方だと思った。

一方でこの記事が改めて注目を集めるほどに珍しいのは、フロントエンドの世界はどうしてもバックエンドからの通信でシリアライズされてメソッドが消えたり、Reactベースの世界観になるとクラスの差分検出がめんどいというところもあったりする。『コア価値であるロジックがフロントエンドの技術変遷の影響を受けすぎない』で述べられていることを裏返せば、通信やフレームワークの事情先行で作っていくとプリミティブ中心に薄く薄く…ということになりがち。そういうところを上手く分離して丁寧に構築する作り方をしてもなおメリットが上回るような重いものを作っていて、難なくそれを扱えるチームの熟練度があってこそかなあと思う。

関連記事: https://panda-program.com/posts/clean-architecture-and-frontend

『生成AIの作業領域との分離』という切り口は考えたことがなかったが確かにその通りだ。賢い。