2018-10-29

帰ってきたきれいなリーナス・トーバルズ、無作法な開発者をたしなめる

Linus Torvalds Shows His New Polite Side While Pointing Out Bad Kernel Code - Phoronix

人の心の読み方を学んで復帰したリーナス・トーバルズは、さっそく無作法なプルリクエストをたしなめている。その文章は大文字センテンスも4文字言葉も使っていない優しいものに変わっている。

問題はプルリクエストはBigBenゲームコントローラーに対するドライバーの追加で、このドライバーはデフォルトで有効にされていた。これはLinuxカーネルの慣習にそぐわないものだ。新しく追加された名前もきいたこともないようなデバイス用のドライバーが、いきなりカーネルでデフォルトで有効にはされないものだ。新参者のドライバー開発者は、大抵自分のドライバーはとても重要で、自分の所有しているデバイスは全員所有しているのでデフォルトで有効にするのは当然だと傲慢にも考えている。このような既存の慣習に従わない傲慢な態度は、通常、リーナス・トーバルズによって発見され次第、罵詈雑言を持って鼻っ柱を叩き折り、厳しくしつけられる。

それがなんと以下のように穏やかなメールになっている。

新しいポッと出のドライバーがデフォルトで有効にされることは「ない」。そのデバイスが聞いたことのないような名前の場合は「特に」ありえない。

にもかかわらず、このマージ期間で新しく追加された「BigBenインタラクティブ」ドライバーとやらはまさにそういうことをしている。

そういうことはするな。

分かってる分かってる。開発者は全員、自分のドライバーはとても特別で魔法のように重要なので、当然デフォルトで有効にされるべきだと考えているものだ。だが違う。何千ものドライバーがあるなかで、ポッと出の新しいドライバーが、一部の開発者が特別だと思っているという理由だけで、デフォルト有効にされることはない。

そういうわけで、コミット256a90ed9e46 ("HID: hid-bigbenff: driver for BigBen Interactive PS3OFMINIPAD gamepad")の

default !EXPERT

は完全に間違いだ。プリーズこういうことはしないでくれ。

リーナス

比較のために、去年の11月に似たような問題をたしなめたリーナスのメールを見てみよう。

テメーは新しいドライバーを追加してデフォルトonにしただと。

(大文字)コイツァゼッテーに受け付けらんねーッ。

何でこの俺が直々にマージ期間のたびに毎回言わなくちゃなんねーんだよ。だがもっかい言ってやるぞ。

開発者として、テメーは自分のドライバーとか機能が超絶最高に重要なものだと思ってて、しかもテメーは対応するデバイスも持っているわけだ。

(大文字)だがそんなのァ誰も気にしちゃいねぇんだよ。

これ読んで泣きベソでもかいとけ。オメーのハードウェアが超絶に普及してない限り、全員の設定でデフォルトでデフォルト化されているべきじゃねぇ。

(一部単語が大文字)このブランチで追加されたすべての"defult"の行は間違ってる。

こういうことはやめろ。みんなの期待を裏切る行為だぜ。俺が"make oldconfig"したとき、ポッと出の新しいハードウェアドライバーが有効にされてほしくはない。

もう一つリーナスの忍耐力を試すイベントがあった。リーナス様の環境がKernel oopsをお出しになったのだ。

俺のラップトップが今のgitツリーでカーネルページフォルトを出した。今の所怪しいコミットは

9ee3e06610fd ("HID: i2c-hid: override HID descriptors for certain devices")

これだが、そう思った理由は単に今回のマージ期間でこの辺をいじってるコミットがこれしかないからだ。

oopsは以下の通り

(省略)

だから俺は新しいi2c_hid_get_dmi_hid_report_desc_override()のコードを疑ってるわけだ。

思うに問題はi2c_hid_dmi_desc_override_table[]がNULLエントリーで終端されていないことなので、今からテストする。

この問題はすごく悲しい。これはつまりこのコードは文字通り誰にもテストされてないってことで、誰もこのリストにエントリーを入れてないってことだ。

ちなみに以前、リーナスがパッチを適用したカーネルをブートするだけで確実にカーネルoopsを発動させるような初歩的なミスを発見した場合は、大文字で「テストされてないクソ」となじり、罵詈雑言あふれるメールが飛ぶものだ。

2018-10-24

C++標準化委員会の10月の興味深い文書

2018-10のC++標準化委員会の文書集が公開されていたので、興味深い新機能の提案に限って紹介する。

secure_val

セキュリティ上の理由でメモリの内容を破棄したい場合、コンパイラーの最適化によって意図通りのコードが吐かれないことがある。


