JJUG CCC 2017 Spring

5月20日の土曜日に開催されたJJUG CCC 2017 Springの運営スタッフをやってきました。

Java SE 9もぐだぐだだし、さすがに今回は人減るんじゃねーの、と予想していましたが、ピーカンの晴天も手伝って、1000人以上が参加する大盛況でした。とはいえこれは会場の容量ギリギリで、セッションの満員札止めも続出し、今後の開催に課題を残しました。

当日は、朝から夕方までべったりセッション部屋を担当しました。担当した10セッションすべてが、質の高い良いセッションでした。おそろしいことです。

とりわけガツンと来たのは、大中浩行さんの20分セッション「Java8移行は怖くない〜エンタープライズ案件でのJava8移行事例〜」でした。

元からバージョン管理やCIなど変更に耐えうる足回りを整えており、また小規模な改修やミドルウェアのアップデートなど、システムに手を入れ続けていた。したがって、Java 8移行に関する個別の課題は同じようにふつうに片付けられた、という話でした。

大中さんはメッセージを「技術的に新しいことに取り組まなくなった組織は緩やかに衰退していく」(p. 13)と要約しています。これを肯定形にすると、「新しいことに取り組み続けることでのみ、組織を堅固に保ち続けられる」、ということになろうかと思います。その理由は、

  • メンバーの士気が高まる。
  • 変更を加え続けるための技術的・人材的・組織的地盤が整備される。
  • 個々の改定が、取り組みやすい小さなステップにできる。

というわけです。

実際のところ、あらゆるシステムは協調システムであり、その度合は日増しに強くなっている(Web, クラウド, マイクロサービス, etc.)のだから、「動くコードに触」らない(p. 57)ことによって維持できるという信念は、合理性を着実に失っているのだと思います。

大相撲2017年五月場所中日

● 3-5里山(叩き込み)安美錦4-4 ○

里山見るような立ち合い。安美錦突っ張りながら引き、里山押してついていくが、安美錦押し上げて叩き込み。安美錦うまかった。

○ 4-4佐田の海(押し出し)山口4-4 ●

佐田の海頭で当たって左差し。山口が右に開いて引くのに付いて行って押し出し。これぞ佐田の海の相撲。

● 5-3阿武咲(押し出し)宇良6-2 ○

宇良が低く当たるのを阿武咲突き起こして突き起こして攻める。間合いが空いて、阿武咲が両手突きで飛び込んでくるところを宇良右にいなし、向き直ったところを押し出し。

宇良大きくなった。もう小兵って感じでもない。

● 2-6豊響(押し出し)輝6-2 ○

豊響の当たりを輝両おっつけで止める。押して出るが足がそろって押しきれず、豊響左喉輪から突っ張って逆襲。輝も突き返して右にいなして押し出し。

○ 5-3徳勝龍(押し出し)勢5-3 ●

徳勝龍頭で当たって突っ張り猛然と勢を粉砕。

○ 5-3貴ノ岩(寄り切り)蒼国来 3-5 ●

貴ノ岩左踏み込んで右差し左上手前廻し。蒼国来半身でねばるところを貴ノ岩上手引きつけて、外掛けを掛けながら寄り切り。貴ノ岩、星以上によく見える。

● 2-6松鳳山(寄り切り)正代6-2 ○

松鳳山の両喉輪で正代そっくり返るが、足は下がらずに左抱えて寄り切り。相変わらず無茶な相撲。

○ 6-2北勝富士(寄り切り)宝富士3-5 ●

北勝富士右おっつけから押すが宝富士用意に下がらない。右を差し、左も差した?左の投げから引きつけて出るところ、北勝富士左足一本で踏ん張って、左ハズ押しで逆転寄り切り。いい相撲!

○ 2-6千代の国(寄り切り)大栄翔0-8 ●

大栄翔の突っ張りをかいくぐって千代の国右差し、大栄翔巻き替えて左四つ。しかし四つなら千代の国のほうが上手。両廻し引きつけて寄り切り。大栄翔ストレートの負け越し。

○ 6-2玉鷲(押し出し)隠岐の海1-7 ●

玉右喉輪左ハズ押しで圧倒。

● 4-4嘉風(叩き込み)高安7-1 ○

高安左踏み込んでぶちかましから突っ張っておいて叩き込み。難敵を簡単に料理した。

○ 6-2照ノ富士(極め出し)御嶽海3-4 ●

御嶽海両差しで出るが、照ノ富士閂から引っこ抜いて極め出し。

○ 3-5遠藤(寄り切り)豪栄道5-3 ●

