マルチプラットフォーム版WTの開発は,Windows版のテストが完了した。次はAndroid版をテストしているのだが,Bluetoothキーボードがどうしても101キーボードとして認識されている。どうもキー入力を取得すると101のキーコードが来て,通常はIME側で106に変換しているっぽい。携帯だけならいいけど,raspberry pi版もあるのでどうしてもBluetoothキーボードに対応したい。ということで101->106変換を実装。
現状のWTでは101/106の2次元キー配列(1列分のキー×5段)を既に持っている。これを変換するマップを作ればいいわけで,普通に作ると2重のループで2次元配列のそれぞれを対応づけて,Dictionary<KeyCode, KeyCode>を作る感じ。こういう手続き型のコードはささっと書ける。
ただ,最近関数型言語を勉強していて,写像とか圏論に興味がある。なので関数型で書けないかな,って考えると,101キー集合から106キー集合への写像を作ればいいということなので,あえてLinqで書いてみた。んだけど慣れてなくてすごく分かりづらいものになってしまった。関数型に慣れてる人は簡単に書けるのかなあ。理解しづらいのは置いておいて,コンパイルできるようにするまでは大変なんだけど,書き終わって実行すると一発で動いた。このあたりは手続き型に対する関数型の強みになるのかな。
// KeyLine1をインデックス付きにする x.KeyLines.Select((xLine, i) => new { index = i, line = xLine.KeyTops }) // KeyLine2をインデックス付きにする .Join(y.KeyLines.Select((yLine, i) => new { index = i, line = yLine.KeyTops }), xLine => xLine.index, yLine => yLine.index, // indexが同じキー行でInner Join (xLine, yLine) => // KeyTops1をインデックス付きにする xLine.line.Select((xKey, i) => new { index = i, key = xKey.KeyCode }) // KeyTops2をインデックス付きにする .Join(yLine.line.Select((yKey, i) => new { index = i, key = yKey.KeyCode }), xKey => xKey.index, yKey => yKey.index, // indexが同じKeyTopでInner Join (xKey, yKey) => new { xKey = xKey.key, yKey = yKey.key })) // key1->key2のmapがキー行数分得られたので1次元配列にする .SelectMany(xLine => xLine) // キーとキーのDictionaryを作る .ToDictionary(item => item.xKey, item => item.yKey);
関数型言語だけど,元々Cマガの千言万語で興味があったのだが,最近いろんな言語で関数型言語的な書き方ができてきているので,Haskelを勉強してみた。で,やっぱりモナドで引っかかるので圏論を勉強し始めたのだが,むずい。群論とか線形空間とかの例はなんとなく分かるんだけど,位相空間とかになると分からない。と思っていたら丁度数学ガールの新刊で位相空間を説明していて助かった。