void decrypt()
{
    char password[64] ;
    // パスワードを取得
    get_password(password) ;

    // 複合処理
 
    // パスワードをメモリから破棄
    std::memset( buffer, 0, 64 ) ;
}

このコードでは最適化の結果memsetが省略されるかもしれない。なぜなら、bufferはmemsetの後に使われていないから、memset自体が不要だとコンパイラーは判断できるからだ。

そのために、最適化によって消えずに値を消去できるライブラリを提供する。


void secure_clear( void * data, size_t size ) noexcept ;
template < typename T >
void secure_clear( T & object ) noexcept ;

この提案はさらに、secure_val<T>クラスを提案してる。secure_valはT型を保持するクラスで、デストラクターはT型をセキュアに破棄する。T型の値にアクセスする方法は関数オブジェクトを指定するもので、コピーを許さない。


void decrypt()
{
    std::secure_val<char [64]> val ;

    val.access([]( auto & data )
    {
        get_password( data ) ;
    } ) ;

    // 複合処理

    // valのデストラクターがセキュアにメモリ上の値を廃棄
}

unique_val

secure_valに似ているunique_val。これはT型をコピーせずにムーブするクラスだ。

ムーブしたあとのT型はデフォルト初期化された値になる。

ポインターやシステムリソースへのハンドルを扱うのに使える。

Remember the FORTRAN - p1300r0.pdf

C++に現在提案されているモジュールの実験的な実装はFORTRANが30年間解決できなかったパフォーマンス上の課題を抱えていると警鐘を鳴らす文書。

GCCのモジュール実装では、モジュールのソースファイルをコンパイルして.nsmファイルを作成しその後そのモジュールをimportするソースファイルをコンパイルすると、該当する.nsmファイルを使う。

FORTRAN-90はモジュール機能を備えており、これは今のC++のモジュールと原理的に同じ機能を同じ実装で提供している。つまりFORTRANは30年前からモジュール機能がある。

あるモジュールをimportするソースファイルをコンパイルするためには、事前に依存するモジュールをコンパイルしなければならない。モジュールは別のモジュールをimportできる。つまりモジュールをコンパイルするには事前に依存する別のモジュールをすべてコンパイルしなければならない。

これはビルドシステムととても相性が悪い。ビルドシステムが複数のソースファイルからなるプログラムをビルドするとき、モジュールの依存関係を把握してDAGを構築し、適切な順序でモジュールをコンパイルしなければならないということだ。つまりビルドシステムはC++ソースファイルを解釈する必要がある。

IntelのFORTRANコンパイラーのマニュアルは「プログラムが依存するモジュールのファイルは事前に生成しておけ」という。Intelという超巨大で世界的な大企業ですら、莫大な利用料を支払う顧客に対して、「依存してるモジュールは事前に全部コンパイルしとけよ」ぐらいの助言しか与えられていないのだ。

著名なGNU Fortran開発者ですら、Fortranのプログラムをビルドするときは、「Makeを成功するまで十分な回数実行する」と言っている。

モジュールを正しくコンパイルするにはモジュールの依存関係の解析が必要で、そのためにはソースファイルの解釈が必要になる。Makeやninjaのような汎用的なビルドシステムにC++を解釈する機能をつけることは現実的ではないので、C++コンパイラーが依存関係を解決する機能を提供するようになるだろう。

ところで、Windowsはプログラムを起動するパフォーマンスが極めて悪い。1ソースファイルごとにC++コンパイラーを1回起動して依存関係を解決するような実装はWindowsではパフォーマンスが悪い。

不自由で低能なWindowsはプロセスの作成もスレッドの作成も遅いし、ましてやファイルの作成に至っては、i7でNVMeのSSDを積む高性能なコンピューター上で動くWindows 10がRaspberry PiとSDカード構成のRaspbianにすらパフォーマンスで負けるという信じられないほどの低能を誇っている。

Benchmarking OS primitives – Bits'n'Bites

そして、ソースファイルの一部だけを変更した後の部分的なビルドですら、モジュールの依存関係が変わるかもしれないので依存関係の解決が必要だ。

モジュールはビルド時間を削減するべきであって、ビルド時間を増やすのは本末転倒だ。

FORTRANが30年かかっても解決できていない問題は解決できそうにない。

P1283R0: Sharing is Caring

Linuxのshared libraryやWindowsのDLLのためにエンティティをexportする属性、sharedの追加の提案。

P1282R0: Ceci N’est Pas Une Pipe: Adding a workflow operator to C++

新しいワークフロー演算子として<|と|>を追加する提案。


// 右から左
a <| b ;
// 左から右
a |> b ;