遠藤右踏み込んで低く当たると豪栄道左に開いて叩く。土俵を伝って回り込む豪栄道を、遠藤なおも追撃して両差し、腰を落として寄り切り。遠藤良い相撲。

● 1-7琴奨菊(右上手出し投げ)白鵬8-0 ○

白鵬呼吸をずらして琴奨菊の出足を遅らせる。あたって左四つ、琴奨菊がぶるが白鵬土俵中央で捕まえて、上手を切って右上手投げ。

○ 7-0日馬富士(押し出し)千代翔馬1-7 ●

日馬富士鋭い出足、両手突きから右喉輪で圧倒。

○ 6-2稀勢の里(寄り切り)碧山2-6 ●

稀勢の里右張って左差し、右上手引いて寄るが腰の重い碧山、右だけでは寄りきれない。結局左も下手を引いて、碧山が右おっつけで対抗するところ、両廻し引きつけて寄り切り。

大相撲2017年五月場所二日目

● 0-2北太樹(左肩透かし)里山2-0 ○

今日は左をすぐ差したが、北太樹右ギュウギュウに極める。北太樹小手から振り回して、右に全体重を掛けてねじ伏せようとするところ、里山左ひじを耐えながら膝が土俵に付くスレスレまで粘って、右で頭を押さえつけて左肩透かし。里山珍しく相手を睨みつけた。

見るだに怖かった。さすがに左ひじを気にしていたけれど、大怪我ではないようで良かった。

● 1-1(寄り切り)千代丸1-1 ○

突っ張りを反りながら止めて佐田の海右差し。しかし動きが止まり、佐田の海巻き替えるところ千代丸すぐに出て押し出し。

横綱

稀勢の里は1-1だが肝心の左が使えない。さすがに優勝争いまでは厳しいか。

日馬富士は連勝のいずれも良い相撲。出足鋭い。

白鵬の連勝は省エネ。初日は足がそろってちょっと危なかった。

鶴竜は連敗。間合いの妙が持ち味の横綱が、間合いの妙で負けてるので、調子は良くないんだろう。

大相撲2017年五月場所初日

当日券で入場。5:45に並んで整理番号312番のギリギリ。さすがに初日の客足は今場所が山だろう。

修学旅行の中学生らしい一団がワイワイにぎやかに観戦していて楽しかった。

● 照強(左肩透かし)里山

両者低く低く頭を下げあって手四つ。里山が左を差そうとするのを照強終始おっつけて許さない。里山右でひとつ押し上げて、ついに左がのぞいた!と見るやすぐさま左に開いて肩透かし。おみごと!

佐田の海(寄り切り)大砂嵐 ●

大砂嵐両手突きを佐田の海耐えて、大砂嵐に両差しを許したのも気にせず左上手引いて寄り立て、右外掛けで出した。

決まり手寄り切り。外掛け取ってほしかったな。

関東大震災時の朝鮮人・中国人虐殺への政府関与を否認する答弁に抗議します

産経新聞報道によれば、日本政府は、関東大震災の際の朝鮮人・中国人虐殺への政府関与について、「調査した限りでは、政府内にその事実関係を把握することのできる記録が見当たらない」とし、また「遺憾の意を表明する予定はない」とする答弁を閣議決定したとのことです。

同様の答弁は昨年(2016年)にも行われています。忸怩たることに、今まで知りませんでした。

不都合な歴史的事実を糊塗・否認しようとする、これら卑劣な答弁に抗議します。

まず、「記録が見当たらない」は明白な虚偽です。そもそも、有田議員の質問で言及されている『災害教訓の継承に関する専門調査会報告書』自体が「政府内」の「記録」です。また、同報告書は震災について多くの一次資料・二次資料を引いています。その中では、虐殺のきっかけとなったデマの流布に政府が関わった事例、虐殺に政府・軍が直接関わった事例も触れられています。その内のいくつかは、同時代の「政府内」の「記録」です(p. 191, pp. 207-209, pp. 209-210)。

この報告書を取り上げた質問に対して「記録が見当たらない」と言っているわけですから、これは「理解不能」とか「怠慢」とかいう次元の話ではなく、あからさまな虚偽の強弁です。同報告書は、今年の4月に内閣府のサイトから一時的に削除されて、虐殺に関する情報を隠蔽する意図があるのではないか、という疑念を呼びました。今回の答弁は、この疑念をあらためて深めるものです。

また、「遺憾の意を表明する予定はない」との答弁は、正義への挑戦であり、被害者に対する冒涜です。政府答弁は単なる叙述ではなく、政治的行為としての言語行為なのだから、ここで政府は「遺憾ではない」という立場を表明したわけです。悲しいです。

