月: 2023年9月

TIL: lightning vs lightening

ライトニングケーブルの話題のたびに「あれっ」と思って調べて、なるほどーと思ってまた忘れる、というのを何度か繰り返している気がするので、何度めかのTILだと思うが、lightningとlighteningは違う単語なのであった。lightningは雷、稲妻のこと。lighteningは「明るくする」ということ。前者はふつうの名詞。後者は動詞の現在進行形。

なんとなくlight + en で lighten から派生したように思って、ついlighteningが雷の意味の語の正しい綴りである、みたいに思いがちなんだよね。lightningは簡略的な綴り、みたいな。でもそうではない。

明るくするほうの lighten は14世紀初頭から使われはじめた用法で、light-enという現代英語と同じルールの単語。いっぽうlightningのほうは語源は古英語のlightnen(「明るくする」)かlihting(光)からきているらしい。

っていうことは、語源(の説のひとつ)のlightnenとlightenは同義っぽい気がする。が、単語として確立したのが古英語の時代からなので綴りとしてはこうなってる、ということなのかね。ちなみにGoogleの検索結果で教えてくれる語源では、中英語期の綴りはlighteningだったということが書いてあってよくわからないといえばよくわからない。

というわけで学びがありました。でもまたすぐ忘れると思います。そしてライトニングケーブルの話題を見ることはもうないので学ぶことはないかもしれない。

https://www.grammarly.com/blog/lightening-vs-lightning/

https://www.etymonline.com/word/lighten#etymonline_v_30828

https://www.etymonline.com/word/lightning#etymonline_v_9506

JSONとBigInt

ちょっと前にblueskyで見かけた話題。もとは「GraphQLのスキーマではintが32ビットしかなくて、64ビット整数とかないのがイケてない」といった話だったかなと思う。直感的にはこれは「Javascriptではすべてが倍精度浮動小数点数だから64bit intがないから」ということになるが、よくよく調べてみるといろいろややこしい歴史的事情があるようだ。

たしかにJSにはもともとひとつのNumber型しかなく、いわゆるdouble型(倍精度浮動小数点)だけで数値を表現してきた。IEEE754の倍精度浮動小数点数は仮数部が52ビットあるので、実際には32ビット整数ていどであれば全て誤差なく表現できる。なので32ビット整数または倍精度浮動小数点数がどちらも使えるというふうに理解されてきた。

そうはいっても不便なので、現代のJSにはBigIntがある。ES2020で導入されたらしい。ただし普通の数値リテラルはすべてNumberであり、BigIntにするためにはnを後置する必要がある(0nみたいに。または明示的にコンストラクタを呼ぶ)。BigIntとNumberはimplicitには変換されず、明示的に変換する必要があり、取り扱いはちょっと面倒ではある……が、存在するのは有り難い。ともあれ、BigIntはあるので「すべてがdoubleなので64ビット整数は扱えない」というのは現代では厳密にいうと正しくない。

一方、ウェブのAPIというものはだいたいJSONをフォーマットとして利用している。元々の話題であるGraphQLでもそうで、レスポンスはたいていJSONだろう。そしてJSON自体はBigIntなどが導入されるよりはるか昔に制定された規格なので、BigIntであったり整数に後置する記号(nとか)のことなんか考えられていない。このためにBigIntを利用できない。というわけでJSONは仕様上ではdoubleしかない、というふうに理解・整理できそうではある。

……かと思いきや、実はJSONの仕様上では数値の桁数などに制限はない。あくまでも表記的なフォーマットの話だから、数値データでは数字をいくらでも連ねてもよい。つまりフォーマットとしては決してdoubleに縛られているわけではない。

がしかし、その数値データをどのようにデコードするかというロジックはデコーダ側の実装にゆだねられている。JavascriptではJSON.parseによってデコードするのが普通だが、ECMAscriptの仕様で定義されるJSON.parseの挙動によればJSONの数値はすべてNumberになることを定めているので、どれだけ大きな桁数の数値であってもけっきょくはdoubleの精度までしか扱えないし、BigIntにはできない、ということになる。

