ハンナ・アーレント『全体主義の起源』第三巻「全体主義」(大久保和郎, 大島かおり訳, 訳書2017年)

全体主義の運動・統治に関する論考の最後の分冊。1巻は「反ユダヤ主義」、2巻は「帝国主義」とそれぞれ題されているが、いずれも未読。3巻だけでもかなりたいへんな読書です。

全体主義の具体例として、本書はスターリン時代のソ連ナチス・ドイツを取り上げている。というよりも、これまでに類例のないふたつの体制が、しかしながら相似た形で現れたことについて論考するにあたり、ちょうどよいカテゴリが「全体主義」だった、という感じだと思う。

だいたい次のことが書かれているものと理解したけど、だいぶ粗雑なチェリーピッキングになっているはず。また、アーレント独自の用語法についても捉えきれていないはず。

暴政と全体主義の区別

暴政 *1 においては、被支配者から暴君がその不法な恣意により、恐怖を駆動力として統治を行う。恐怖によって人々は、政治的・公的生活から引きこもらされるが、私的生活までは侵犯されない。 (pp. 314-317)

一方全体主義において、指導者は運動を構成する大衆を代表しており (pp. 43-44) 、その意志は常に正しく、法である。その統治は、生活のすべての局面に浸透するテロルによって駆動される。テロルが最高の形で現れる場である収容所では、人間は政治的・公的生活に加えて私的な生活も剥奪され、差異のない単一の存在となり、最後に消される。

なお、全体主義において、常に正しいとされるのは指導者の「意志」であって、その発言や命令ではない。指導者は外部世界、あるいは運動の周縁に対して平然と嘘をつく。運動の精鋭は、それが嘘であることを知っており、意志がどこにあるかを理解する能力を持っている。 (pp. 139-141)

イデオロギーの役割

全体主義は、それが採用するイデオロギーに新しいものをなに一つ付け加えはしない。一方、不条理で、現実離れしているかのように見えるイデオロギーの世界観を、その組織の中でマジで実現する。虫けらであると宣言されたユダヤ人は虫けらのように殺されたのだし、その後にはポーランド人、いずれはドイツ人もが続くはずだった。現実化されたイデオロギーは、途方もない説得力を発揮する。 (p. 102-104, pp. 302-304)

一方で外部世界は、イデオロギーを単なるお題目とみなして、外交的な嘘(民主主義陣営との共闘であるとか)を現実的な本音とみなした。

論点

次の諸点については折に触れて考えることになると思う。

*1:p. 295の訳注によれば、モンテスキューの区分法における「専制政体」を、アーレントは「暴政」と記述している。

ハンナ・アーレント『エルサレムのアイヒマン: 悪の陳腐さについての報告』(大久保和郎訳, 訳書2017年)

アイヒマン裁判の報告。アードルフ・アイヒマンナチス親衛隊 (SS) でユダヤ人の移送にあたった。潜伏先のアルゼンチンで拉致され、エルサレムで裁判を受けて死刑判決、同年刑死した。

ここでは、副題の「悪の陳腐さ」について点検する。

巨大な犯罪をなした人間が個人として取るに足らない人間であることは、改めて驚きとするところではない。私たちは、官吏的人物の典型であった東條を知っている。凡庸な君主であった裕仁を知っている。麾下の軍隊を統制する意志と能力を欠いており、したがって虐殺について未必の故意が認められるに過ぎない松井を知っている。

本書がこの副題のもとに述べていることは、ナチが一民族の絶滅という類のない犯罪を公式の政策としたこと、アイヒマンがそれをはっきりと理解して、その主要な一部である職務にあたったこと、にもかかわらず彼自身は凡庸で、正常であった、ということである。アーレントはその凡庸さを報告することで、「類のない巨大な犯罪を行った者は、類のない怪物的な人物に違いない」という決めつけに反駁したのであって、悪が陳腐であったこと自体から、それ以上の何かを引き出そうとはしていない。

本書の大部分は裁判報告だが、その構成は通常の裁判報告と異なる。つまり、まず事件の叙述があって、ついで訴訟、という構成は取っていない。裁かれた犯罪行為が地理的にも時間的にも大規模であることから、そのような構成は不可能だっただろう。本書は、SS官吏としてのアイヒマンの行動をほぼ経時的に記述する中で、法廷での審議についても織り交ぜて述べている。

最後の章である「エピローグ」は、犯罪としてのホロコースト、法廷、個人の罪などについて議論している。

なお、本書が何を書き、何を書かなかったかについては、巻末の「追記」、および『責任と判断』所収の「独裁体制のもとでの個人の責任」で、著者自身が整理している。

オルハン・パムク『雪』(宮下遼訳)

「吹雪の山荘」ものの政治群像劇。「西欧」や「イスラム」や「神」や「世俗主義」や「失業」や「かつて社会主義だったもの」などの諸観念を、登場人物たちが言葉や実弾として投げつけ合う話です。読みでがあって面白い。