最後に、一連の政府答弁に、歴史を直視し、生かそうという姿勢がまったく見受けられないことを懸念しています。危機の際に社会の周縁に位置する人々が攻撃されることは、古今東西、社会集団の大小を問わず普遍的な事象です *1 。それが他人事ではない証左として、私が住んでいる関東平野には、100年前の虐殺の歴史が染み付いています。そこから目を背けないことは、今の私たちの責務だと思います。

*1:念のため、だからといって個別の迫害が免罪されるわけではありません。迫害は偶然的な出来事ではなく、日常的な不正義の爆発的な現れです。

伊勢参宮神乃賑

ようよう上がりましたわたくしが初席一番艘でございます。おあと二番艘に三番艘、四番艘に五番艘、御番僧にお住持に旗に天蓋、銅鑼に妙鉢、影灯籠に白張と申しますとこら葬礼の方で、てな具合にガチャガチャと始まりますのが上方噺の旅のお噂、「伊勢参宮神乃賑」、通称「東の旅」でございますが、わたくしは品川の宿から箱根の山を越えて、浜松名古屋を尻目に殺して、西へ西へのお伊勢参りでございます。その道中の陽気なこと!

宮巡り

初日に月夜見宮と外宮、二日目に月讀宮と内宮へと参りました。

外宮も内宮も拝殿がなく、本宮を拝むところには幕が張られていて、その先の垣根は門が閉まっていて、その先に本殿があって、裏には回れない。新約聖書の神殿の幕が裂けるシーンを思い出して、ははあ、となりました。

古市

内宮をお参りしたあと、お茶を飲んで赤福を食べて、ひとしきりゴロゴロしてからの帰り道、バスが「古市」の停留所に差し掛かりました。古市といえば昔の遊郭で、伊勢参りの旅人が精進落しに訪れて、ずいぶん繁盛したところだそうです。

思わず降りてひとめぐりしてみましたが、今はただの高台の住宅地で、集落の端っこの小さな資料館はもう閉館時刻を過ぎていました。

こんなもんかいなとブラブラして、唯一まだ営業しているという麻吉旅館に立ち寄ってみたところ、かつての妓楼のたたずまいをバッチリ残していました。

http://d.hatena.ne.jp/miyakawa_taku/files/2017-05-07_furuichi1.jpg?d=.jpg

http://d.hatena.ne.jp/miyakawa_taku/files/2017-05-07_furuichi2.jpg?d=.jpg

資料館は翌日に再訪しました。

言葉

伊勢のひとたちの言葉は、おおむね名古屋よりも大阪京都に近いようです。

ただ、バスの運転手さんは「お降りの方みえますか(いらっしゃいますか)」と言っていました。これは名古屋と同じです。

伊勢の雀は東京の雀よりもシュッとしていて首が長い気がしました。気がしただけかもしれません。

各言語のprintfはロケールに依存するか

言語やライブラリによっては、printf系関数の出力がロケールに依存する場合があります。たとえば、ロケールによっては小数点がカンマで出力される場合があります。

手元の各環境で調べたところ、次のとおりでした。

C (POSIX.1-2008, eglibc 2.19)

POSIXが定義するprintf関数の出力はロケールに依存します。

// printf.c
#include <stdio.h>
#include <locale.h>

int main(void)
{
    setlocale(LC_ALL, "");
    printf("%g\n", 3.14);
    return 0;
}
$ gcc printf.c -o printf
$ LANG=da_DK.utf8 ./printf
3,14

Java (Java SE 8)

Javaのprintf系メソッドの出力はロケールに依存します。ロケールは引数として明示的に指定することもできます。

public class Printf {
    public static void main(String[] args) {
        System.out.printf("%g%n", 3.14);
    }
}
$ javac Printf.java
$ LANG=da_DK.utf8 java Printf
3,14000

Golang (1.7.5)

Go言語のprintf系メソッドの出力はロケールに依存しません。

package main

// #include <locale.h>
import "C"
import "fmt"

const LC_ALL = 6

func main() {
    C.setlocale(LC_ALL, C.CString(""))
    fmt.Printf("%g\n", 3.14)
}
$ LANG=da_DK.utf8 go run printf.go
3.14

Python (2.7)

Pythonの%演算子の結果はロケールに依存しません。ロケールに依存した出力を行うためにはlocale.format関数を使います。

import locale

locale.setlocale(locale.LC_ALL, '')
print "%g" % 3.14
$ LANG=da_DK.utf8 python printf.py
3.14

Ruby (1.9.3)