C++20にはレンジやExecutorやコルーチンやモナドが提案されているがこれらの提案は右から左、もしくは左から右といった処理の流れを記述する。例えば以下は1から始まる整数列を生成し、奇数だけをフィルターした整数列にし、その先頭から5個だけを取り出した整数列にするレンジのコードだ。


iota(1) | filter(odd) | take(5) ;

これは処理の流れがわかりにくい。すでにoperator >>はあるが、これは演算子の評価順序の関係で使えない。operator >>=なら使えるがこれは汚い。

そこでオーバーロード可能なワークフロー演算子を追加する。


iota(1) |> filter(odd) |> take(5) ;

これはほしい。

P1281R0: Feature Presentation

本当の条件付きコンパイル機能の提案。

constexpr ifは条件付きコンパイルではなく、条件付きテンプレート実体化抑制機能だ。そのために意味上エラーとなるコードを書くことができない。

この提案では、条件付きコンパイル機能を提供する属性により、文法上正しいが、意味上エラーとなるコードを書けるようにする。


[[ feature("key")]] 

[[feature()]]はキーとなる文字列を受け取る。このキー文字列が宣言されていないか、ブロックリストに入っている場合は、その属性がある宣言とその中身がASTから取り除かれる。

利用例は以下の通り。


struct [[feature("vulkan")]] Device {
  [[feature("glsl-to-spirv")]]
  static Shader compile(std::filesystem::path filename);
  static Shader load (std::filesystem::path spirv_file);
};

struct [[feature("direct-x")]] Device {
  [[feature("hlsl-to-spirv")]]
  static Shader compile (std::filesystem::path filename);
  static Shader load (std::filesystem::path spirv_file);
};

いまグラフィックAPI用のライブラリを書きたいとする。このライブラリはVulkanとDirectXを両方サポートする。ただしコンパイル時の環境では、VulkanかDirectXのどちらかしか提供されていない。上のようなコードで、"vulkan"か"direct-x"のどちらかのキー文字列だけを宣言することで、2つのDeviceクラスの実装のうち、どちらか片方だけを有効にできる。無効な属性のクラスはまるごとASTから取り除かれる。

さらにこのライブラリはシェーダー言語であるGLSLやHSSLからSPIR-Vへの変換機能を提供するが、条件次第ではこの機能を提供しないことも選択できる。

文法上妥当である必要があるので、比較的穏当な条件付きコンパイルだ。#ifdefはいずれ廃止したいものだ。

P1280R0: Integer Width Literals

ビット長を指定した整数型intN_tとuintN_tに対するユーザー定義リテラルとして、operator "" iNとoperator "" uNを追加する提案。


using namespace::literals ;

auto a = 0i16 ; // std::int16_t
auto b = 0i32 ; // std::int32_t

auto c = 0u8 ; // std::uint8_t
auto d = 0u64 ; // std::uint64_t

便利だ。

P1279R0: std::breakpoint

プログラムからブレイクポイントを設定できるライブラリstd::breakpointの提案。


using namespace std::literals ;

int main()
{
    std::breakpoint() ;
    std::cout << "hello"sv ;
    std::breakpoint() ;
    std::cout << "world"sv ;
    std::breakpoint() ; 
}

P1278R0: offsetof For the Modern Era

std::offsetofの提案。offsetofはマクロでstandard layout classにしか使えない。std::offsetofはstd::bit_castで実装できるが、std::bit_castはconstexprではない。std::offsetofはconstexprになるべきだが、議論が必要だ。

P1277R0: Subscripts On Parade

operator []で複数の引数を取れるようにする提案。


struct S
{
    int & operator [] ( int a, int b, int c ) ;
} ;

int main()
{
    S s ;
    s[1,2,3] = 1 ;
}

多次元配列ライブラリが提案中だが、多次元配列へのアクセスをできるだけ直感的に書けるようにしたい。

P1276R0: Void Main

void mainを認める提案。すでにmain関数は空のreturn文を認めていて、その場合は0を返したものとみなされる。ならばvoid mainも認めてよいはずだ。

P1275R0: Desert Sessions: Improving hostile environment interactions

C++にプログラムの引数の参照と、環境変数を参照、変更できるライブラリを追加する提案。C++風にイテレーターでアクセスできる。

P1274R0: Bang For The Buck

識別子としてダラーサイン($)を認める提案。さらに、識別子の最後に限り驚嘆符(!)と疑問符を(?)を認める。

これにより"set!"や"empty?"のような関数名も使えるようになる。

$は静的リフレクションのキーワードreflexprの代わりに使えるようにすべきだという声もあるが、著者は識別子として使えるようにしたほうが有益だと主張している。

私としては$はreflexprの代わりに使いたい。jQueryのように・・・というと縁起が悪いが。

Pattern Matching - p1260r0.pdf

