星にゃーんのブログ

ほとんど無害。

自作プログラミング言語Malgoがかなりそれっぽくなってきた

プログラミング言語Malgo

2017ごろから、自作のプログラミング言語Malgoとそのコンパイラを作っている。 2018年の2月に、このことをブログに書いた。 あれから三年経ち、色々とできることが増えた…かというと、そうでもない。 しかし、言語設計はかなり変わった。ガワだけ見るとほとんど別物だ。

当時のブログ:https://takoeight0821.hatenablog.jp/entry/2018/02/28/122847

現在のMalgoは、Haskellに影響を受けた構文を持つ、非純粋な正格評価の言語だ。 型推論高階関数、代数的データ型などの、いわゆる「関数型」な言語機能を備えている。 例えば、フィボナッチ数を計算するプログラムはこんな風に書く:

-- Fibモジュールの宣言
module Fib = {
  -- Builtinモジュールのインポート
  import Builtin;
  import Prelude;

  -- 外部関数newlineのインポート
  -- newlineの実装はCで書かれている
  foreign import newline :: () -> ();

  -- 中置演算子<=の定義
  infix 4 (<=);
  (<=) = { (Int32# x) (Int32# y) -> isTrue# (ge_Int32# y x) };

  infixl 6 (+);
  (+) = { x y -> add_Int32 x y };

  infixl 6 (-);
  (-) = { x y -> sub_Int32 x y };

  -- フィボナッチ数列のn番目の要素を求める関数
  fib = { n ->
    -- ifは関数として定義されている
    -- {}で囲まれた値は遅延評価される
    if (n <= 1)
      { 1 }
      { fib (n - 1) + fib (n - 2) }
  };

  main = {
    print_Int32 (fib 5)
  };
}

Malgoの言語設計

Malgoは、できるだけ言語仕様が小さくなるように設計されている。 これは、実装の負担を軽減するためと、僕個人の好みが主な理由だ。

言語の小ささを表す象徴的な例にif関数がある。 Malgoのifは、次のように関数として定義されている。

if :: Bool -> {a} -> {a} -> a;
if = { True t _ -> !t
     | False _ f -> !f
     };

重要なのはif関数の型Bool -> {a} -> {a} -> aだ。 波括弧{}で囲まれた型の値は、明示的に評価(!演算子)されるまで評価が遅延される。 これによって、ブロックを第一級の値として扱うことが可能になっている。

Malgoコンパイラの実装

MalgoコンパイラLLVMを用いて実装されている。 MalgoのソースコードLLVM IRに変換するわけだが、これは自明な処理ではない。 だいたい次のようなことを考慮する必要がある。

関数値の表現方法

LLVM IRには関数値を表現する方法がない。 Malgoは関数値を多用するので、これは困る。 そこで、クロージャ変換という方法を用いる。

クロージャとは、関数ポインタと自由変数の値の組だ。 例えば、連想配列envinsert関数を使って要素を追加する、 次のような関数を考える。

-- 連想配列envと関数insertは定義済みとする

let insertToEnv = { name val -> insert name val env };

この関数をコンパイルするためには、

  1. 関数にユニークな名前をつける(LLVMでの関数名、関数ポインタの名前になる)
  2. 自由変数を求め、引数に付け加える
  3. 自由変数の値と関数ポインタを組にして、クロージャとする(これがinsertToEnvの実態となる)

また、insertToEnvを関数として呼び出す際は、組を分解して関数ポインタと自由変数の値を取り出し、 取り出した関数ポインタに自由変数の値と本来の引数を引数として与えて呼び出す必要がある。

クロージャ変換の結果、上記のコードは次のように変換される(擬似コード)。

-- insertToEnvの関数部分
define insertToEnv_impl(name, val, captures) {
  insert = captures[0];
  env = captures[1];
  return insert(name, val, env);
}

define ... {
  // insertToEnvの定義
  insertToEnv = (insertToEnv_impl, (insert, env));

  // insertToEnvの呼び出し
  closure_func = insertToEnv[0];
  closure_captures = insertToEnv[1];
  closure_func(name, val, closure_captures);
}

型消去

Malgoはパラメータ多相を持つ。例えば、次のようにしてパイプライン演算子|>を実装できる。

infixl 0 (|>);
(|>) :: a -> (a -> b) -> b;
(|>) = {x f -> f x};

|>には、どんな型のxfでも渡すことができる。 "Hello, world" |> upcase |> putStrLnとか、2 |> { x -> x * 20}のように書ける。

|>LLVM IRで定義するには、型変数abをどのように表現するかを決める必要がある。 型消去は、「すべての型の値が1ワードだと仮定すると、単に型を無視するだけでパラメータ多相を実現できる」というアイディアだ。 Malgoでも型消去を採用している。

型消去を実現するための方法はいくつかあるが、最も単純なやり方は、 符号拡張なりヒープへの割り付けなりで、すべての値を1ワードに収めてしまう完全なボックス化である。 Malgoはユーザー定義型が代数的データ型しか存在しない(構造体とかがない)ので、 プリミティブ型のボックス化だけを定義すればよく、完全なボックス化は自然に実装できる。

型消去により、|>LLVM IRにおける型は次のようになる(ここではクロージャを無視している)。

{ i8*, i8* (i8*, { i8*, i8* (i8*, i8*)* }*)* }* @"|>"(i8* x)

ちょっとごちゃごちゃしているが、引数xの型がi8*になっているのがわかる。 (i8*は、Cにおけるvoid*に相当する)

アンボックス型

前節では、完全なボックス化の実現のためにはプリミティブ型のボックス化を定義すればよいと述べた。 しかし、実際にはMalgo処理系にはボックス化の方法が定義されていない。 プリミティブ型のボックス化は、次のようにユーザー定義の型と関数で実現される。

-- 32bit符号付き整数のボックス表現
data Int32 = Int32# Int32#;

-- ボックス化関数
int32# :: Int32# -> Int32;
int32# = { x -> Int32# x };

Malgoの数値リテラルは、42と書くとint32# 42#に変換される。 42#はボックス化されていない生の整数値であり、多相的な関数に渡すことはできない。 これは、型変数aとプリミティブ型Int32#に、異なるカインドを与えることで実現している。 具体的には、型変数aInt32はカインドTYPE BoxedRepをもち、Int32#はカインドTYPE Int32Repをもつ。 また、BoxedRepInt32RepはカインドRepをもち、TYPERepのみを引数にとる。

内部実装では、型とカインドは同一のものとして扱い、型の型はカインドに、カインドの型は自分自身になるように定義している。 型を総称化する際に、カインドRepをもつ型変数があれば、それを型パラメータにする代わりにBoxedRepを代入する。

TODO

だいぶ本物のプログラミング言語っぽくなってきたが、実用的なレベルには達していない。 実装するべき機能はいろいろとあるが、今ぼんやりと考えているのは

  • レコード型
  • 存在型
  • 型クラス
  • 高度な最適化
  • パッケージ管理システム
  • MLライクなモジュールシステム
  • Algebraic effects
  • 構文木マクロ
  • Language Server

標準ライブラリもかなり貧弱なので、近いうちに気合いを入れてガッと実装してしまいたい。

世の中間言語を集める

個人的なプロジェクトとして、コンパイラ中間言語の設計に取り組んでいる。 今できてるのはラムダ計算に毛が生えてコード生成に向いてるセマンティクスを持つみたいなやつで、『星を継ぐもの』に登場するコリエルというキャラクターから名前をもらってkorielと呼んでいる。

まだまだ未完成で、Haskellで扱うためのライブラリはできたが、ドキュメントもなければバイナリ表現やテキスト表現もない。

github.com

今後korielの開発を進めるに当たって、他の「中間言語」について調べてみようと思った。 プログラミング言語については良く知っているが、言語処理系の中間表現についてはあまり詳しくないからだ。

中間表現と中間言語

中間言語っぽいものを表す言葉は二つある。 「中間表現」"Intermediate representation"と「中間言語」"Intermediate language"だ。 これは混乱を招くので、ちょっと整理しておきたい。

まず、中間表現とは、コンパイラVM*1ソースコードを表現するためのデータ構造だ。単純な文字列ではなく、木構造(ASTとか)やグラフ構造(モジュールの依存関係グラフとか)のように、コンパイラVMにとって都合のいいデータ構造が使われている。

中間表現の中でも、プログラムによって読み書きできるコードの形になっているものを中間言語と呼ぶ。

An IR may take one of several forms: an in-memory data structure, or a special tuple- or stack-based code readable by the program.[3] In the latter case it is also called an intermediate language. Intermediate representation - Wikipedia

C

Cは割と良く使われる中間言語だ。もちろん、Cは汎用プログラミング言語として設計された。しかし、他の言語に比べてアセンブリに近いこと、多くのOS、CPUの上で動作する性能の良い処理系が存在していることから、中間言語として採用されることが多い。

言語Aのコンパイラを作るときに、いきなりA to assemblyなコンパイラを書くのは骨が折れる。そこで、A to Cなコンパイラを書き、あとのことはCコンパイラに任せる、というスタイルがある。

他にも、部分的にコードをCにコンパイルすることで高速化をはかることもある。 Cythonはその好例だ。

LLVM IR

LLVM*2コンパイラのさまざまな機能を提供するツールチェーンだ。 もちろん中間言語もあって、LLVM IRという。 Clang, Rustなど多くのコンパイラで使われている。

Kotlin/Native*3というプロジェクトでは、KotlinをJVMを介さずネイティブなバイナリにコンパイルするが、ここでもLLVMが使われている。

他にも非常に多くのプロジェクトで使われている、デファクトスタンダード的存在である。

SSAをベースとしており、Cのより中間言語向きなバージョンといった雰囲気。

共通中間言語 (CIL)

LLVMデファクトスタンダードである一方で、CILはもっとも「名前は聞いたことがある」中間言語だろう。

C#で使われている中間言語で、.NET対応言語はこの中間言語コンパイルされ、アプリケーションやライブラリはこの中間言語の状態で配布される。 ユーザーの環境にインストールされた.NETのVMがこれを解釈したりJITコンパイルしながら実行される。

パッと調べたところ、例えば以下の記事が詳しい。

ufcpp.net

スタックベースで、オブジェクト指向をサポートするための言語機能が充実している。

JVM byte code

JVMはおそらく(Oracleを信じるなら)30億のデバイスにインストールされている。 JVMが実行するJVM byte codeもそれなりに良く使われる中間言語で、Scala、Kotlin、Groovyなど、JVMで動く言語も多い。RubyにはJVMで走るように実装されたJRubyという実装がある。

これもCILと同様に、スタックベースの言語であり、オブジェクト指向をサポートするための言語機能が充実している。

TODO(追記予定)

残り40GBは流石にまずい二日目

昨日は現状を整理して、要らないアプリをアンインストールしよう、というところまでやった。

アプリのアンインストール

/Applicationsからアプリケーションを削除してはい終了、と行けばいいのだが、~/Library以下にゴミが残ったりする。 これを真面目に探して消すか、それとも放っておくかは悩みどころだが、今回は積極的に消していくことにする。 具体的には、du -h ~/Library | grep 'アプリケーション名'で出てきたそれっぽいフォルダを消す。

  • Adobe Acrobat Reader DC
    • ~/Library/Caches/com.adobe.Readerがそれっぽいので消す。
  • Chrome Remote Desktop Host Uninstaller
    • 実行したら異常終了して消えた。他のChromeアプリももろもろ削除。
  • cluster
    • ~/Library/Application Support/mu.clusterがそれっぽいので消す。
  • FTBApp
    • アップデートした。
  • Godot
    • ~/Library/Application Support/Godotがそれっぽいので消す。
  • IntelliJ IDEA
    • アップデートした。
  • Kindle
    • ~/Library/Caches/com.amazon.kindleがそれっぽいので消す。
  • Logisim
    • 特に何も見つからなかった。
  • mtgaprotracker
    • ~/Library/Application Support/mtgaprotrackerと~/Library/Caches/com.mtgarenapro.mtgaprotrackerと~/~/Library/Caches/com.mtgarenapro.mtgaprotracker.ShipItがそれっぽいので消す。
  • PS Remote Play
    • 特に何も見つからなかった。
  • The Unarchiver
    • ~/Library/Application Scripts/cx.c3.theunarchiverと~/Library/Containers/cx.c3.theunarchiverがそれっぽいので消す。

1GBほど減ったはずだが、微々たるものであまり効果を感じられない。

Xcodeのダイエット

Xcodeが15GBぐらい食ってる。多分シミュレータが場所を取ってるはずなので、いい感じに消す。 xcode coresimulatorとかでググると色々情報がある。

~/Library/Cachesって手で消していいんだろうか

ここまでで93.39GBの空きができた。最初40.3GBだったので、53.09GB削除したことになる。

~/Library/Cachesのサイズは15GBだ。これを消したら68.09GB消したことになる。 調べた感じ、消しても良さそうだったので思い切って消す。ちょっと怖いのでゴミ箱に入れて再起動。 VoiceTriggerだけは消せなかったので残した。

結果

f:id:takoeight0821:20210110170913p:plain
だいぶ減った

で、かなり容量に余裕ができた。 どうもこの画面は起動直後は数値がかなり大きめに出るようで、最初いきなり40GB減ったのはそれが原因だと思う。 まぁ、とりあえずこれで良しとしよう。しかし総容量が371GBというのも心許ない。Bootcamp消そうかな…

残り40GBは流石にまずい一日目

流石にまずいので、この三連休でどうにかします。目標は100GBの削減。

現状

現状。酷い。
現状。酷い。

関心があるのは一番上のMacintosh HD。その内訳は左から順に以下の通り。

  • 書類:91.36GB
  • App:39.39GB
  • iOSファイル:21.12GB
  • ミュージック:6.52GB
  • デベロッパ:5.59GB
  • 写真:2.59GB
  • 音楽制作:2.41GB
  • システム:15.05GB
  • その他:143.32GB

一番はその他、二番が書類、三番がAppといった感じ。

これは大変だぞ…と思いながら書いていたら、いつの間にかこうなってた。

なんか減ってた
なんか減ってた

目を離したすきに  89.03 - 40.3 = 49 でなんと49GBも減っていた! このまま減ってくれないかとしばらく眺めていたが、そんなことはなさそうなので、残り51GBがんばります。

現状をもう一度まとめておくと、以下の通り。

  • 書類:93.7GB
  • App:39.39GB
  • iOSファイル:21.12GB
  • ミュージック:6.52GB
  • デベロッパ:5.59GB
  • 写真:2.59GB
  • 音楽制作:2.41GB
  • システム:15.05GB
  • その他:94.71GB

その他ってなに?

で、その他って具体的にどのファイルたちのことなんだろう。 他はだいたい見当がつく。こんなところだろう。

  • 書類:~(ホームディレクトリ)以下にある、Apple製のアプリケーションが関与していないファイル
  • App:/Applicationsや~/Applicationsに入っている〇〇.app
  • iOSファイル:iPhoneのバックアップ
  • ミュージック:「ミュージック」に入っている音楽。昔はiTunesとか言ってたあれ
  • デベロッパXcodeが使う色々なファイル(エミュレータとか)
  • 写真:iCloudにあげられた写真
  • 音楽制作:GarageBandの使う素材ファイルあたりだろう
  • システム:多分OS本体やそれに類する各種ファイル。下手に触らない方がいい

つまり、その他は上記のファイル「以外」の全て、ということか…

App

まず、Appから手を付ける。いらないアプリが残ってたりしないだろうか。

  • Adobe Acrobat Reader DC.app
    • プレビュー.appで片付く。どうしても必要な時にインストールすればいいだろう。
  • Chrome Remote Desktop Host Uninstaller.app
    • Chrome Remote Desktop一度も使ったことないしとりあえずアンインストールしておこう。
    • 合わせて ~/Applications にあるChrome関連のアプリも調べてみないと
  • cluster.app
    • 頻繁にclusterを利用するわけではないしこれも必要な時で良さそう。
  • FTBApp.app
    • たまにMinecraftのmodpackで遊ぶので残しておこう…と思ったら起動しない。
    • FTBはめちゃくちゃいろんなものをダウンロードするので、メンテが必要そう。
    • とりあえずアプデ。
  • Gobot.app
    • 前ちょっと遊んだけど、それっきりなのでとりあえずアンインストール。
    • ゲーム作りたいな。というかゲームエンジン作りたい。
  • IntelliJ IDEA.app
    • たまに使う。要メンテ。
  • Kindle.app
  • Logisim.app
    • ちょっと前に必要で使ったけど、もう不要なのでアンインストール。
  • mtgaprotracker.app
    • 他のツールに乗り換えたので不要
  • PS Remote Play.app
    • 以前使う必要があったのでインストールしたが、もう不要。
  • The Unarchiver.app
    • なんで入ってるんだ?

ここまでで、要らなさそうなアプリがいくつか見つかった。 明日はまずこれらのアプリを削除したりアップデートしたりする。

半月文章を書き続けた。

11月3日の夜、昔のことを思い出した。 小学校の頃、僕はスポーツ少年団の合宿に参加した。 スポーツをやってたわけではなかった。 空手の師範代だったじいちゃんがその地域のスポーツ少年団に関わってて、 その伝手で参加することになった。

正直なところ全然乗り気じゃなかったし、楽しくもなかった。 でも、友達ができたのは覚えている。もう顔も声も名前も忘れてしまったけど。 どこか白い雰囲気を纏った子だった。

その思い出を文章にした。

この文章を皮切りに、iOSのメモ帳に書いた文章を毎日公開し続けた。 毎日書くのはそんなに大変じゃなかった。 僕のPCにはたくさんの書き散らかされた文章のデータがあり、 それらをサルベージしてスクショ一枚に収まるように整形してやるだけだった。 もちろん書き下ろしもいくつかある。

書いた文章を読んでみると、なんとなく書き手の趣味がわかってくる。 思い出の忘却への恐怖とか、ポストヒューマンとしての人工知能とか、そういうのが好きなんだなってなる。 表現や思想の自由にもうるさいのかも。でも活動家ってわけじゃなさそうだ。

流石にネタが尽きたので、ここ数日は更新頻度が落ちている。 文章を書くのは楽しいので、これからもすこしずつ続けていきたい。

twitter.com

2020年の9月にようやくスターウォーズを観た

スターウォーズは言わずとしれた名作スペースオペラである。「遠い昔 はるかかなたの銀河系」というフレーズを至るところで聞いた。適当な棒を構えてライトセーバーごっこに興じたこともある。C-3POR2-D2がすべてのエピソードに登場していることも知っている。チューバッカもハン・ソロも見たことがある。ダース・ベイダーのあのテーマもやたらいろんなところで流れているし、"I'm your father."なことも知っている。

でも、スターウォーズを観たことがなかった。

2020年9月、21才の後半戦に至り、初めてスターウォーズを観た。451236の順で観た。 はちゃめちゃに面白かった。こんなに面白い作品があっていいのかと疑うぐらい面白かった。 宇宙を駆けるミレニアム・ファルコンの勇敢さにおののいた。 ブラスターを素早く抜くハン・ソロの手腕に見惚れた。 イマイチぱっとしないルーク少年が強靭な意思を持つ青年へと成長し、ついに父の心を強く打ったことにいたく感動した。

今まで一度もスターウォーズを観たことがなかった。本編の映像の断片すら観たことがなかった。 スターウォーズが世界で最も成功した映画シリーズの一つであることは知っていた。 でも、スターウォーズを観たことがなかった。 R2-D2を模したキャンディーディスペンサーを持っていた。 でも、スターウォーズを観たことがなかった。 ミレニアム・ファルコンのレゴが欲しかった。 でも、スターウォーズを観たことがなかった。

2020年9月、ようやくスターウォーズを観た。ついに観た。451236の順で観た。 SNSで見かけた順番だ。ハン・ソロがセンスの悪いインテリアにされたまま三本引っ張るのも悪くなかった。 パドメとレイアの関係に驚いた。 すれ違っていくオビ=ワンとアナキンに心を痛めた。 ヨーダが抱える後悔を感じ取った。 まだ789は観ていない。近いうちに観ることになるだろう。

2020年9月にようやくスターウォーズを観た。今まで観ていなかったことに驚いた。 父がスターウォーズ世代であることを知った。 『ホワット・イフ?』の表紙に描かれた怪しい大穴がサルラックであることを知った。 ルーカスの宇宙では音がなることを知った。 Wookieepediaの情報量が本当に常軌を逸していることを知った。 結局のところ、アナキン・スカイウォーカーはいいやつで、ルーク・スカイウォーカーは肝の据わったやつだと知った。

スターウォーズは、本当の本当に面白い映画だ。 2020年の9月に僕は初めてそのことを知った。

死にゆく星空に百合は咲く 『アステリズムに花束を』を読みました

『アステリズムに花束を 百合SFアンソロジー』は、「百合」と「SF」の2つのテーマを掲げて編まれた短編集だ。 もともとは伊藤計劃の『ハーモニー』10周年を記念して企画されたSFマガジンの百合特集がかつてないほどの反響を呼んだことがきっかけらしい。積ん読の山に目を向けると文庫版の『ハーモニー』がこちらを見ている。気が向いたら読みます。

さて、近年「百合」と呼ばれるジャンルが急成長している。あまりにも急成長したがために百合好きを公言する人々の間でも「百合とはなにか」のコンセンサスが取れておらず、安易に百合語りをすると棍棒やら鉈やらが飛んできて五体をバラバラに解体されカラスの餌にされる始末である。私も2回ほど鳥葬の憂き目にあったことがある。 実は「SF」も似たような状況だと聞くと驚く人もいるだろうか。やれSci-Fiスペースオペラだ空想科学だ1000冊読まないとダメだとか、挙句の果てにはSukoshi Fushigiだとか言い出して光線銃だの荷電粒子砲だのを持ち出してどんちゃん騒ぎが始まる様を見たのは一度や二度ではない。私も2回ほど太陽葬の憂き目にあったことがある。

そういうわけで百合とSFは存外相性が良く、そのことが商業レベルで証明されたのは両ジャンルを好むものの端くれとして喜ばしい限りである。じゃあ「百合SFとはなにか」という話をしたくなるわけで……これは最後にしよう。殺されるから。

『アステリズムに花束を』最初の一編のタイトルは『キミノスケープ』。ある日突然「あなた」以外の人間が忽然と姿を消した世界で、「あなた」は自分以外の誰かと巡り合うために旅を続けている。こんなあらすじの作品を「百合SFアンソロジー」の頭に持ってくるセンスはかなりキテると思われるかもしれない。なんといったって百合なのに登場人物がたった一人なのだ。百合とSFの定義の曖昧さをあらゆる角度から逆手に取っている。

次の作品は『四十九日恋文』。死者と四十九日の間だけメールができる、というお話だ。メールの文字数制限は49文字から始まり、毎日1文字ずつ減っていく。最後の日には一文字しか送れない、と。なんとも切ない世界観だ。 恋人を喪った女性がその心の内を少しずつ語りながら、死んだ恋人と短い文通をする。日に日に短くなっていく恋文はついにたった2文字になり、最後の一日が訪れる。 死んでしまった恋人に送る最後のメールのたった一文字、遺してしまった恋人に送る最後のたった一文字の言葉。書店で立ち読みした私は膝を打ちこの本をレジへ持っていった。

次は漫画『ピロウトーク』。前世でお気に入りの枕を無くしたという先輩とその後輩が枕を探してあちこちを旅する。先輩は「枕」は自分の魂の欠落をぴったり埋めるような恋人で、何度宇宙を巡ってもどんな姿に生まれ変わってもひと目見れば同じ存在だとわかるものだと語る。二人の"ピロウトーク"は意外な結末を迎え……。 奇妙な協力関係と微妙な気持ちのすれ違いは百合、という認識が自分の中にあるのはなぜだろうか。『裏世界ピクニック』がそんな作品だと聞いたことがあるが、まだ仮想積ん読に埋もれている。以前にもこんな作品を読んだのは間違いないが、思い出せない。もしかしたら前の宇宙で読んだのかもしれない。

次は『幽世知能』。あらゆる物理系は情報処理能力を持ったコンピュータだと言える。ならば現し世に物の怪や神隠しをもたらす幽世も宇宙である以上は物理系であり、幽世はコンピュータとして使うことができる。そういう理屈で幽世を利用したコンピュータ、幽世知能が創られた。正直こんな設定からどうやって百合に持ってくのかさっぱりわからないが、どういうわけか話はおどろおどろしい雰囲気をたたえながら情報理論や宇宙物理学を骨組みとして「相互理解」へ向かっていく。 摩訶不思議な架空のSFガジェットが物語を通して読者にも理解可能なものになり、それが物語を動かす大仕掛けになる。そんなSFの魅力の一つが遺憾なく発揮された作品だ。

次は『彼岸花』。いよいよ作品のあらすじをまとめることが不可能になってきたが、これはかなり変わったアフターシンギュラリティもの(?)だ。おそらく人造と思われる吸血鬼のような新人類「死妖」によって人類は置き換えられ、旧人類最後の一人となった舞弓青子は、死妖らから「姫様」と呼ばれる少女の計らいでその妹として生きることになる。マリみて的女学園の疑似姉妹の交換日記という形式で綴られる本作はもしかすると正統派の「百合SF」なのかもしれない。ところでみんな猫屋と鷹匠のこと好きだと思うんですけど、どう?

次は『月と怪物』。架空のソ連を舞台に、超能力開発のために拉致された姉妹の数奇な人生を描く。この作品はかなりストレートに同性愛を描いているが、私がそのことに気づいたのはラスト数ページのところだった。慌てて読み返すとなるほどうまくできている。超能力開発に絡めて共感覚が一つのSF的テーマとして語られるが、これも「ソ連といえば赤」の連想を思い起こさせる。ソ連といえば宇宙開発も外せない要素だ。これがタイトルの「月」に関わってくるのだが、そのシーンの詩的な美しさは堪らない。

『海の双翼』、これはもう読んでもらうしかその雰囲気を伝える方法がないのだが、個人的にはこういう「百合」が一番好きだ。この作品が「百合」かどうかはおそらくこのアンソロジーの中で最も意見が分かれるところだが、興味深いことに物語そのものがその問に一つの答えを提示している。SFのギミックも言語と情報が軸になっていてこれまた好物だ。常々人とコンピュータをつなぐインターフェイスに興味を持っているので、SF的インターフェイスを主要なギミックにしている作品を読むとあれこれと空想が止まらなくなる。

次は『色のない緑』。この作品は偶然時事ネタの塊になってしまった。2052年4月にインフルエンザが大流行し、人々は接触を恐れ可能な限り外出を控えるようになり、商業施設は軒並み廃墟と化した、という背景設定はわれわれの世界の2020年に興味深いほど合致している。人工知能技術の発達により小説は人工知能が書くのが当たり前になり、主人公は人工知能が書いた小説を「脚色」することを職業としている。これもまた今日のAIブームが人工知能による創作物の生成を当たり前のものにしたことを思わせる。物語の中で、主人公の友人は人工知能の不完全性を証明するが、その論文は論文の正当性を評価する人工知能によってリジェクトされ、彼女は液状記憶装置の中身を飲んで自殺する。これもいかにも現実に起きそうな話だ、というのは悲観的すぎるだろうか。

最後は『ツインスター・サイクロン・ランナウェイ』。ガス惑星の周囲を回るコロニーに暮らす二人の主人公は、氏族社会にゆるやかな反抗を示し、男女の夫婦でしか許されない"漁"へ出る。「百合SF」と真っ向勝負をしている本作だが、私はそんなことより乗り手の思考により形を変える船の方に魅力を感じた。ブレインヒューマンインターフェイスを持ち、必要に応じて柔軟に形と機能を変えることができる宇宙船はロマンの塊だ。あれ欲しい。絶対そんな船に乗って合理的だけど無茶苦茶な船にしたい。それを操縦できる人がいるかどうかは別にして。

そういうわけで、買ったのが去年の7月末だから、読み終わるまでにだいたい9ヶ月かかったことになる。この9ヶ月で世界は大きく変わった。「百合」は未だにあちこちで議論を巻き起こしつつも、女性同士の関係性を描くジャンルとして一定の共通認識を得、「SF」は不況を乗り越え『三体』は空前の大ヒット、『ツインスター・サイクロン・ランナウェイ』は長編化、『なめらかな世界と、その敵』も各地で話題沸騰。 そして現実のSF化もとどまることを知らない。新たなウィルス性の感染症グローバル化を達成した人類文明を焼き尽くさんがばかりに蔓延し、人々は接触を恐れ可能な限り外出を控えるようになり、保守的な人々もIT化を余儀なくされた。学校も仕事も今はすべてオンラインだ。良くも悪くも、今回の件は世界を変えるだろう。

すでに多くの人が指摘しているが、他者との接触、他人との関係がどれほど尊いものだったか、我々はそれを失いかけたことで強く自覚することになった。わずかな間に社会規範は大きく変わり、ハグや握手は親愛を示すための推奨される行為ではなくなった。明日は何が変わるだろうか。人はこの苦難を乗り越えることができるのだろうか。不安は多いが、希望もある。少なくともわたしたちは、こういった状況をすでに物語を通して学んでいる。

「百合SF」とはなんだろうか。そんな問いはナンセンスかもしれないが、私は今の現実を語るための非日常的な道具立てではないかと思う。女性同士の同性愛も魔法のような科学技術も現実に大量に存在する概念だ。しかし、それらは未だ非現実的な響きを持っている。そういう微妙なものを描くと、現実のうまい比喩になるのではないだろうか。喩え話はいつだって現実に立ち向かう助けになる。

確かにヒトはいつか死ぬ。だけど、生まれて死ぬまでのわずかな時間で、ヒトとヒトの関わりは美しく輝く。星のない宇宙を、ヒトの住む小さな土塊は明るく照らすだろう。どこまでも、いつまでも。