カテゴリー: Uncategorized

ゼルダの伝説ティアーズ・オブ・ザ・キングダム

クリアしました。プレイ時間70時間ぐらい。

なんというか、たいへんにすごくて、あまり類のないタイプのゲームであり、いやまあすごかったなと思った。がなんというか、ゲームの要素がどれもこれも自分にはいまひとつフィットしなくて、うーんこれは自分向きではないな……という違和感というかなんというか、そういうものをずっと思ってたゲームでもあった。そういう気持ちはエンディングまで解消されなかったかな。

たとえばなんだけど、ウルトラハンドによっていろんなものを構築できる能力。ネットのいろんな記事なりなんなりを眺めていると、とにかくみんなこの能力をつかっていろんなものを作って楽しんでいるようだ。が、自分はいっさいそういうことをする気になれなかった。ゲーム内の障害を解決するために、パズルを解くためにいろいろ考えるのは好きだしやるけど、そうでもないところで何かをやってみようという気持ちがいっさい湧かない。馬車的なものも(大妖精クエスト以外では)一度もつくらなかったし、ほとんどの移動は徒歩とワープだけでこなした。そういうものに興味が出てこないんだよね。マインクラフトに興味がわかないのと同じだな。

スクラビルドも同様で、ああこれは無限に強化アイテムが湧いてくるから適当な武器を強化して消費していくゲームなんだな、ということはまあわかる。わかるんだけど、はっきりいってめんどくさいなと思う。ここに面白さを感じることはついぞなかった。あとどうでもいい話なんだけど、主人公は特殊能力で武器にいろいろくっつけられるという設定なのに、そのへんの雑魚的もいろいろも武器にくっつけられるのはどうなってるんだ。

戦闘のアクション。今回はいつものゼルダよりも前作ブレス・オブ・ザ・ワイルドよりもだいぶ戦闘のアクション要素が高まっているように感じた。作ってるほうとしては折角いろんな戦闘用の動作や要素を盛り込んだのにそんなに活用されないのはもったいないといった面があるのかもしれないけど、正直こういうのあんまり得意じゃないというのもあるし、かったるいし、たいへん。とくに終盤の展開というかラストバトル周辺はほんとうにうんざりした。そして自分はゼルダにそういうことを求めていないという気持ちが高まった。

メインクエストや祠などのパズルっぽいタスクは楽しめるし、ウオトリー村の復興タスクとかはけっこう楽しい(海賊退治はめんどくさくてイヤイヤこなした)。メインクエストのボス戦もしんどい奴はいるけどそんなに嫌いじゃない。つまり自分はパズル的な要素とかギミックとかをゼルダに求めているのだな、という気がする。本作は、全体的にパズルっぽさはずいぶん抑えられていたように思う。それよりは戦闘と、工作による創意工夫が強調されていたかんじ。そのへんがnot for meなかんじだったな。あと前作もそうだったけど祠をさがすのがかったるすぎる。コログの運搬もすぐ飽きてスルーしてた。全般的にやりこみ要素に興味がないのだよね。でもBotW以降のゼルダというのはやりこみ要素だけで構成されてるようなゲームなんだよな。

ストーリー。まぁゼルダというのはストーリーはあってなきがごとしというか、メインのゲーム要素に対する刺身のツマ的な意味しかないと思うけど、でもなんかいまいちだなーと思った。全般的なバックストーリーがそのまんま天孫降臨でキーアイテムが勾玉のかたちなのも、わざとな含意じゃないだろうけどちょっとたじろいてしまったし、賢者の能力がクライマックスの展開にいまいち絡んでこないのも今ひとつ白ける。賢者として覚醒したから魔王を倒せた、みたいなストーリーになっていない気がする。サブクエストのストーリーもそこまで興味がわかないし、サブクエストの報酬が全体的にしょっぱくてやるモチベーションが薄かった。すごいアイテムをもらってもすぐ壊れるか消費しちゃうかだし、経験値とか成長要素は基本的にはないし……。

まぁいろいろ書いたわりには70時間以上プレイしているわけだし、全体的には面白いゲームなんですよ。でもやはり、not for meなところが強かったですね、という気持ち。今後のゼルダは基本的にこういう構成になるみたいだし、もう続編やりたくないかもなあとすら思ったかな。

