隠居日録

隠居日録

2016年(世にいう平成28年)、発作的に会社を辞め、隠居生活に入る。日々を読書と散歩に費やす

Ank: a mirroring ape

佐藤究氏のAnk: a mirroring apeを読んだ。本作は470ページを超える大作だ。

昔何かの本で、日本語のサルに相当する英語は二つある。一つはmonkeyで、もう一つはapeである。その使い分けは、尻尾があるのがmonkeyで、尻尾がないのがapeであるというのを読んだ記憶がある。今までなんとなくこの通りに覚えていて、深く考えていなかったが、この説明は正確ではないということを本書を読んで気づいた。というのも、apeの日本語は正確には類人猿でサルではないのだ。普段我々は類人猿も含めてなんとなくサルと呼称しているが、類人猿と猿にはいろいろな違いがある。そのうちの一つが鏡像認知(鏡に映っている自分自身を認識できる能力)であり、本書のタイトルにもmirroringという言葉によって表されている。本書の主人公は霊長類研究者の鈴木望であるが、もう一人の主人公はAnkと名付けられたチンパンジーだ。

世界的なIT企業ムカクのCEOであるダニエル・キュイが京都に設立したKMWPセンターが発端となり起きた京都騒乱事件を時間軸を行きつ戻りつしながら描いているSF小説で、前作のミステリーとは全く作風が異なっている。鈴木望ミラーリング・エイプという論文がダニエル・キュイの目に留まり、そのKMWPの所長に就任した若き研究者である。KMWPセンターは「AIは本来の言語を持たない」という課題を解決するために、言語とは何かを探るためにダニエル・キュイが設立したのだが、KMWPセンターでは表向きの研究テーマとは別のテーマが研究されていた。そこに南スーダンで密猟者から保護されたチンパンジーが移送されてきたことにより、京都騒乱事件が発生してしまったのだ。

本当のタイトルにmirroringとあるように、この物語では「鏡」がキーワードになっていて、直接的に間接的に鏡が登場する。それは鏡像認知であったり、実際の鏡であったり、鏡文字であったり、論文であったり。この鏡を起点にして京都騒乱事件の原因につなげていったのはなかなか面白かった。前作のQJKJQでも結構グロテスクな表現があったが、今回もそのような表現がかなりあった。ただ、人間の悪意は描写されていないので、読んでいてあまり心理的な抵抗は感じなかった。

Firefox Quantumとgreasemonkeyとlibron

PCを再起動したら(あの日はWindows updateの日だったので)firefox 57 (Quantum)に更新され、そしたらaddonが動かなくなったりして、困ってしまっているのだが、なんとなく以前のように使えるようになってきた。ただ、greasemonkeyも4に更新しなければならず、4は以前の物に対して後方互換がなくなってしまったので、スクリプトを更新しなければならない場合もある。そのうちの一つがlibronなのだが、公式からはまだ新しいスクリプトが公開されていないので、自力で何とかするしかない。

問題なのは、GM_で始まる関数群がGM.に置き換えられたことで、単なる名前の変更だけなら、どうということはないのだが、GM.getValueが非同期で呼び出さなければならないようで、これを書いている時点でもまだ正しく理解しているとはいいがたい状態であるが、動作させるのにずいぶん苦労した。公式のwikiによると、

// ==UserScript==
// @name     GM set/get demo
// @grant    GM.getValue
// @grant    GM.setValue
// ==/UserScript==

(async function() {
console.log('Starting the get/set demo ...');
let i = await GM.getValue('i', 0);
console.log(`This time, i was ${i}.`);
GM.setValue('i', i+1);
})();

と書けば、直接値が戻ってくるようになると書かれている。それで以下のような関数を定義して(複数の値を読みだすと遅くなるということなので、JSON形式で設定を保存するようにした)、mainから呼び出して、保存している設定を読みだそうとしたのだが、値が読み出せないのだ。

async function readLibronConfig() {
  var options = JSON.parse (await GM.getValue('libron', "{}"));
 
  libron.selectedSystemId = options.systemid ? options.systemid : 'Tokyo_Pref';
  libron.selectedSystemName = options.systemname ? options.systemname : '東京都立図書館';
  libron.selectedPrefecture = options.prefecture ? options.prefecture : '東京都';
  libron.univChecked = (options.univChecked == true) ? true : false;
}

この関数の中で値を調べると呼び出せているようなのだが、その値が呼び出したmainでは参照できない。全ての設定がundefinedのままだ。いろいろ動作を調べてみて、ようやく気付いたのだが、aync ~ awaitによって、この処理は呼び出した側では即時完了してしまい、その時点で値は読みだせていない。そして、呼び出された側では、非同期にこの処理の動作を継続していて、値が読みだされた後に、その後の処理が継続しているようなのだ。なので、実際のmainの処理は値が読み出せた後に、実行しなければならない。結局、mainの呼び出しの所を、以下の様にして、設定を読みだした後に、mainを実行するように修正した。

if (isGreasemonkey()) {
  readLibronConfig ().then (() => main ());
} else {
  function onReadyGM(){
    main();
  }
}

長いので、パッチの全体以下の続きを読むから。

続きを読む