Rubyのprintf系関数の結果はロケールに依存しません。マニュアルに明記はされていません。

require 'dl/import'

module Libc
  extend DL::Importer
  dlload 'libc.so.6'
  extern 'char *setlocale(int, const char *)'
end

LC_ALL = 6
Libc.setlocale(LC_ALL, '')
printf("%g\n", 3.14)
$ LANG=da_DK.utf8 ruby printf.rb
3.14

Lua (5.2.3)

Luaのstring.format関数の結果はロケールに依存します。ISO Cのsnprintfに従うものとして定義されています。

os.setlocale("", "all")
print(string.format("%g", 3.14))
$ LANG=da_DK.utf8 lua printf.lua
3,14

継続パズルyin-yangの回答

Shiroさんに教えてもらったyin-yang puzzleの回答。

課題のプログラムは次の通りです。

(let* ([yin ((lambda (foo) (newline) foo) (call/cc (lambda (bar) bar)))]
       [yang ((lambda (foo) (write-char #\*) foo)
              (call/cc (lambda (bar) bar)))])
  (yin yang))

以下ネタバレ。

let*をlambdaと関数適用に分解して、名前をわかりやすくすると次のようになります。

((lambda (yin)
   ((lambda (yang)
      (yin yang))
    ((lambda (yang*) (write-char #\*) yang*)
     (call/cc (lambda (cc) cc)) ; (B)
     )))
 ((lambda (yin*) (newline) yin*)
  (call/cc (lambda (cc) cc)) ; (A)
  ))

注目するべき点は、Bで捕捉される継続では、yinになんらかの値が束縛されている、ということです。実際には、AかBで捕捉される継続のいずれかが束縛されます。Bの継続が束縛されている場合、その継続ではyinになんらかの値、具体的にはAかBで捕捉される継続のいずれかが束縛されており、Bの継続が束縛されている場合、その継続では……。

Aの継続が呼び出されると、改行して、引数で渡された値がyinに束縛されます。

Bの継続が呼び出されると、その継続が捕捉された時点でのyinへの束縛が再現され、アスタリスクが出力され、引数で渡された値がyangに束縛されます。

ステップを追うと次のとおり。

1. (newline), そしてAの継続がyinに渡される。ここで名前環境を{yin=A}と書く。
2. (write-char #\*), そしてBの継続がyangに渡される。このBの継続において、上述したとおり、yinにはAの継続が束縛されている。これを{yin=A, yang=B{yin=A}}と書く。
3. (yin yang)を呼ぶということは、(A B{yin=A})を呼ぶということ。Aに戻って(newline), そしてyin*, yinにはB{yin=A}が渡される。{yin=B{yin=A}}
4. (write-char #\*), そしてyangにはBの継続が渡されるが、このBの継続において、yinにはB{yin=A}が束縛されている。つまり{yin=B{yin=A}, yang=B{yin=B{yin=A}}}。
5. (yin yang)は(B{yin=A} B{yin=B{yin=A}})。Bに戻るが、そのときyinにはAが束縛された状態。(write-char #\*)を呼んで、yangには(yin yang)の引数であるB{yin=B{yin=A}}が渡される。{yin=A, yang=B{yin=B{yin=A}}}。
6. (yin yang)は(A B{yin=B{yin=A}})。Aに戻って(newline), そしてyinにはB{yin=B{yin=A}}が渡される。{yin=B{yin=B{yin=A}}}。
7. (write-char #\*), そしてyangにはBの継続が渡されるが、このBの継続において、yinにはB{yin=B{yin=A}}が束縛されている。{yin=B{yin=B{yin=A}}, yang=B{yin=B{yin=B{yin=A}}}}。
8. (write-char #\*), {yin=B{yin=A}, yang=B{yin=B{yin=B{yin=A}}}}
9. (write-char #\*), {yin=A, yang=B{yin=B{yin=B{yin=A}}}}
10. (newline), {yin=B{yin=B{yin=B{yin=A}}}}
11. (write-char #\*), {yin=B{yin=B{yin=B{yin=A}}}, yang=B{yin=B{yin=B{yin=B{yin=A}}}}}
12. (write-char #\*), {yin=B{yin=B{yin=A}}, yang=B{yin=B{yin=B{yin=B{yin=A}}}}}
13. ...

Rubyで書き直すと次の通り。

require 'continuation'

def let(v, &block)
  block[v]
end

let(lambda {|foo| puts ''; foo }[callcc{|bar| bar }]) {|yin|
  let(lambda {|foo| print '*'; foo }[callcc{|bar| bar }]) {|yang|
    yin[yang]
  }
}