雪〔新訳版〕 (上) (ハヤカワepi文庫)

雪〔新訳版〕 (上) (ハヤカワepi文庫)

雪〔新訳版〕 (下) (ハヤカワepi文庫)

雪〔新訳版〕 (下) (ハヤカワepi文庫)

日本人の読者である自分には、「トルコ的なるもの」と、「イスタンブール」が表象するものの対立が印象的でした。トルコ的なるものに対立するイスタンブール = 自分だけは西欧の自由主義をものにしたつもりで、田舎者を馬鹿にしたり、状況次第でイスラム主義に同情を示したりしながら、その実は軍隊の汚れ仕事に寄りかかっているいけすかないインテリ、という感じ。一昨年に見た映画『裸足の季節』では、田舎から逃げ出す少女が目指したイスタンブールが、比較的ストレートに美化されていたのですが、こういった対立関係を念頭に見ると、また見え方が違うのかも、と思います。

会話文がステレオタイプ的に訳されていることが少し気になります。特に女性の発言に顕著です。

夏時間導入における電算システムの対応

夏時間が導入された場合、電算システムにおいて必要となる対応をまとめます。なお、「夏時間に対応しない」としても、改修が不要とは限りません。

なお、本稿はUnix系およびWindowsのみを取り上げます。汎用機における夏時間の扱いについては、知見がないため取り上げません。

背景1: 電算システムにおける時刻の一般的な取り扱い

まずは、コンピュータがどのように時刻を扱うか、簡単におさらいします。

コンピュータが「現在時刻」を得るには、 1. システムクロック、 2. タイムゾーンデータベース 3. タイムゾーン設定 の3つのリソースを用います。

システムクロック: OSは、UTC(いわゆるグリニッジ標準時)の1970年1月1日0時ちょうどから、現在までに経過した秒数を、システムクロックとして提供します。うるう秒を無視すれば *1 、システムクロックを用いて、UTCの現在日付・現在時刻が算出できます。

タイムゾーンデータベース: 我々がふだん使っている時刻系(地方時)は、一般にUTCからずれています。たとえば、2018年8月のカリフォルニアでは、UTCから7時間遅れた地方時が用いられ、11月上旬以降は、UTCから8時間遅れた地方時が用いられます。一方、2018年時点の日本では、一年を通してUTCから9時間進んだ地方時が用いられます。ある地域で用いられる地方時は、法令の改廃や領土の割譲によっても変わります。このように、ある地域で適用される地方時の履歴をまとめたデータベースがタイムゾーンデータベースです。一般的に用いられるタイムゾーンデータベースは、ICANNが管理するtz database (tzdata) です。

タイムゾーン設定: システムクロックとタイムゾーンデータベースを用いて「現在時刻」を得るためには、「どの地域における時刻を得るか」の情報が必要です。「どの地域」を表すのがタイムゾーン識別子です。たとえば日本の地方時を用いる場合には、タイムゾーン識別子として「Asia/Tokyo」を指定します。Windowsでは、これを「日付と時刻」の画面から設定します。

背景2: タイムゾーンの取り扱いの諸相

同一のコンピュータの中でも、プログラムによって、異なるタイムゾーンデータベースやタイムゾーン設定が使われる場合があります。また、タイムゾーンデータベースを用いず、UTCからのズレをプログラム内でハードコードしている場合もあります。このような場合は、得られる「現在時刻」がプログラムごとに異なることになります。

OS提供のAPI: Windows APIのGetLocalTime関数、あるいは標準Cライブラリのlocaltime関数を使うと、OSが管理するタイムゾーンデータベース・OSのタイムゾーン設定を使った地方時が得られます。ふだんデスクトップで目にする時刻は、OS提供のAPIを用いている場合が多いでしょう。

Java: Oracle JDK / OpenJDKでは、OSが管理するタイムゾーンデータベースとは別に、独自のタイムゾーンデータベースを用います。このデータベースはtzupdaterツールで更新されます。また、ZoneIdオブジェクトを指定することで、OSのタイムゾーン設定とは独立に、任意のタイムゾーンにおける地方時が扱えます。たとえば、America/Los_Angelsタイムゾーンで運用されているシステム上のJavaアプリケーションで、Asia/Tokyoの地方時が扱えます。

Python: datetime.now関数は、無引数で呼び出すと、OSが提供する地方時における現在時刻を得ます。一方、タイムゾーンオブジェクトを引数に指定することで、任意のタイムゾーンにおける時刻が得られます。このタイムゾーンオブジェクトは標準で提供されていないため、プログラム内で定義するか、あるいはpytzライブラリから取得する必要があります。pytzライブラリを用いる場合、その更新はpipやsetuptoolsなどのパッケージマネージャによって行われます。