つまるところ、「JSONは昔のJSの仕様がもとになっているのでBigIntのことなんて知らんし」「JSにおけるJSONの扱いにおいてはBigIntのことはなかったことになっている」ということになっている。お互いがそれぞれ新しい状況に対応できていない感じ。

どうにかならないもんだろうか。ちょっと考えてみる。

案1:ECMAscriptのJSON.parseの仕様を改めdoubleで表現しうる以上の整数はBigIntにデコードするように変更する。ただこれをしてしまうと、値の大きさによってBigIntかNumberか型が変わってしまうので、デコード結果を扱うのが面倒になる。先述したようにJSではBigIntとNumberはimplicitには変換しない方針なのも大きい。小さな値のBigIntを含むオブジェクトをJSON.stringifyしたものをJSON.parseすると違うデータになる(Numberになっちゃうから)という問題もある。

案2:JSONの仕様を変更してnのような後置を認める。これはJSの利用者からすると有り難いが、世界中に無数にあるいろんなプログラミング言語のJSONライブラリとの互換性が崩れるという難しい問題がある。互換性の問題が発生してしまう。新しい仕様への対応を済ませてサーバ側が新しいフォーマットを返すようにしたら古いクライアントで動作しなくなるといったことも起こる。

というわけでなかなか簡単な解決策はないのであった。sigh。

JSON5みたいな類似フォーマットで対応できてないのかな、と思ってみたが、JSON5も不可であった。BigInt登場以前からあるからかな。

YAMLの場合にはBigIntに対応できている。そしてYAMLはJSONの厳密な拡張である(つまり、正当なJSONは正当なYAMLである)。なのでJSON.parseのかわりにYAML.parseすることでBigIntにできる可能性はある。npmのyamlパッケージだと intAsBigInt というオプションがあって、これで全部BigIntにできるようだ。ただし、あまりにもトリッキーなので実用することはなさそうな気がする。

もちろん全く他のシリアライゼーションフォーマットを採用するという手もある。たとえばBSONにも64bit整数はあるし、messagepackにもある。毛色は違うがprotocol buffersにもある。ちなみに、protobufにはJSONデコーダ/エンコーダもあるが、protobuf/jsonは64ビット整数を文字列にエンコードしている。スキーマがあるので、どの文字列を64ビット整数としてデコードしてほしいかがわかっているので、こういうことができる。ただ、調べたかぎりでは任意長のいわゆるBigIntをサポートするフォーマットはなさそうだ。言語によってはBigIntが外部ライブラリになってしまったりするからね、C++とか……。

けっきょくいちばん現実的なのは「64ビット整数やBigIntはネイティブにはサポートせず文字列にする。適宜文字列からBigIntなどに変換するロジックを持つ」という一種のstatus quoなのだな。変換は場合によってはわりと面倒なのでフレームワークが適切に対応してくれないと厳しいが、そのためには「どの文字列はBigIntであるべきか」という情報、つまりスキーマ定義が必要になってしまうので自動化しづらい。TypeScriptの型情報とかをうまく使ったりできたら面白いんですけどね。できるのか知らないけど。

それでいうと、元の話題にもどるとGraphQLではスキーマがあるのだからint64を持っていてBigIntで取り扱うということはできそうではある。ただそうするとエンコーダ・デコーダに専用のライブラリが必要になってしまうのが痛いという判断なのかもしれない。


ところで、JavascriptのJSON.stringifyはBigIntをエンコードできない、というのはこの記事を書くために手元で試すまで知らなかった。BigInt……めんどうくさい……。

アイスランド旅行: パフィン、ブルーラグーン、そのほか

アイスランドを象徴するような動物はいくつかありそうだが、その筆頭になるものがあるとすればパフィンだと思う。