浮動小数点数の加算の順序にハマった話

fediverseにちょっと書いたけど、仕事でちょっとハマって数時間悩んだ話。

とあるコードを書いていて、どうもテストが安定しなくてflakyになる。つまり、通るときは通るがたまに失敗する。が、理由がよくわからない。

こういうとき、Goでよくあるのはmapのイテレーションの順序が意図的にランダム化されているというパターンだ。mapは(内部的にはハッシュテーブルが使われているので)イテレーションの順序は不定であるし、不定であるべきなので順序に依存するコードを書くべきではない。現実的にはたいていの言語ではこのへんは「実装依存である」ということになっていて、うっかりすると言語のランタイムバージョンが上がったり、キーが一個増えたり減ったりするだけで順序が狂い、突然テストが死ぬみたいな現象によくみまわれる。Goでは意図的にこの問題に対処するために、言語のバージョンが変わらなくても毎回イテレーションの順番かわることになっている。実際、同じバイナリで同じmapをfor-loopで巡回するだけでも、毎回結果は異なったりする。たとえば次みたいに。

https://go.dev/play/p/fm_oDaAeXpI

ただ自分はそのことはよく知っているし、ここでいじってるコードのイテレーションの順番はわりと大事なのできちんと順序を保っているつもりでいた。それか、イテレーションの順番に影響なさそうな単純な集計だ。なのに微妙に結果がかわることがある。わけがわからない。困ったな……と思っていた。

そこでいろんなところにhackyな変更を入れたりしてデバッグしていたのだけど、しばらくしてひらめいて正しい修正ができたのだった。

実際にはコードのなかでは「単純な集計」をしている箇所があって、そのなかの集計のひとつはmapのなかの浮動小数点数を合計するというものだった。単純化するとこんな感じ。

func getTotal(m map[string]float64) float64 {
  var total float64
  for _, v := range m {
    total += v
  }
  return total
}

これは一見問題ないように見える。単純に合計しているだけだし。でもこういう計算が実はflakinessの原因になっていた。

浮動小数点数では大きな数と小さな数のあいだの演算をすると小さな数の下位ビットの情報が抜けおちるように計算される。そのため、上のコードのmのなかに大きな数値と小さな数値が混在していると、イテレーションの順番によって結果が微妙に異なってしまうというケースがありうる。これまた単純化された事例だけど、mapのsliceがあって、そのなかをスキャンして最大値をとるもののインデックスを知りたい、みたいなことがあったとしても、次のようにまったく同じmapなのにインデックスが変わってしまう、みたいなことがありうる。今回遭遇したのもだいぶ単純化されてるけどこういうパターン。

https://go.dev/play/p/HKyvY6BFOnm

ようするに浮動小数点数の加算順序は大事なのを見落していたということだ。たいていの場合、この順番のちがいの結果はほんとうに微差なので、微差を無視するような比較を実装するというのも手だし、getTotalするときの順番はどんなものでもいいがとにかく固定する(たとえばキーをソートしてその順番をつかう)という手もある。今回やったのはfloat64の値をもってきてその値でソートして小さい順に加算していくというもの。下位ビットの欠落が問題であるはずなので、これがまぁたぶんいちばん正しいだろうと思う、が、実際のところはほとんどどうでも良いということになるだろうと思う。

https://go.dev/play/p/HKyvY6BFOnm

というわけで、浮動小数点数の加算による情報の欠落も、mapの順序が不定になることも知ってはいたけれども実際に遭遇するとなかなか見つけづらいバグでした、という話でした。いやぁ浮動小数点数はむずかしいですね。あとあれだな、テストケースにそういうのが見つかるようなケースがあってよかったですね。

猫がキーボードを踏む問題

ブログで書いたことがあるかどうか覚えてないけど、知人友人には周知のようにかれこれ7年くらい猫を飼っている。そして2020年から例にもれず在宅勤務をはじめている。最初はその必要があってのことだが、そのうちにフルリモートの会社に転職してしまったので、ずーっと在宅勤務している。

猫はジャレたくなると仕事中の机によく来る。とりわけうちの猫は好奇心が強く、ミーティング(ビデオ会議)をしていたり話していたりすると机のところによく来る。同僚は「こいつ、いっつも猫を抱えながら仕事してるなー」と思ってることでしょうが、違うんですほんとミーティングのときだけで大部分の時間はうちの適当なところで寝てるんですよ。