パターンマッチの提案。文法は比較的穏健。

整数の例


// Before
switch (x) {
    case 0: std::cout << "got zero";
    case 1: std::cout << "got one";
    default: std::cout << "don't care";
}

// After
inspect (x) {
    0: std::cout << "got zero";
    1: std::cout << "got one";
    _: std::cout << "don't care";
}

文字列の例


// Before
if (s == "foo") {
    std::cout << "got foo";
} else if (s == "bar") {
    std::cout << "got bar";
} else {
    std::cout << "don't care";
}

// After
inspect (s) {
    "foo": std::cout << "got foo";
    "bar": std::cout << "got bar";
    _: std::cout << "don't care";
}

tupleの例


// Before
auto&& [x, y] = p;
if (x == 0 && y == 0) {
    std::cout << "on origin";
} else if (x == 0) {
    std::cout << "on y-axis";
} else if (y == 0) {
    std::cout << "on x-axis";
} else {
    std::cout << x <<','<< y;
}

// After
inspect (p) {
    [0, 0]: std::cout << "on origin";
    [0, y]: std::cout << "on y-axis";
    [x, 0]: std::cout << "on x-axis";
    [x, y]: std::cout << x <<','<< y;
}

他にもvariantの例、ポリモーフィック型の例、式を評価する例がある。

pattern_matching

別のパターンマッチの提案。こちらはどの関数型言語からやってきたんだというぐらい既存のC++にそぐわない異質な文法になっている。

enumの例


enum color { red, yellow, green, blue };

