カテゴリー: Uncategorized

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

ブログで書いたことがあるかどうか覚えてないけど、知人友人には周知のようにかれこれ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

https://jetpack.com/blog/the-end-of-twitter-auto-sharing/

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コメントするかバグをファイルしてあとでやりましょう、みたいな方向にもっていく)。

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

シーズン:未来への手紙

クリアした。

なかなかよかった。雰囲気ゲーム。寂寥感のある雰囲気がいい。盛り上がりもなにもない、ひたすらチルなゲームだ。

村の住人のひとりが不思議な悪夢をみた。長老によると「季節」の終わりが近づいているのだという。主人公はいまの世界のありさまと「季節」のおわりを記録するために村を出て旅に出ることにする……といった設定。プロモーションではあんまりはっきり書かれていなかった気がするが異世界が舞台で、この世界はどうも「季節」というものが移りかわることで世界がはっきり変化してしまうようだ。繁栄していた黄金の季節、戦争の季節、そしてまだ名前のついていない今の季節……。

ゲームプレイは、舞台となる世界のあちこちを行って、いろんなものを観察したり、写真に収めたり、レコーダーで録音したり。そういう素材を、もっているノートにまとめていく。それだけ。まとめるのもいろいろ凝ってデザインしてもいいし、雑にペタペタ貼るだけでもいいし、まあべつに何もしなくたっていい。基本的なことだけでストーリーは進んでいく。

ゲームとしては小規模のゲームで、数時間もやっていれば終わる。もうすぐ世界が終わる(変わる)というぼんやりとした寂寥感と終末感を味わうようなゲームだ。内省的なモノローグ、思わせぶりな台詞や世界観がなかなかいい。

クリアしたのでレビューを読んでいたらkotakuのレビューではコテンパンに批判していたが、あまり納得のいく批判には思えなかった。が、このレビュアーのような期待感をもってプレイする人というのはいるだろうし、そこには向いていないだろう。まぁ内容こんだけかとか、これで終わりなのか、ってなるもんな。

ロードス島戦記ーディードリット・イン・ワンダーラビリンスー

唐突に手元のゲーム機でプレイできることに気づいてやってた。2021年にいきなり発売されたロードス島戦記のゲーム新作。ディードリットが主人公のメトロイドヴァニア。

https://en.wikipedia.org/wiki/Record_of_Lodoss_War:_Deedlit_in_Wonder_Labyrinth

自分程度でもクリアできるぐらいの難易度で、かと言って簡単すぎるということもなくて割といい塩梅でよかった。ただ歯車に矢を当てて回すギミックが苦手で、かなりうんざりというところが途中に何度かあったけど。

ストーリーは、まあそういうんだろうなという展開でしかないが、良かったんじゃないでしょうか。知ってるキャラが出てくるだけでなんだか懐かしい、というのもあるがそれを通り越してもう何十年も触れていないコンテンツなので単語は知ってるけどどういうんだったっけみたいになってしまっていた。

非常におっさん向けなコンテンツという気がするけど、ターゲットな人たちはプレイすると楽しいんじゃないでしょうか。