まあそれはいい。そんな言いわけもほんとは別にしなくてもいい。いっつも猫をなでながらミーティングしてるのは間違いないし。

ところで、先日猫を飼っている友人から「こないだのポッドキャスト、猫の声が入ってましたね」と言われて、ああそうだね、遠くでニャーと鳴くこともあるよね……という話をしていてどうも話が噛み合わないと思ったら、このノイズみたいな音は猫がゴロゴロ鳴く音だ!と気づいたという非常に猫上級者の発言であった。でもポッドキャストで話しているときもミーティングと同じで席の前にやってきてジャマをするので、そのときの鳴き声だと思う。閑話休題。

それで在宅勤務も3年たったわけなんで慣れたものなんだけど、なぜかどうも最近になって猫が頻繁にキーボードを踏むようになってきた。

仕事にはノートPCを使っている(会社支給のものがそれなので)。でもまぁ実際には外部モニタ、外部キーボード、外部マウスをつかってもっぱらそちらで操作している。ノートPCはそれでも開いて机の片隅に置いてあり、たまに何かのウィンドウを置いたり、ミーティング時のカメラとして利用している。うちは夫婦で共働きなので机を横に並べて配置していて、ちょうど机のあいだの側にノートPCがある、という配置。

この配置はかなり以前からそのままなのだが、最近になって猫がノートPCの内部キーボードを踏むようになった。猫がふたつの机のあいだを行き来することがよくあり、その通りみちとして踏んでいく。ふつうに作業していたりミーティングをしていたりすると、とんでもないキーを押したりしないか不安があるし、話していたら猫をしかるのもむずかしい。

どうして最近になって発生した事象なのかはよくわからない。これまでもこういう配置だったし、そこまで微妙な位置のちがいが原因という気もしないのだけど。ともあれ、さすがにミーティングに支障をきたすようになってきたので、対策を考えることにした。

自明な対策としては机の反対側の隅に動かすということが考えられる。でもケーブルのポートの位置(とくにHDMIポートの位置)の関係でやりづらいのでこれは却下。

次に自明な対策として、とりあえずノートPCを閉じることにした。自分は作業中(妻はミーティング中)などであればこれで良い。ノートPCにはUbuntuが入っているのだけど、デスクトップLinuxって気軽に閉じても大丈夫なのかなと不安になったが、意外と安定して動いている。最近のLinuxはえらいね。

これならキーボードが露出しないから踏まれなくなるけれど、ミーティング用のカメラがほかにないので、究極的な解決策にはならない。ミーティングではどうしてもノートPCは開かないといけないのだ、いまのところは。ではどうしよう。

というわけで思いついた解決策は2つ。ひとつは外部ウェブカムを買ってきてミーティングにそれを使うこと。もうひとつはノートPCスタンドみたいなのを買ってきてその上に載せること。

実は妻も同じようにノートPC+外部モニタ+外部キーボード+外部マウスという構成で、ノートPCも机同士の境界側に置いているのに、キーボードを踏む被害が起きていないのだ。それは妻がノートPCスタンドを使ってるからではないか、と思ったのだ。こういうやつね。

値段を比較してみたらさすがにスタンドのほうが安いので、設置してみた。いいかんじだ。

子が寝たあとで設置したので部屋は妙に暗い

それでスタンド初日の今日。妻は出勤日だったのであれだけど、やはり猫はやってきて机のあいだをいったりきたりしてきた。が、ノートPCはさすがに高い位置にあってジャマなだけなので、踏むことなく済んだ。成功だ。副次的効果として、ノートPCが高い位置にあって画面がみやすくなって、それもいい感じだ。いやそれは副次的ではないな。

wordpressのtwitter連携

https://www.itmedia.co.jp/news/articles/2305/02/news087.html

The End of Twitter Auto-Sharing

Update: May 18, 2023. It took a few weeks, but Twitter finally shut off our API access. Though we were in limbo for a bit, we can now confirm that our services have been disconnected and Twitter is no longer part of Jetpack Social.


In early April, we experienced an unexpected suspension of our Twitter API access. This access is what powers Jetpack Social, which in turn helps you automatically share your blog posts to Twitter. Though the service was restored that same day, it turns out that there were bigger changes looming on the horizon. 