固定のUTCオフセット: 日本では長年、UTCから9時間進んだ地方時のみが用いられています。このため、UTCと地方時との相互変換において、9時間進める処理、9時間遅らせる処理が、プログラム内にハードコードされていることがしばしばです。

上記の組み合わせ: システム内、あるいはプログラム内で、上記の組み合わせが用いられている場合があります。たとえば、ブラウザのJavaScriptでOS提供の地方時が用いられて、サーバ側のJavaプログラムではJavaタイムゾーンデータベースが用いられる場合。あるいは、OS提供のlocaltime関数を用いているにもかかわらず、プログラムの一部分が、UTCとのズレが9時間であることを仮定した処理を行っている場合などです。

以降は、夏時間が導入された時に顕在化する可能性があるシステム上の課題について、例示的に述べます。

課題1: 存在しない時刻への対応

冬時間から夏時間に移行する時には、地方時において存在しない時刻が発生します。たとえば、冬時間の午前2時から夏時間の午前4時に移行する時、その日は2時台と3時台の時刻がまるまる存在しないことになります。

地方時の2時半に起動される日次処理があるとします。夏時間への移行日には、2時半という時刻が存在しないため、この処理がいつ実行されるべきか、そもそも実行されるべきか、検討する必要があります。仮に夏時間の4時ちょうどに起動したい場合、スケジューラがそのような設定に対応しているか調査する必要があります。

例として、cronieパッケージのcronコマンドは、夏時間への移行の際に日次処理の実行タイミングがスキップされた場合は、移行直後にジョブが実行されます。

課題2: 重複する時刻への対応

夏時間から冬時間に移動する時には、地方時において同じ表記の時刻が2度発生します。たとえば、夏時間の午前4時から冬時間の午前2時に移行する時、2時台の時刻と3時台の時刻は2回ずつ発生します。

時刻をユーザに入力させるようなシステムでは、これが問題となります。たとえば労務管理システムにおいて、勤務開始時刻が2時半と入力されたとき、これが夏時間の2時半か、冬時間の2時半かを、なんらかの方法で知る必要があります。

システムがログファイルを出力する時、ログ行の書式によっては、出力されたログがいつ時点のものか、一意に特定できなくなる可能性があります。たとえば「2019-10-27T02:30:00 INFO ...」のようなログ行は、この日が冬時間への移行日にあたる場合、夏時間・冬時間どちらの時刻のものか判別できません。このような場合、たとえば「2019-10-27T02:30:00+09:00 INFO ...」のようにUTCからのズレを出力したり、UTCでの時刻表記に変更したりするなどの対応が必要となるでしょう。

また日次処理の起動についても検討が必要です。毎日2時半にスケジュールされる日次処理について、それが夏時間の2時半と冬時間の2時半の二回実行されるべきか、どちらか一度だけであるべきか、といったことです。

課題3: 時刻表記の逆行

夏時間から冬時間への移行の際、時刻表記が巻き戻ることが問題を生む可能性があります。

たとえば、地方時の時刻表記を出力するファイル名の先頭に付しており、ファイル名のソートによって時刻順の並び替えが可能であると仮定している場合などです。

課題4: 1日の長さが22時間〜26時間で変動する

1日の長さが24時間であることを仮定しているシステムは、問題を生む可能性があります。

たとえば、1日のリクエスト数を24で割ることで1時間あたりのリクエスト数を算出している場合、夏時間への移行・冬時間への移行の際は、計算結果が不正になります。

同様の問題は、本質的にはうるう秒挿入の際も起こり得ます。しかしながら、うるう秒挿入の際の変動がたかだか1秒であるのに対して、夏時間・冬時間への移行は、変動幅が大きいため、問題が顕在化しやすくなります。

課題5: 夜間の長さが変動する

午後6時から午前6時までの時間は、通常12時間であるのに対して、夏時間移行の際は10時間、冬時間移行の際は14時間に変動します。

これによって、たとえば夏時間移行の際に、朝までに終わっているべき夜間処理が完了しない、といった問題が起きる可能性があります。

また、労務管理システムにおける勤務時間やインターバル時間の算出においても、改修が必要になるかもしれません。

課題6: システム間・システム内の時刻の不整合

上述したとおり、システムを構成するプログラムや、プログラム内の部分ごとにタイムゾーンの扱いが異なる場合には、不整合が発生し得ます。

課題7: 「夏時間に対応しない」ための対応

あるシステムが「夏時間に対応しない」ことを決めた場合、つまり「UTC+9時間の固定オフセットで運用する」ことを決めた場合には、タイムゾーンデータベースに依存しないようにプログラムを改修したり、タイムゾーンデータベースをアップデートしないように設定を変更したりする必要があります。

またこのシステムが、他システムと連携している場合には、システム間でほぼ確実に時刻の不整合が発生することも認識する必要があります。たとえば、ユーザがブラウザを通じてシステムに対して処理を行う場合、システムの扱う時刻とJavaScriptのDateオブジェクトの時刻にはズレが生じます。また、ログ解析を共通の基盤として運用している場合、「夏時間に対応しない」システムのログ出力の取り扱いには注意が必要でしょう。