// Before
const Vec3 opengl_color = [&c] {
  switch(c) {
    case red:
      return Vec3(1.0, 0.0, 0.0);
      break;
    case yellow:
      return Vec3(1.0, 1.0, 0.0);
      break;
    case green:
      return Vec3(0.0, 1.0, 0.0);
      break;
    case blue:
      return Vec3(0.0, 0.0, 1.0);
      break;
    default:
      std::abort();
  }();

// After
const Vec3 opengl_color =
  inspect(c) {
    red    => Vec3(1.0, 0.0, 0.0)
    yellow => Vec3(1.0, 1.0, 0.0)
    green  => Vec3(0.0, 1.0, 0.0)
    blue   => Vec3(0.0, 0.0, 1.0)
  };

あまりにもC++として異質すぎる。

クラスに対するパターンマッチの例


struct player {
  std::string name;
  int hitpoints;
  int lives;
};

// Before
oid takeDamage(player &p) {
  if(p.hitpoints == 0 && p.lives == 0)
    gameOver();
  else if(p.hitpoints == 0) {
    p.hitpoints = 10;
    p.lives--;
  }
  else if(p.hitpoints <= 3) {
    p.hitpoints--;
    messageAlmostDead();
  }
  else {
    p.hitpoints--;
  }
}

// After
void takeDamage(player &p) {
  inspect(p) {
    [hitpoints:   0, lives:0]   => gameOver();
    [hitpoints:hp@0, lives:l]   => hp=10, l--;
    [hitpoints:hp] if (hp <= 3) => { hp--; messageAlmostDead(); }
    [hitpoints:hp] => hp--;
  }
}

あまりに既存のC++の文法とは違いすぎる。

p1235r0.pdf

implicit constexprの提案。

constexpr関数の制約は今後ますます減っていき、コンパイル時定数式にしたい処理は今後ますます増えていく。

C++17ではlambda式のoperator ()は暗黙にconstexprだ。この結果、以下の同じように見えるコードの挙動が異なる。


int f( int x ) { return x ; }
auto g = [](int x ) { return x ; }

// Error
constexpr int a = f(0) ;
// OK
constexpr int b = g(0) ; 

そこですべての関数を暗黙にconstexprにしてしまおうというのがこの提案だ。

C++ Compile

C++のコンパイル方法を標準化しようという提案。C++の教育SGが提唱されたり、パッケージシステムも議論される中、必要な提案ではあると思うが、果たして受け入れられるだろうか。

この提案では、コンパイラーのオプション指定は+で指定する。長いオプションは++で指定する。

cpp hello.cpp ++output=hello

まず<compile>ヘッダーにコンパイラーを呼び出すライブラリが追加される。


namespace std
{
  int compile(int, char * *) noexcept;
  int compile(vector<string>) noexcept;
}

一つ一つの文字列がargumentとして処理される。+で始まらないargumentはソースファイル名だ。

+で始まるのはコンパイル時のオプションで、例えばヘルプメッセージの出力、出力ファイル名、デバッグといったC++コンパイラーによくあるオプションを定義している。

コンパイル方法を標準化することによって、教育や提案中のパッケージシステムで使いやすくなる。

ファイルシステムライブラリも標準C++にある今、C++ライブラリとしてのビルドシステムという不思議な概念が浮かんだ。

p1177r0.pdf

パッケージシステムの全容の提案、コンパイラーAPI、ビルドシステムAPI、パッケージ依存解決API、パッケージ検索APIによって構成される。

P1214R0: Pointer to Member Functions and Member Objects are just Callables!

メンバーへのポインターをINVOKEのように振る舞わせる提案。


struct Foo
{
    int data ;
    int func( int x ) { return x ; }
} ;

int main()
{
    int (Foo::*data_ptr) = &Foo::data ;
    int (Foo::*func_ptr)(int) = &Foo::func ;
    Foo obj ;

    // Before
    obj.*data_ptr = 123 ;
    (obj.*func_ptr)(123) ;

    // After
    data_ptr(obj) = 123 ;
    func_ptr(obj, 123) ;
}

ジェネリックコードで大量の特殊化を書く必要がなくなる。

p1227R0: Signed size() functions

符号付き整数を返すsize関数としてssizeの提案。

std::vector<int> v ;
for ( int i = 0 ; i < v.size() - 1 ; ++i )
{ }

このコードは"0u-1"を実行してしまうので意図通り動かない。ssizeがあれば、"v.ssize() - 1"と書ける。

P1108R1: web_view

画期的に使いやすいグラフィックライブラリ、webviewの提案の改定案。変更点としては議論が追加されている。これはHTMLとCSSをブラウザーで表示し、JavaScriptを注入できる極めて簡単なライブラリだ。

2018-10-23

SQLiteの行動規範がキリスト教徒の戒律を全文引用していて香ばしすぎる

Code Of Conduct

SQLite creator crucified after code of conduct warns devs to love God, and not kill, commit adultery, steal, curse... • The Register

SQLiteの行動規範(Code of Conduct)は大真面目に西暦500年の聖ベネディクトの作った72か条の戒律を全文引用している。この行動規範はSQLiteの利用者が同意する必要はないが、開発者は同意しなければならない。結果としてSQLiteは危険すぎるので使ってはならない。なぜならばSQLiteの開発者は全員キリスト教原理主義者で奴隷制度を肯定し非武装でキリスト教徒に改宗すらさせた敵をジェノサイドしたカルト宗教の信奉者であり、キリスト教の教義に合わないコードは書かず、異教徒を攻撃するだろうからだ。

聖ベネディクトが西暦500年ごろに作った72か条の戒律のほとんどは現代の価値基準に照らし合わせて香ばしい。

  1. まず第一に、主たる神をまつたき心、まつたき魂、まつたき力を以って愛せよ
  2. しこうして、汝の隣人を汝がごとく愛せよ
  3. 殺すなかれ
  4. 姦淫するなかれ
  5. 盗むなかれ
  6. 欲するなかれ
  7. 偽証するなかれ
  8. 皆を敬え
  9. 汝自身にせぬことを他人にするなかれ
  10. キリストに従うために汝自身を否定せよ
  11. 汝自身を折檻せよ
  12. 喜びに耽るなかれ
  13. 断食を愛せよ
  14. 貧者を慰撫せよ
  15. 裸人に服を与えよ
  16. 病人を訪れよ
  17. 死人を埋葬せよ
  18. 艱苦を救え
  19. 嘆きを慰撫せよ
  20. (訳注:異教徒どもの罪深い)世界とは手を切れ
  21. キリストへの愛のほかには何も好むな
  22. 怒りに身を任せるな
  23. 遺恨を養うな
  24. 心に偽りを抱くな
  25. 偽りの和平を結ぶな
  26. 寄進を惜しむな
  27. 呪うな、汝自身を偽るがゆえに
  28. 心からの真実のみを口にせよ
  29. 邪悪に邪悪をもって返すな
  30. 他人に邪ならずして、汝への邪は甘んじて受けよ
  31. 汝の敵を愛せよ(訳注:敵の存在も神の思し召しなるがゆえに)
  32. 汝を呪うものを呪うな。祝福せよ
  33. 正義のために懲罰を受け入れよ
  34. 誇るなかれ
  35. ワインを痛飲するなかれ
  36. 鯨飲馬食するなかれ
  37. 寝ぼけるなかれ
  38. 怠けるなかれ
  39. 愚痴るなかれ
  40. 中傷するなかれ
  41. 望みを神に託せ
  42. 汝にかかる良きことは汝の功にあらずして神の功とせよ
  43. 己の行いは邪にして己の責に帰すことを思え
  44. 審判の日を恐れよ
  45. 地獄を恐れよ
  46. 全身全霊で永久の命を欲せよ
  47. 毎日死を見つめよ
  48. 人生における行動に常に気をつけよ
  49. 神はすべての場所を見張っていることを確実に知れ
  50. 邪なる思いが胸中に生ずるときはただちにキリストに帰依し、精神の父なることを認識せよ
  51. 邪なる言葉を口にするなかれ
  52. 饒舌を愛するなかれ
  53. うぬぼれや笑いをもたらす言葉を話すなかれ
  54. やかましい笑いと行き過ぎを愛するなかれ
  55. 聖書の朗読を積極的に聞け
  56. 頻繁に祈れ
  57. 祈りにおいては毎日己が神に対する罪に落涙嘆息し、かかる邪を将来に償うことを思え
  58. 肉の欲望を満たすなかれ
  59. 己が意思を憎め
  60. 神が権威を託した者の命にすべて従え。たとえ権威者が自ら率先せずとも従え(そは神の禁じたもうことなり)。主のかの言葉を思い起こせ「他人の言葉を汝行い、他人の行いを汝行うなかれ」と
  61. 己の至らぬのに聖人と呼ばわるることを望まずして、呼ばわるるところの聖人たらんとせよ
  62. 神の戒律を日々満たせ
  63. 禁欲を愛せよ
  64. 誰をも嫌うな
  65. 嫉妬羨望するなかれ
  66. 諍いを好むなかれ
  67. 傲慢を避けよ
  68. 目上を敬え
  69. 目下を愛せよ
  70. 汝の敵にキリストの憐憫を祈れ
  71. 日没までに汝の反対者と和平せよ
  72. 神の慈悲に悲嘆するなかれ

2018-10-22

江添誕生日ボドゲ会@10月28日

江添誕生日ボドゲ会@10月28日 - connpass

10月は誕生日なので週末の28日に昼からボドゲ会、夕方からすき焼き会をすることにした。参加表明はconnpassから行える。

2018-10-14

消費税について考えたこと

「消費税10%は100円が110円になると考えるのではなく、1000万円が1100万円になると考えるべきだ」というつぶやきを目にした。しかしこれは言っていることが同じだ。

私はむしろ、消費税とは手取りに対する税金ではないかと考えている。貯蓄をしない家計では、消費税は実質手取りに対する税金だ。貯蓄をしない家計にとって、消費税10%とは、手取り20万円が18万円になることだ。

もっとも、この考え方にも問題はある。というのも貯蓄をしない家計は賃貸住宅に住んでいるだろうが、不動産の貸付料である家賃には消費税はかからない。手取り20万円の家計で家賃6万円の場合、14万円が12万6千円になるということだ。

消費税と言えばイタリアは先進国だ。1973年という昔から12%の消費税を導入し、1997年には20%に引き上げられた。そのイタリアでは、表に出ず消費税を脱税した地下経済とマフィアが発展した。

消費税が10%ともなると、日本でも地下経済と、地下経済の信用取引を履行させるためのヤクザが発展するだろうか。

日本ではヤクザの人権を剥奪する法律によりヤクザの人口が急激に減りつつある。また個人間の送金手段は経済に悪影響を及ぼすほど厳しく規制しているので地下経済も発展しにくい。

とはいえ、消費税があまりにも高くなれば地下経済は発展するだろうし、地下経済が発展したならば、その信用取引を確実に履行させるための機関としてヤクザが必要になり、ミカジメ料を支払うようになるのでヤクザも再び興隆するだろうか。

ということを考えながら、消費税制度の解説を眺めていたところ、興味深い定義を発見した。

「郵便切手類、印紙、証紙、物品切手の譲渡は非課税取引」

興味深い定義だ。すべての取引が地下経済に潜ることはできない以上、我々は表の取引もする。であれば、一部の取引を切手や印紙による取引とするのは現実的ではないだろうか。素晴らしいことに地下経済にする必要すらない。単なる非課税取引をしたにすぎないのだから。

具体的に考えよう。君は牛を二頭持っている。今君は牛を一頭売る契約をしたので契約書作成の税金を収めるため収入印紙を貼る必要がある。君は残りの牛一頭のミルクを売って現金を得て消費税を払い、残りの現金で収入印紙を買う。もし、君がミルクと収入印紙を直接交換したならば、消費税を支払う必要はない。

すばらしい。我々は現金ではなく収入印紙で支払うことによって消費税を節税することに成功した。消費税を支払わない分、ミルクの値段を下げるか、利益を上げることができる。

こう考えると、消費税の存在は貨幣経済に対する足かせであるように思えてくる。

しかし収入印紙は日本国に対する支払いにしか使えない用途の限定された通貨だ。現金という汎用的な通貨ではない。この問題をどうすればいいのだろう。

収入印紙には需要がある。需要があるものは汎用的な通貨である現金と交換できる。例えば金券ショップでは、収入印紙は額面の95%ぐらいで交換できる相場だ。ところで今の消費税は8%である。収入印紙で取引して収入印紙を現金化した場合の損失が、消費税率を下回る場合、これは得をしたと言えるのではないか。しかも合法だ。つまり収入印紙での取引は合法的な節税になるのではないか。

私は経済学にも消費税制度にも詳しくないのだが、この解釈は正しいのだろうか。

2018-10-07

Steven WeinbergのTo Explain The Worldを読んだ

邦訳では「科学の発見」という題名がついているSteven WeinbergのTo Explain The Worldを読んだ。

著者のSteven Weinbergはノーベル物理学賞の受賞者でイスラエルの熱烈な支持者だ。

冒頭で「本書で筆者は過去を現代の基準で批判する愚を犯す」と書きながら、この本は科学がどのように発展してきたかを解説している。

本書はまず、古代ギリシャにおける万物を構成する元素の説について取り上げる。古代ギリシャの哲学者が、元素は水だとしたり、火だとしたり、水、火、土、空気の4種類だと主張している歴史を取り上げる。

ここまではまあいいとして、プラトンの提唱した説を取り上げて悶絶する。プラトンは四大元素である火、水、土、空気について、とても小さい元素が存在し、5種類ある正多面体をそれぞれ割り当てた。たとえば火は正四面体で、水は正二十面体といった具合だ。その仮説を立てるのはいいとして、割り当ては一体どういう理由で行われたのか。プラトンは単にそれが理想だからとしか語らない。

科学というものは、まず観測し、観測結果から仮説を立て、仮説が観測結果に従うことを検証するものだ。

しかし古代ギリシャでは、科学は科学ではなく哲学で、単に理想を追求するものでしかなかった。なので万物を構成する元素は元素は火や水といったわかりやすい理想的なものになり、元素は5種類ある正多面体であるとし、完全数を尊びといった、現実の観測結果より理想を追求し、理想が現実に従わないことは無視されていた。

その後、本書の大半は天体の運行の予測を通じた科学の発展に費やされる。

天体の運行には規則性があり、古代から占星学などの存在により、天体の運行を正確に予測する需要があった。

古代ギリシャ時代から地球が中心で月、惑星、太陽、その他の恒星は全て地球の周りを回っている説が主流であった。

古代ギリシャ時代にはすでに地球を中心とした天体の運行を予測する数式モデルが考案されていたが、他の天体はすべて地球を中心とした真円で回るなどと定義されていたため、現実の観測とは大いに異なっていた。しかも、それぞれの天体が謎の理由で割り当てられた正多角形に内接する真円で回るなどという、これまたプラトンのように理想を追求したモデルであった。

天体は地球を中心に真円で回転するモデルを使うと、惑星はある時期だけ逆方向に回りだしたりする。惑星が大抵の言語で語源からして、惑う星であるのも、これが原因だ。

そこでプトレマイオス説が考案された。この説では、天動説で現実の観測結果に近似させるために、あまりにも無理やりな天体のモデルを考案した。天体は太陽を中心に真円で回っている。この真円を従円と呼ぶ。天体は従円を線上を中心としてさらに真円で回っている。この真円を周転円と呼ぶ。

プトレマイオス説は複数の真円を組み合わせ、真円の大きさをパラメーター化することで、惑星の運行を現実に近似させることを試みた。その結果、かなりの制度で現実の観測に近似した天体モデルを作ることに成功した。

プトレマイオス説は科学だ。観測から観測結果に従う数式モデルを作ったわけで、これは科学と言える。

プトレマイオス説は哲学者からは理想ではなく天体の予測のための方便であるとされていた。天文学者(この時代の天文学者は占星学をかねる)は積極的に使っていた。というのも、プトレマイオス説は現実の観測結果の近似していて、予測に役立つからだ。

その後、様々な天文学者がプトレマイオス説により複雑な周転円を追加することで、さらに現実の観測結果に近づける努力が行われた。

太陽を中心として天体が公転している地動説は以前にも理想として提唱されたことはあったが、現実の観測結果を説明できる具体的な数式モデルはコペルニクスによってまず作られた。ただし、コペルニクスの数式モデルは精度が悪かった。というのも、コペルニクスは天体は太陽を中心に真円で公転していると定義したが、実際には太陽は中心ではなく、天体の公転軌道は真円ではないからだ。

本書は中東の科学についても解説している。中東の科学はイスラム教の普及によって妨害されるまでヨーロッパより進んでいた。ギリシャ時代の学説は中東からもたらされる形でヨーロッパに再発見された。その後イスラム教の普及により中東の科学の発展は阻害された。

そしてガリレオ・ガリレイの時代までやってくる。ガリレオ・ガリレイは優秀な望遠鏡を発明し、望遠鏡によって精密な天体観測をした。その結果地動説を唱えるわけだが、その上でパトロンであるローマ教皇を天動説を信じているなどと批判したので宗教裁判にかけられて地動説を封印する。後世に残る逸話によれば、このときガリレオは「それでも地球は回っている」とつぶやきながら法廷を後にしたと言われる。

宗教裁判の後、ガリレオは晩年まで自宅に軟禁状態におかれるわけだが、ガリレオの科学への情熱は冷めていなかった。ガリレオは落下する物体の速度について研究していた。落下する物体の速度を観測するのは当時としては難しい。というのも、速度が速すぎるために正確な観測ができないためだ。

ガリレオはこの落下速度の問題に対し、科学的な観測方法を考案する。緩やかな傾斜面を転がる球を使うことで速度の計測を可能にした。時間の計測には水時計を使った。傾斜角を変えることでガリレオは速度は傾斜角に比例することを示し、傾斜角を転がる球は落下速度の計測の代わりに使うことができることを示した。もちろん現実には、球と傾斜面の摩擦にもエネルギーが使われるが微々たるもので当時実現可能な観測方法としては十分なものだった。ガリレオは傾斜角を転がる球を机の端から飛ばし、その軌道が放物線であることも観測している。

本書はニュートンの説明に移る。ニュートンによって科学革命はクライマックスを迎えるわけだが、しかしこのニュートンという人物はなんという奇人だろうか。ニュートンは生涯、イングランドのごく狭い地域より外に出ることはなかった。ニュートンは潮の満ち引きについて多大なる関心を持っていたにもかかわらず、生涯一度も海を見ることはなかった。中年に至るまでニュートンは身近に女を寄せ付けることがなかった。母親とて例外ではない。50代になってから親戚の美しい娘を家政婦として雇っているが、この2人の間に男女関係はなかった。ニュートンは科学以外にも、非科学的な錬金術や宗教について多大な著作を残している。

ニュートンの研究者の間でよく言われることには、ニュートンは最初の科学者ではない。ニュートンは最後の魔法使いである。時代が魔法から科学に変わる節目の時期にあって、魔法から科学への橋渡しをした人物だ。

ニュートンの法則を記述したPrincipiaは、単に重力を説明し得たために偉大だというわけではない。ニュートンはPrincipiaによって、物理的現象は簡単な数学的原則と、その原則の応用で説明できることを示したのだ。

中国の悪意あるハードウェアの細工を見破る方法

中国で生産されているハードウェアに悪意あるチップが取り付けられておりAppleやAmazonが被害にあっているとする報道があり、真偽について議論がある。

これに関連して、Hacker Newsで興味深いコメントが寄せられていた。

I have worked in card payment industry. We would be getting products from China ... | Hacker News

俺はカード支払い業界で働いている。中国から送られてくる製品にクレジットカード情報を送信する装置が取り付けられていることがある。これは国家による攻撃ではない。装置は生産ラインの途中で取り付けられている。大抵は賄賂を受け取った従業員によるものだ。装置が組み立てられた後は、改造防止の機能が動くので、改造を検知させずに装置を分解するのは不可能だ。

この問題が発覚してから、我々は製品の重さを計測することにした。我々も製品を分解することはできないからだ。分解したならば改造検知により装置は動かなくなる。

攻撃者は重さの計測に気がついたので、製品内部の必須ではないプラスチックを引っぺがして装置を追加することによって増加した重さの調整をしてくるようになった。

結局、我々は特別な土台を使い製品の角運動量(訳注:慣性モーメントか)を計測するようになった。とても高価な装置で角運動量を計測する。俺が作った土台を使って2つの角度から角運動量を計測している。2つの製品の角運動量がどの角度からでも一致するならば製品は同一というわけだ。すべての角度から角運動量を計測できないが、今のところ破られていない。

角運動量ではなく慣性モーメントだろうという用語の甘さや、慣性モーメントは3軸を使って全角度を測定できるのではというツッコミが入っているが、この話自体はよくあるものらしい。

なんでそんな製造段階で悪意ある細工が混入した製品を送ってくるところと取引を続けるんだというコメントに対し、この製品を製造しているのは今や中国をおいて他にないとか、中国の商習慣では信頼を前提としない契約による取引に応じてくれないとか、中国と取引するには製品の欠陥は自前で発見できなければならない、発見できないのはマヌケな顧客であり欠陥品で十分だとみなされる、などの中国のお国柄を指摘するコメントが続いている。