Twitter decided, on short notice, to dramatically change the terms and pricing of the Twitter API. We have attempted to work with Twitter in good faith to negotiate new terms, but we have not been able to reach an agreement. As a result, the Twitter connection on Jetpack Social will cease to work, and your blog posts will no longer be auto-shared to Twitter.

You will still be able to share your posts to Twitter manually by pasting the post link into the body of your tweet. 

In addition, you can still auto-share your posts to Tumblr, Facebook, and Linkedin. In the near future, we are adding the ability to auto-share to Instagram and Mastodon. We are continuing to release new features in Jetpack Social, so keep an eye on the Jetpack blog for more updates.  

We apologize for any inconvenience this causes for your website and marketing efforts. We wish the outcome had been different, but our customers are always our primary concern, and we’re not willing to compromise the experience or value you receive from Jetpack. 

This entry was posted in Jetpack News, Social Media. Bookmark the permalink.

Jetpack News Social Media

Kristina P. profile
Kristina P.

Chief of Staff on WordPress.com. Former entrepreneur. Lover of people, the outdoors, running, cooking, dancing, hiking, biking, reading, WordPress, WooCommerce, Jetpack and so many things that I haven't even discovered yet.

Explore the benefits of Jetpack

Learn how Jetpack can help you protect, speed up, and grow your WordPress site.Get up to 50% off your first year.

Explore plans

April 29, 2023, 9:45 pm 0 boosts 0 のお気に入り

twitter連携、もういいかと思って手動で切ったけどAPI有料化につき自然消滅だったのか。そのへんもお金とるんだねぇ。そんなことをしても得にならないような気がするけど、まあそういう方針ということなので仕方ないね。

Automatticはmastodon連携のほうを頑張ってください。いつ来るかなあ。

Rustその後

本記事、ちょっと前に書いたけど公開しわすれていた。

Rust、まぁなんとなくわかってきた。データ構造のコードはそれなりに練習になった。

  • unsafeなしのsingle-linked-listをBoxを使って書いた。やってみたらそれほど難しくない。あとイテレータは戻る必要がないので実は簡単。なんでdouble-linked-listにする必要あるんだろう? cursorというAPIは戻れるようになっているが、これはexperimentalとのことで手元では実装していない。実装するならzipperを使うことになると思うが可能ではありそう。ただzipperの構造はちょっと複雑かもしれない
  • そもそも連結リストだけど途中に要素を差し込んだり途中の要素を削除したりすることもないので、複雑さはそこまででもなかった
    • removeとかあるけど、リストに対してインデックスの数値を渡してO(n)で削除するインタフェースになっている。連結リストの存在意義とは……?
  • 作ったリストを2つ使ってqueueを書いた。Chris Okasakiの本に書いてあるやつ。これはかなり簡単
  • 興がのってきたので binomial heap と fibonacci heap も書いてみて、テストをいろいろ書いてみたりした。なかなか楽しい。うまいことしてベンチマークを書いて計算量が理論どおりになっているかを調べたいところだが

オーナーシップ、copy/move、moveによる無効化はいまだに戸惑うし、ルールはわかりづらいように思える。とくにstructのフィールドの一部をもちだしたいときのエラーメッセージが「copyにしましょう」だったりするのがわかりづらい。意図せずコピーしているケースもありそう。

moveが実際にどのようなオペレーションになるかがまだよくわかっていない。ローカル変数同士、ヒープ変数同士であれば変数の指し示す対象を切り替えるだけの操作で済む気もするが、実際にはコピーになっていて意外と高コストだったりしないんだろうか? もっともほとんどのmoveではshallow copyなので、そこまで遅いことはないのかもしれない。

まぁC++でもクラスや構造体はmoveできるが、std::unique_ptrを使うほうがよくあるし、Boxなどを使うほうが普通なのかもしれん。

そろそろデータ構造のおさらいだけじゃなくて、何かツール的なものを作ってみたい。さてなにを作ろうかね。

twitterにフィードを流すのをやめることに

してみた、というのが本記事の趣旨ですが、この記事はtwitterにフィードとして流れる予定です。ややこしいな。