*1:2018年時点で、システムクロックからUTCへの変換は、うるう秒がないものとみなす場合が大半です。しかしながら、アメリカやEUにおける調達基準の見直しによって、この状況は変わるかもしれません。参考: https://www.theregister.co.uk/2018/07/19/windows_leap_second/

代数的データ型のシミュレーション

タスクの完了状態として、 1. 正常に値を戻した場合 2. 例外を投げた場合 3. まだ完了していない場合 の3種類があるとします。Haskellであれば代数的データ型、OCamlであればvariant型で表すところです。Javaは、このような型を言語としては表せませんが、Visitorパターンとその変種によってシミュレーションできます。

ふつうのVisitorパターン

最初のやり方はふつうのVisitorパターンです。「完了状態」をStatus抽象クラス、個々の状態の種類を具象クラスSuccess, Failure, Unfinishedとします。

interface Visitor<T, R> {
  R visit(Success<T> success);
  R visit(Failure<T> failure);
  R visit(Unfinished<T> unfinished);
}

abstract class Status<T> {
  abstract <R> R accept(Visitor<T, R> visitor);
}

class Success<T> extends Status<T> {
  private final T result;

  Success(T result) {
    this.result = result;
  }

  T getResult() {
    return this.result;
  }

  @Override <R> R accept(Visitor<T, R> visitor) {
    return visitor.visit(this);
  }
}

class Failure<T> extends Status<T> {
  private final Exception exception;

  Failure(Exception exception) {
    this.exception = exception;
  }

  Exception getException() {
    return this.exception;
  }

  @Override <R> R accept(Visitor<T, R> visitor) {
    return visitor.visit(this);
  }
}

class Unfinished<T> extends Status<T> {
  @Override <R> R accept(Visitor<T, R> visitor) {
    return visitor.visit(this);
  }
}

class Main {
  public static void main(String[] args) {
    handle(new Success<>(42)); // => OK: 42
    handle(new Failure<>(new Exception("boo"))); // => Ouch: java.lang.Exception: boo
    handle(new Unfinished<>()); // => Unfinished
  }

  private static void handle(Status<Integer> status) {
    String msg = status.accept(new Visitor<Integer, String>() {
      @Override public String visit(Success<Integer> success) {
        return "OK: " + success.getResult();
      }
      @Override public String visit(Failure<Integer> failure) {
        return "Ouch: " + failure.getException();
      }
      @Override public String visit(Unfinished<Integer> unfinished) {
        return "Unfinished";
      }
    });
    System.out.println(msg);
  }
}

Statusのインスタンスは、3種類のうちいずれかのvisitメソッドを呼び出すので、代数的データ型をシミュレーションしているものとみなせます。

この方法の利点は、よく知られているパターンであるために、オブジェクト指向プログラミングに通じている人であれば容易に理解できることです。難点は、見ての通り冗長なことです。

Visitorパターンから具象クラスを隠蔽

前項の例でSuccess, Failure, Unfinishedの各具象クラスは、単にvisitメソッドへの振り分けを行うための、タグのような役割を果たしているに過ぎません。タグの役割をメソッド名に追い出すことで、具象クラスを表出させないようにすることもできます。

interface Visitor<T, R> {
  R visitSuccess(T result);
  R visitFailure(Exception exception);
  R visitUnfinished();
}

abstract class Status<T> {
  abstract <R> R accept(Visitor<T, R> visitor);

  static <T> Status<T> success(T result) {
    return new Status<T>() {
      @Override <R> R accept(Visitor<T, R> visitor) {
        return visitor.visitSuccess(result);
      }
    };
  }

  static <T> Status<T> failure(Exception exception) {
    return new Status<T>() {
      @Override <R> R accept(Visitor<T, R> visitor) {
        return visitor.visitFailure(exception);
      }
    };
  }

  static <T> Status<T> unfinished() {
    return new Status<T>() {
      @Override <R> R accept(Visitor<T, R> visitor) {
        return visitor.visitUnfinished();
      }
    };
  }
}

class Main {
  public static void main(String[] args) {
    handle(Status.success(42)); // => OK: 42
    handle(Status.failure(new Exception("boo"))); // => Ouch: java.lang.Exception: boo
    handle(Status.unfinished()); // => Unfinished
  }

  private static void handle(Status<Integer> status) {
    String msg = status.accept(new Visitor<Integer, String>() {
      @Override public String visitSuccess(Integer result) {
        return "OK: " + result;
      }
      @Override public String visitFailure(Exception exception) {
        return "Ouch: " + exception;
      }
      @Override public String visitUnfinished() {
        return "Unfinished";
      }
    });
    System.out.println(msg);
  }
}