ペンギンを思わせる黒と白のカラーリングに派手な嘴の小さな海鳥だ。産卵のためアイスランドに夏にやってくる(らしい)。パフィンはアイスランドのいたるところでキャラ化しており、土産の意匠としても一番メインというかんじ(もうひとつの主役はヴァイキングたち)。ぬいぐるみ、フィギュア、キーホルダー、ステッカー、衣類、ほんとになんでもある。わたしはTシャツと靴下を買った。

さてそんなパフィンだがもちろん観察ツアーもある。パフィンがいるのは夏だけで、ツアーはだいたい8月下旬には終わるようだった。わたしが行った時期はほぼ終わりかけだったけどなんとか期間内ということでツアーに参加できた。

なお、アイスランド最大のパフィンコロニーは島の南のほうだそうで、そちらにいくともっとたくさん見られるようだったが、そちらに行くのはすこし面倒そうだったので、レイキャビクから行けるツアーを選んだ。市内の港から船で出て15分ほどで行けるコロニーを見るというような1時間ほどのツアーだ。

終わりかけの時期だし、首都から近い場所だし、どうかなーと思ったけど、パフィンはあっさり見られた。けっこう小さな鳥だし船ではそこまで近寄れないし、さすがに最盛期よりは少ないだろうし、持ってるのは携帯電話だけだし子供は抱っこせにゃならんし、というわけですごくいい写真は撮れなかったのだけど、たくさん見られて良かった。ツアーは2箇所ぐらい巡ったが、どちらにもたくさんいた。

パフィンツアーはとても楽しかった。もっとたくさんいる時期には街にも迷い込んだ小鳥がいたりするらしい。最大のコロニーのある場所だとさらにもっといっぱいいるとか。またアイスランドではパフィンを食べるという話もあるようだが、パフィン料理は都合がつかず食べられなかった。


話はかわってブルーラグーン

ブルーラグーンはアイスランドでもかなり大きな観光施設である。そこそこ大きな湖というか池みたいなものが丸ごと温泉になっているという話。実際にはここにジオサーマル発電施設があり、その関係で副産物的に出来た温泉であるらしい。

こちらもなかなか楽しいのだけど、アイスランド旅行としては異質という気がした。非常に完成度の高い観光施設というか温泉施設というか、そういうものになっており、火山が噴火したので溶岩見学ツアーするぜ!みたいなのとは対局にある感じがするため。でもいい場所ではあった。空港にほど近く、レイキャビクからはけっこう離れている。わたしは到着したその日にそのまま行った。入場するなら予約はしておいたほうがいい。レイキャビクからはツアーバスがあるのでそれを利用するという手もある。


というわけで、アイスランド旅行で書こうかなと思ってたことはこれぐらいかなと思う。パフィンはかわいかったし自然はすごかった。レイキャビク市内も楽しい。あーあとそういえば緯度が高いのでまったく陽が沈まなかった。夏至あたりでは白夜になることもあるようだ。わたしが行ったときはだいたい夜10時ぐらいが日没とのことで、夜11時になれば真っ暗なのだが、夜9時ぐらいに散歩したときにはこれぐらいの明るさ。

逆に冬となればまったく陽が登らない極夜にもなるらしい。冬も冬でオーロラツアーとかあるみたいだけど、ハイシーズンはやっぱり夏かなぁという気がする。こういう緯度が高い場所は気候が極端になりがち。

そういえばアイスランドは経度としてはレイキャビクあたりで西経20度ほどにもなるようだが、イギリスと同じタイムゾーンを採用しているらしい。しかもサマータイムがないので、時刻は常にUTC。なんか知らんけど便利そうだ。でもまぁこのズレは日没時間とかに微妙なズレを与えているはず。

というわけでアイスランドでした。サンフランシスコからは直行便がないのでそうそう気軽に行けるような場所ではないけど、また行きたいなあ。とくに子がもう少し大きくなって移動の自由度が増したらまた行きたいね。