↑こんなことを書いていたんですが、それからすっかりtwitterは見なくなりました。面白ツイートみたいのを教えてもらったりしたら見てるけど、自分のタイムラインはほとんど見てません。ポッドキャストの https://misreading.chat/ のほうは新しいエピソードのたびに宣伝ツイートをしていたんですが、impressionを見たら非常に虚無感がただよう感じだったので、数回前からこれもやめることに。というわけで非常にinactiveな感じです。

このブログの投稿はwordpressの連携機能でtwitterに流していたし、そこ経由で読みたい人もたくさんいると思うしまぁそれはいいか、とは思ってた。んだけど、なにか反応があったりするとそのために読むのはかったるいし、あんまり考えたくないなという気持ちになってきた。なのでいったん止めることにします。というか前回の投稿で止めてたのでシェアされてないんだけど、止めたことをお知らせする必要はあるんじゃないかと改めて思ってこんな記事を書いています。

twitterで出てきたときだけ読んでいたという奇特なお方は、RSSリーダなどで読むか、またはmastodonではシェアしたりするかもしれないのでそっちをご覧ください。あるいはなんだろうな……wordpress.comがactivitypubに対応してくれたらいいんですけど。Automatticがんばれ。というかtumblrがActivitypub対応するって話はどうなったんだ。

断線生活

3月14日に嵐がサウスベイを襲った。雨はそれほどでもなかったが風が強くてどうかなあと思っていたら家のインターネットが落ちてしまった。数時間で復旧するかなと思っていたら、24時間たってもまだ落ちている。

調べてみたら偶然うちは大丈夫だったが近所に停電が広がっているらしい。その停電も続いていて、たぶんインターネットの設備が停電エリアにあるので落ちたままなんではないか、という気がする。なかなかのおおごとである。今回はベイエリア全体で15万世帯とか停電しているらしい。

強風で停電というのは昔はよくわからなかったが、このリンク先にもあるように強風によって街路樹が倒れたり折れた枝が吹き飛んだりして被害をあたえているようだ。送電網のトポロジーと被害箇所で停電エリアは決まるので、今回うちが大丈夫で近所は停電していたりするのは、もうほんとうに偶然でしかないのだった。

停電しなかったのはよかったがしかし、インターネットがないと本当の意味で仕事にならないので、今日は回線を探し求めて外出した。ノマドワーカーだ。

最初に向かったのは図書館で、ここはけっこうよかった。同じような境遇の人々がいて混雑していたがなんとか空き席を確保して仕事ができた。インターネット回線も速くはないがふつうに安定している。ありがたい。

昼食を食べるために離席して、ついでに移動もするかとRed Rockカフェに行ったが、ここは停電で閉店していた。ダウンタウンはおおむね停電の影響がなくてみな営業していたけど、ここの区画だけ停電があったらしい。

そこからは新しい場所をさがしてすこしさまよい、カフェに行ったりして仕事をしていた。図書館もカフェもどこもそれなりに賑わっていた。平日ふだんどれくらいの賑わいなのかは知らんけど、やはり自分と同じような境遇の人が多いからだと思う。

学校も閉鎖していたりするので子連れの人たちもよくみかけた。子供を座らせて宿題をやらせているな……という母親をみかけたりした。

ちなみに台風一過かどうなのか、今日は素晴らしい天気で青空が広がり、すこし暑いくらい。ぽかぽかとしたいい一日だった。これほどいい天気だがしかし停電トラブル、という対比はなかなかにシュールであった。

それにしても停電もインターネット断もなかなかのおおごとである。強風や大雨で落ちるのはめずらしいが、このへんだとまあ、たまにあるなという感じ(こんなに長期なのははじめて体験したけど)。一方、これくらいの強風は日本のほうがおおそうなものだが、倒木やそれにまつわる停電とかはあまり聞いたことがない。なんでなんだろうな、というのは気にはなる。

首都圏はそこまで木が多くなくよく管理されているので、強風で被害がおきそうなやつは切っちゃったりするが、このへんはそういうのを放置しがちだし巨木も多くてそういう管理が大変だからではないか、というのが妻の説。このへんは人口が東京みたいに密ではないので送電網もsparseになっていてresilienceが低いんじゃないか、というのが友人の説。どっちもありそう。両方の組み合わせだったりするのかもね。

明日もまだ断線していそうだ。明日はどこに出かけるかな……

Rustでsafeな連結リストをつくる試み