よく見る変種のわりには、名前がついていないのが気になります。「Visitor-AnonymousElementパターン」とか?

Visitorインタフェースを関数に分解

Visitorインタフェースは、3つの関数の三つ組として分解することも可能です。

import java.util.function.Function;
import java.util.function.Supplier;

abstract class Status<T> {
  abstract <R> R accept(
      Function<T, R> visitSuccess,
      Function<Exception, R> visitFailure,
      Supplier<R> visitUnfinished);

  static <T> Status<T> success(T result) {
    return new Status<T>() {
      @Override <R> R accept(
          Function<T, R> visitSuccess,
          Function<Exception, R> visitFailure,
          Supplier<R> visitUnfinished) {
        return visitSuccess.apply(result);
      }
    };
  }

  static <T> Status<T> failure(Exception exception) {
    return new Status<T>() {
      @Override <R> R accept(
          Function<T, R> visitSuccess,
          Function<Exception, R> visitFailure,
          Supplier<R> visitUnfinished) {
        return visitFailure.apply(exception);
      }
    };
  }

  static <T> Status<T> unfinished() {
    return new Status<T>() {
      @Override <R> R accept(
          Function<T, R> visitSuccess,
          Function<Exception, R> visitFailure,
          Supplier<R> visitUnfinished) {
        return visitUnfinished.get();
      }
    };
  }
}

class Main {
  public static void main(String[] args) {
    handle(Status.success(42)); // => OK: 42
    handle(Status.failure(new Exception("boo"))); // => Ouch: java.lang.Exception: boo
    handle(Status.unfinished()); // => Unfinished
  }

  private static void handle(Status<Integer> status) {
    String msg = status.accept(
        result -> "OK: " + result,
        exception -> "Ouch: " + exception,
        () -> "Unfinished");
    System.out.println(msg);
  }
}

acceptの呼び出しが簡潔になる反面、状態の名前が明示されないことが難点です。とはいえ、状態の種類が少数にとどまるのであれば、これで十分かもしれません。

ここまでくると、Visitorパターンの変種というよりも、代数的データ型をdesugarしたもの、という感じです。

土俵上の「女人禁制」の撤廃を求めます

本場所、巡業その他における土俵上の「女人禁制」の撤廃を求めます。それは性別についての差別だからです。

書きたいことは以上で終わりですが、愛想がないのでもうちょっと続けます。

4月4日の舞鶴巡業で、来賓の舞鶴市長があいさつ中に倒れました。この際、土俵上で救命措置をおこなった女性に対して、行司や年寄が土俵を降りるよう求めました。

さらには6日の宝塚巡業で、土俵に上がってあいさつすることを要求した宝塚市長の中川氏に対して、相撲協会は、氏が女性であることを理由に拒否しました。

いずれも明白な差別です。もちろん、これらの差別事件は何の脈絡もなくいきなり起きたのではなく、「女人禁制」自体の差別性がこの二日間に露呈した、ということです。

6日の中川発言については、舞鶴の事件に便乗し、政治的に利用したものであるとして、批判する声をいくつか目にしました。以下では、この点について論じたいと思います。

まず、中川氏自身が差別の当事者である、ということを認識する必要があります。現に差別を受けた人に対して、状況やタイミングがどうこうであるから声を上げることを慎め、と求めることは不当です。

また、中川氏は自治体の長であるという点で影響力の大きな政治的主体でもあります。今このタイミングで、氏がなにも声を上げないとしたら、消極的にであれ、「女人禁制」を支持することになります。あっちかこっちかであって、中立はあり得ません。この点をあいまいにせず、態度をはっきりと示した中川氏はえらいし、その要求、発言の内容も正当なものだと思います。

「なにも声を上げないとしたら、消極的にであれ、『女人禁制』を支持することにな」るということは、当然ながらファンである私自身にも跳ね返ってくることです。どうしましょう。五月場所で署名集めでもしようかしら。

相撲興行は、その時々の世間に阿って伝統をでっち上げたり *1 、弾圧を避けるためになかったことにしたりして *2 、300年間のらくらと人気を取ってきた文化です。「女人禁制」を撤廃することくらいはわけもないことで、それによって何が失われるわけでもありません。

*1:横綱の地位、土俵入りの所作などなど。

*2:行司の装束、あるいは「女人禁制」それ自体。

梁英聖『日本型ヘイトスピーチとは何か』(2016)

梁英聖『日本型ヘイトスピーチとは何か』(2016)を読了しました。タイトルは「ヘイトスピーチ」ですが、中身は現代日本におけるレイシズム全般を扱っています。自分の中でモヤモヤしてた部分について、きわめて明瞭に整理の方向付けをしてくれています。

日本型ヘイトスピーチとは何か: 社会を破壊するレイシズムの登場

日本型ヘイトスピーチとは何か: 社会を破壊するレイシズムの登場