前回の記事を書いてから、考えてるだけじゃだめだなとすこし書いてみたところいろいろわかった。

Rcによるリスト

Rcはリファレンスカウントで管理できる。RcはWeakをつくれるので、たとえばnext方向にRcをつなげておき(先頭ノードはリスト本体が保持)、prev方向へはWeakを持たせればいいのではないか? と考えてみたのだった。

やってみたところこの方針では書けないということがわかった。Rcの参照先は基本的には更新ができない。ノードを追加したらprevやnextを書き換えないといけないけど、書き換えができない。書き換えをするには mutable なリファレンスを一時的に獲得する必要があるが、weakも含めたリファレンスカウンタが1でないといけない(これは安全性のためだろう)。prevとnextで基本的にノードにはstrongが1つとweakが1つ常にあるので、mutableなリファレンスを獲得できない。

なのでこの方針で書くことはできないのだった。マジで?

Arc / mutex によるリスト

ArcはRcのようなリファレンスカウンタだが非同期でアクセスできるようになっている。mutexと組み合わせると一時的に書き換えができたりする。どう考えてもオーバーヘッドが大きいから現実的じゃないけど、これならRcの問題は解決されるんじゃないだろうか?

解決される、というふうには思う。だが問題があった。要素の参照を返せないのだ。

たとえば、先頭要素を返す front() メソッドを書いてみたとする。こんな感じになる。

pub fn front(&self) -> Option<T> {
    if let Some(n) = &self.head {
        let node = n.lock().unwrap();
        Some(node.element.clone())
    } else {
        None
    }
}

このコードでは結果の値を clone して返している。単純に&node.elementとする場合、そのライフタイムはnodeのライフタイムに縛られる(Mutexのlockというのはそういうものだ)。なので返される値はifの中が終わった瞬間に無効になるのでコンパイルできない。

こういうインタフェースを実装していくのは可能だが、cloneできるものに限定するのもイマイチだし、要素アクセスのたびにcloneされるのはまったく現実的ではなさそうだし、要素を書き換えたいときのイディオムが変わってしまう(front_mutみたいなものは書けない)。イテレータのインタフェースも標準的なものとは変わってしまう。

というわけで、やはり現実的ではなさそうだ。

他の誰かに所有してもらう

ノード間でオーナーシップを持つのはおかしいんじゃないかという気がする。ノードのオーナーはリスト本体であってそいつが所有していればいい。あとは適当にリファレンスを持てばいいんじゃないか。こんな感じ。

struct Node<'a, T> {
  element: T,
  next: Option<&'a Node<'a, T>>,
  prev: Option<&'a Node<'a, T>>,
}

struct LinkedListVec<'a, T> {
  nodes: Vec<Node<'a, T>>,
  head: Option<&'a Node<'a, T>>,
  tail: Option<&'a Node<'a, T>>,
}

ノードをベクタで管理していて連結リストとは……という気持になるが、適切にreservedなサイズを増やしていけば追記するだけならamortized costはO(1)なのでいいんじゃないか。本気でやるなら削除したノードを管理しないといけないが……。

だがどうもライフタイム解析で失敗してしまい、うまくいかない。リストがノードを保有していてその生存範囲では有効ではあるが、そのようなことをうまく表現できていないような気がする。

というわけでこの方向性もうまくいかなさそうだ。

ちなみにだが、next/prevをusizeにしてしまい、nodesの中の場所をインデックスで指定する、という方法ならたぶん大丈夫だと思う。しかしそれはなんというかもはや、nodesをメモリ領域にしてインデックスをポインタがわりにしているのとほぼ同じことである。そりゃまぁ unsafe という言語機能は使わないが、インデックスの先がほんとうに生きているものかの保証があやういので(途中でノードを破棄したときとか)、ぜんぜん安全な感じがしない。さすがにアホっぽい気がするのでこれは試していません。

まとめ

というわけで、double-linked-listをsafe Rustの範囲内で作るのはどうも無理っぽいというので正解という気がする。raw pointerとunsafeバリバリなstdのリスト実装が一番現実的なのであった。そこまで複雑じゃないからね、という話なのかもしれない。

しかし、linked listていどのことすら適切に表現できないような言語仕様というのはどうなんだろうか。どうも自分は不思議な気持ちになるんだよな。なにかもっとうまい仕組みがあったりしないんだろうか?