モヤモヤしてた部分とは、次の二点です。

  • a. 世界的な右傾化の中で、日本では、alt-right的な跳ねっ返りではなく、既存保守勢力がそのまま極右にスライドしている。差別扇動という点で典型的には石原慎太郎門閥→極右という点で典型的には安倍晋三。こりゃなんだ?
  • b. 「ヘイトスピーチの法規制」について。これは原理的に表現の自由と衝突するし、橋下「日本人に対するヘイトスピーチ」、あるいは石破「デモはテロ」やトランプ「fake news」のように、用語の簒奪によって、反動に利用される危険がないか。確立された法や規範の上で戦う方が良いのではないか。

a. 日本における極右化の特徴的様態について

まずはaについて。

丸山眞男「日本ファシズムの思想と運動」は、1930年代〜の日本において、独伊とことなって、お歴々による国家主義が草の根のファシズムを最終的に圧倒した、ということを指摘しています。現在の極右化の様態についても、同じように考えられるのだろうと思いつつ、それではあまりに大雑把だし、そもそも丸山の立論もあまり明確ではない。モヤモヤ。

本書は、日本においてレイシズム自体を規定・禁止する法がなく、また規範も確立していないこと、また植民地出身者の諸権利および国籍を剥奪した上で、「入国管理のための1952年体制がそのまま外国人政策を代用する」(p. 128) 構造が続いていることを指摘しています。

また関連して、戦争責任・植民地支配責任がまともに総括されなかったため、歴史否定を批判する規範も成立していない (pp. 271-274)。そもそも真相究明自体が不足している(pp. 301-302)。

つまり、体制自体に差別が根ざしているので、alt-rightが出るまでもない、というのが主たる指摘です(p. 267)。

b. 「ヘイトスピーチの法規制」の是非について。

ついでbについて。

aの議論を踏まえると、ヘイトスピーチについて「確立された法や規範の上で戦う」ことは無理筋か、少なくとも不充分だ、ということは納得できました。在日コリアンの反差別運動は、原則から差別的な制度の中で、限定的な権利獲得闘争にとどまることを強いられています (pp. 127-128)。

また、「ヘイトスピーチ」という概念自体が、米国の特殊な文脈から発しており、注意が必要であることも指摘しています。いわく、米国では公民権運動の中で、差別行為を規制する一方、言論は差別的なものであっても擁護する法・規範が形成されました。これは、反差別運動の側からすると、武器としての言論がつぶされることを懸念したためです。「ヘイトスピーチ」は、この米国に固有の二分法に対する異議申し立ての中で提出された概念です(pp. 215-218)。

このような状況では、ヘイトスピーチ規制以前に、そもそも「人種差別撤廃条約の理念にもとづいた反レイシズム法を作らせることが重要」 (p. 289)。

まとめ

以上、自分の従来の関心にもとづいてまとめましたが、本書は個別の暴力の事例から、戦後民主主義の構造まで、広範な射程を貫徹した構成で論じる、きわめて意欲的な本です。最後の章は、著者が代表を務める反レイシズム情報センター(ARIC)での経験を元に、具体的にレイシズムをなくしていくための実践についての試論でしめられています。ジャンルによらず、魂のこもった本に出会うことはまれですが、この本はまさにそれです。

正直言って、読んでいる間は暗澹とした気持ちにならざるを得ないのですが、すべての人にとって必読の本だと思います。

ForkJoinPool vs ThreadPoolExecutor

12月27日のJJUGナイトセミナーLT大会に参加しました(LT資料)。

会場片付けの際、マルチスレッド処理に関して発表された @hiroga_cc さんと、ForkJoinPoolThreadPoolExecutorの使い分けについて、少しだけおしゃべりしました。その場では頭がこんがらがってしまったので、改めて整理します。

要旨

ForkJoinPoolは、次のようなジョブが効率的に実行できるように設計されたExecutorです。

  • 各タスクがIOをともなわない、CPUヘビーな処理であること。
  • 各タスクの処理が、新しいタスクを産み出すような、再帰的タスク構成であること。

上記の条件を満たさないジョブに対して、ForkJoinPoolが使えないというわけではありません。ただし、タスク発生状況に応じてに応じてスレッドの生成・破棄を制御したい場合などは、ThreadPoolExecutorの方が適しています。

構成と動作

ForkJoinPool, ThreadPoolExecutorとも、下記の点では共通しています。

  • マルチスレッドで、並列にタスクを処理するための仕組みである。
  • ワーカースレッド群と、タスクキューの組み合わせで構成される。

異なる点はタスクキューの構成と取り回しです。ForkJoinPoolでは、ワーカースレッドが可能な限りブロックせずに動作し続けられるように、各ワーカースレッドにひもづいてタスクキューが用意されます。具体的な構成・動作の差異は次のとおりです。

  • ThreadPoolExecutor
    • 全ワーカースレッドがひとつのタスクキューを共有する
    • タスクの投入は共有のタスクキューに対して行う (→ 競合しやすい)
    • ワーカースレッドは共有のタスクキューからタスクを取得する (→ 競合しやすい)
  • ForkJoinPool
    • 各ワーカースレッドが自分のタスクキューを持っている
    • ワーカースレッド内で発生したタスクは、自分のタスクキューに投入される (→ 競合しにくい)
    • ワーカースレッドは、まず自分のタスクキューからタスクを取得する (→ 競合しにくい)
    • 自分のタスクキューにタスクがない場合のみ、他のスレッドのキューからタスクを盗む (work-stealing) (→ 競合しやすい)

ForkJoinPoolでは、ワーカースレッド内で発生したタスクをさばききるまで、自分のスレッドにひもづいたタスクキューだけにタスクの投入、取得を行います。このため、スレッド間競合にともなうブロックなしに計算が続けられます。

IO

タスクの処理がIOをともなう場合、上述したようなForkJoinPoolの利点は消し飛びます。IOは各スレッドが共有するリソースであるため、複数のスレッドが同時にIOを行うと、そこで競合が発生するからです。またIOは、タスクキューの取り回しに比べてはるかに時間のかかる処理であるため、上述したForkJoinPoolのメリットはかき消されます。

上述のとおり、このような場合にForkJoinPoolが使えないわけではありませんが、ThreadPoolExecutorの提供する機能の方が望ましいことが多そうです。

IOによってスレッドがブロックすること自体を避けたい場合は、NIONettyによるノンブロッキングIOを組み合わせることも選択肢となります。

日馬富士関の引退に寄せて

横綱日馬富士が、酒席で貴ノ岩を殴り、その責を負って引退しました。引退はしかるべき対処でしょう。 *1 また、九州場所を全休した貴ノ岩の軽快を祈ります。

日馬富士は、ものすごく直接的に胸を衝く相撲を取る人でした。決して大きくない体と、気迫と魂を相手にまっすぐ全部ぶつける人でした。攻勢一辺倒の横綱といえば他には朝青龍ですが、朝青龍の相撲が、生の歓びの横溢する祝祭的な感じを与えたのに対して、日馬富士の相撲は、土俵に命が掛かってるんだ、という戦慄を与える種類のものでした。

横綱昇進前後の、絶好調と絶不調が交互に訪れる不安定な成績は、遊びのない取り口の必然的な帰結だったのでしょう。絶不調の場所で、それでも綱の体面を保つため、星を稼ぐ窮余の策が当たってすぐの左上手投げで、しかしこれが絶品でした。場所によっては勝ち星のほとんどを左上手投げ一本で稼いで、しかもめったに失敗しなかった。そうこうしている内に、出し投げ主体の曲線的な組み立てへと間口を広げて、安定して綱が張れるようになったのは本当に立派だったと思います。

全身に故障を抱えて、千枚通しのような、鋭いってなもんじゃない立ち合いを十五日間続けられなくなった後でも、ここぞの一番では爆発的な相撲を取ってくれました。弟弟子である照ノ富士の初優勝が掛かった白鵬戦、あるいは新横綱稀勢の里との対戦などなど。九度の優勝、三度の全勝という成績も大変なものですが、それだけでは計り知れない印象を残した横綱でした。

妹が大ファンなんですよね。心配になるくらいほっそい安馬の時代から応援していて。当時から負けん気と向こうっ気はすごかったけど、まさか横綱を張るまでになるなんて思いもしなかった。

*1:昔なら許されたが今では、ということですらない。玉錦と同時代の関脇新海は、同様に酒席で同僚を殴った廉で引退しています。

JJUG CCC 2017 Fallの記録

11月18日に開催されたJJUG CCC 2017 Fallに、スタッフとして参加、およびセッションでしゃべってきました。

一日中セッション部屋担当で、なんかアナウンスしたり、「N分前」の紙を出したり、Twitterのハッシュタグを賑わしたりしていました。

AsciiDocとPlantUMLでドキュメント作成 by 梅澤雄一郎さん #ccc_a1

軽量マークアップ言語であるAsciiDocと、ドキュメント生成系の基盤一式について。

Kinkのマニュアル生成にはreStructuredText+Sphinxを使っているのですが、記述の素直さという点ではAsciiDocに軍配が上がるようです。機能面で便利だと思ったのはコード内にアンカーが付けられるところ。

「GitHub Flowを使いたいがためにGitを使っている」には大賛成です。商用システムの開発において、分散SCMの利点はブランチ・マージがしやすいところにあります。ブランチ・マージを効率的・安全に回すフローを定義して、フローを支援する環境を整備しなければ、宝の持ち腐れどころか、野放図なバージョン管理(管理?)という害悪をもたらすだけだと思っています。

Apache Cassandraを使ったJavaアプリケーションの作り方 by 森下雄貴さん #ccc_a2

CassandraのサンプルアプリケーションであるKillrVideoを題材にして、今風のシステム間連携のやり方を見ていこうぜ、というセッション。