ところで single-linked-list なら、まぁ Box とかを使えばいけそうな気がする。双方向イテレータも zipper とかを使えば実現できるんじゃないかな。でも実際にやってみたらいろいろ罠があるんだろうか。

Rust再入門

なんかそろそろまた入門してみるか、という気持ちになったので勉強してみることに。

なにかしらちょっとしたものを作ってみるぐらいがいいかなと思うが、プロジェクトアイディアをさがしていても進まないのでまずなにかを読んでみることにした。とりあえず std にある linked list のコードを読んでみた。あと deque と binary heap。このへんは単純。 B-tree も読んでみようかなという気がするが格段に複雑になるね。

linked list はつくりは単純なので理解はできるが、わからないこともあったので疑問を書いておく。

linked list は基本的に NotNil (ほぼ raw pointer のラッパ)を使っていて、unsafeだらけだ。なぜだろうか?

第一に std の linked list は double-linked list で、各ノードはバックリンクを持つ(リスト本体も先頭と同時に末尾へのポインタをもち、push backがO(1)でできるようになっている)。single-linked listならオーナーシップを連結させればよさそうな気がする。

2つのオブジェクトが相互にリファレンスを持っているというのは単純な循環リンクなので、たとえば単純なリファレンスカウント (Rcなど)では適切に管理できない。drop時に適切にリファレンスカウントを減らすようなコードを書かないといけないが、それならraw pointerを開放していっても手間がいっしょ。ただRcからweakをつくれるようだ。それならできる?

そもそも単純に、あるノードが次のノードの所有権を持つとすると、そのノードのライフタイムは確定できるので、次のノードが前のノードへのポインタを持っていても安全性は保証できそうな気がする。安全なweakポインタというか。そういうのってないんだっけ? あったらこんな仕組みになってないとおもうので、ないんじゃないかという気がするけど、どうして存在しないんだろう。こんな単純な例ならいいけど現実的にうまく解析できないとか、そういう理由なんだろうけども……。

疑問の2。raw pointerを使えばいいような気もするけど Option と NonNil を組み合わせているのはなぜ?

これは単純で、raw pointerはnilかどうかをチェックするのもunsafeになってしまうから、かなぁ。

コードレビューコメント

https://zenn.dev/anatoo/articles/14612f027194e5

なんか「詰められている」ように受け取られてしまう、というのはちょっと日本文化的な気もするが(というかコードレビューで詰めたりするなという気がするが)、質問だけだと意図が伝わらないということはまあよくあるという気がする。

でも自分はタグみたいなものは使わないかな。「これなんでですか?」みたいなコメントは、そのコメントで解決したいことが明らかではない気がするから。もうすこし言葉を増やして解決可能なコメントにするのが良いと思う。

たとえば「この行、必要なんでしょうか。上のほうでこういうことをしているから、これなくてもいいと思うんですが何か見落しているんでしょうか」とか。あるいは「この部分はデバッグ用のやつでは」とか。または「メインの変更と関係ないので別PRに分けてください」と言ってみたり。

「本当に意図がわからないので教えてください」ということはあるけど、「なぜこの変更が必要なのかコメントも書いてください」というお願いをしてみたり。

まあだんだん簡潔になりがちなんだけど、なぜ?というコメントはそもそもよくないものなので、自分がなにを解決したいのかに沿ってコメント内容を変えるべきなんじゃないか、ということを思った。

……と思ったけど、タグ、まあ使うこともあるな。主に nit: というやつ。これは nitpicking の略で、重箱の隅をつつくようなタイプのコメントを意味する。本質的ではないのでどうでもいいっちゃいいんだけどいちおう指摘します、みたいなときによく使う。たとえば変数名がミススペルしてるよとか。

定型的な書き出しでコメントの意図を制御することもある。just curious / out of curiosity というのは変更してほしいわけではなくて教えてほしいんですが……という意図だし、you don’t need to change this PR but … みたいに「いまやる必要はないと思うけどこういう問題が起こることもあると思います」みたいなことを言うことはある(後者はだいたいTODOコメントするかバグをファイルしてあとでやりましょう、みたいな方向にもっていく)。

でもまあ、タグみたいなものよりは全体的にコメントは長めにしておくことで意図を伝えるほうが一般的には良い方向性だと思う。