GuavaのEventBusというクラスの存在を知りました。プロセス内のPub/Sub型メッセージバスみたいです。なんか便利かも。

Spring Bootの本当の理解ポイント by 多田真敏さん #ccc_e3

Springコンテナの仕組みと、Spring Bootの役割。Spring Bootは、Springの世界でCoC (Code over Configuration, 設定よりも規約)を実現するための設定ファイル群だよ、という話でした。

スライドも話も実に分かりやすく、ツボをおさえて、さすがはプロの講師、という感じでした。直後の登壇者としては大プレッシャーです。

Java SE 9の紹介: モジュール・システムを中心に by 宮川拓 #ccc_e4

自分のセッション。Java SE 9のモジュール・システムの話+おまけ程度にその他のアップデート、という内容です。どうにもごちゃっとした話をしてしまったなあ、と思いつつ、しかし実際問題ごちゃっとした領域なわけで、もやもやしています。

モジュール・システムについて、理想形を話すのであれば綺麗にまとめられるはずなのですが、聴衆の期待を考えると、むしろ導入時につまづきの石になるだろう部分に重点を置きたい。つまづきの石について話すためには、既存の仕組みとのあいだの弥縫策や、ワークアラウンド的な道具立てについて、ひととおり触れなきゃいけない。分量も多くなるし、ややこしい話にもなる。結局、ひととおりブチ込んで頑張ってしゃべる、という方針でのぞんだのですが、果たしてよかったのかどうか。

目にする反応は総じて悪くなかったので、救われました。

また、一点スライドの補足。

p. 47に「Oracle JDKでは、外部モジュールの非公開メンバへのリフレクションが可能」とありますが、これはOpenJDKでも同じ動作です。「HotSpot系の」とすべきところでした。 *1

速いソートアルゴリズムを書こう!! 松原正和さん #ccc_m8

1. クイックソート+ワークメモリによる安定ソート化変種、 2. マージソートの分割を3分割にすることによる高速化、 3. マージソートの省メモリ化、という3つのアルゴリズムについてのお話でした。

マージソートって3分割でも計算量変わらないんですね。へーと思ったけど理屈は分かっていない。

Design Pattern in Presto source code by 曾臻さん #ccc_m9

  • スライド: まだ公開されてない?

分散クエリエンジンであるPrestoの実装を題材として、Template MethodパターンとVisitorパターンを紹介する、という内容でした。

「Visitorパターンはデータ構造があまり変わらず、適用する処理が多岐にわたる場合に有効」というような整理がされていて、なるほど、と思いました。Visitorインタフェースはデータクラスに依存するので、データ構造の変更には弱いわけですね。

Javaで使えるもう一つのコンパイル方式 - AOT by 西川彰広さん #ccc_m10

JDK9 on Linuxでは、ネイティブバイナリへのコンパイル (Ahead-of-Time Compilation) ができるよ!という話。

AWS LambdaやCloud FunctionsのようなServerless環境や、その他コンテナ環境では、プロセス起動が速いことが重要だけど、この点Javaは弱かった。AOTコンパイルであらかじめバイナリを作っとくことで、若干マシになる、ということです。モジュール・システムの導入にも、同様の問題意識が反映されているものと認識しています。

ただ、サーバサイドJavaは、エコシステム全体が常駐型プロセスを指向しているので、処理系の工夫だけでは足りない面もありそうです。

DBのTCPプロトコルとJDBC by Yohei Yamanaさん #ccc_m11

MySQLとPostgreSQLの、リモートクライアント接続プロトコルの中身の話。

SQLってそのままポコンとDBMSに送られるんですね。クエリエンジンはDBMS側にあるんだからそりゃそうか。あとでYamanaさんに伺ったところ、クライアント側でも最低限のチェックはしているけど、結局サーバ側に行かないと十分な解析・チェックはできない、とのことでした。

Java x ArduinoのIoT アーキテクチャパターン by 山本ユースケさん #ccc_m12

  • スライド: まだ公開されてない?

楽しいArduinoデモ。LEDをチカチカさせたり、プレゼン用マウス的なものを作ったり。

Arduinoのプログラムは独自言語で書くのでJavaは使えません。しかし、FirmataというプロトコルでArduinoデバイスをホストコンピュータから叩くことができ、firmata4jというJava実装もあるよ、という話でした。

総括

一緒に部屋担当についたボランティアスタッフの方々の活躍により、かなりスムースに運営できたと思います。ありがとうございます。おかげで、スタッフとしての参加でありながら、上述のとおり聴講者としても満喫してしまいました。知恵熱が出そうです。

それから、朝晩ちょっとした荷物を運んだだけで、上半身がえらい筋肉痛です。ふだんいかに運動していないか思い知らされます。

*1:Slideshareがスライド再アップロードできない仕様になっているため、訂正できませんでした。