あなたが学ぶべき10のプログラミング言語
純粋関数型言語は当然学ばなければなりません。
副作用の分離とモナドによる抽象化は本当のプログラマーなら知っておくべきでしょう。
遅延評価のメリット・デメリットとそれを活かしたアルゴリズムも重要です。
- Scala
オブジェクト指向と関数型の機能を合わせ持ったマルチパラダイム言語のScalaを学ぶことは、あなたにとって新たな知見となるでしょう。
Twitterのインフラで使われるなど実績も十分で、現在のプログラマーにとっては当然のように使えるべき言語の1つです。
Haskellもまたそうですが、Scalaは型が強力なので型レベルプログラミングを学び、コンパイル時のエラー検出について考えてみるのもよいでしょう。
マルチコアのCPUが当たり前になった現在では、難しい並列処理をいかにして簡潔に実現するのかというのは非常に重要なテーマです。
Erlangは並列処理を念頭において開発された言語で、アクターモデルによる並列処理が特徴です。
アクターモデルによる新しい並列処理のアプローチは今後必ず重要になってくるので当然学ぶべきでしょう。
Rubyライクな記述のできるElixirを学ぶのもいいかもしれません。
HTML5が普及してWebアプリケーションの重要性増しており、JavaScriptの重要性もまた非常に高まっています。
プロトタイプベースのオブジェクト指向や、プロトタイプチェーンによる継承など、クラスベースのオブジェクト指向と違ったアプローチは学ぶ価値があるでしょう。
また関数が第一級のオブジェクトなので関数型のような記述も可能です。
関数型言語で学んだ知見はここでも多いに役立つでしょう。
歴史ある関数型のLISPやその方言のSchemeなどはプログラマーを名乗るのであれば書けて当然の言語でしょう。
S式による一貫した記法によってコードそものものを第一級のオブジェクトとして扱える柔軟性は他にはない素晴しいものです。
マクロによるプログラミングについても大いに学ぶことがあるでしょう。
歴史ある関数型言語MLから派生して生まれた、オブジェクト指向の機能を持った関数型言語です。
純粋な関数型言語のHaskellとはまた少し違ったアプローチのOCamlを学ぶことで、関数型言語に対する理解がさらに深まるでしょう。
- Coq
プログラムにはバグが付きものですが、バグを無くすにはどうすればいいでしょう。
テストを書けばテストケースに漏れがない限りはプログラムの品質を保証できます。
しかし、定理証明系のCoqを使えば、プログラムの動作を完全に証明することもできます。
テスト駆動開発、ビヘイビア駆動開発に続く、証明駆動開発について学ぶことは新しい知見となるでしょう。
- C++11x
Templateを使ったGenericプログラミングや、constexprによるコンパル時実行、型推論、ラムダ式など先進的な機能がたくさん詰ったC++は是非学んでおきたい言語です。
ある程度の規模の高速なネイティブプログラムを開発しようと思うとCでは非力すぎるため、多くの場合C++が最良の選択肢でしょう。
高速なネイティブプログラムが必要となる場面というのは未だ多く、学ばなければならない言語の1つでしょう。
Luaはプログラムに組み込んで使うこと目的として開発されたJavaScriptライクなスクリプト言語です。
言語として特徴的なのは途中で処理を止めて再開することができるコルーチンを持っている所でしょう。
スクリプト言語でありながら動作が非常に高速で、プログラムに組込むDSLとして最適と言えます。
例えばプログラムの設定ファイルの記述をLuaで柔軟に行なえるようにするなど、DSLを組込みこんだ設計というのは学ぶべき価値があるものです。
Ivy Bridgeで作るフェニックス3号
4/29にIvy Bridgeが出るのでその構成のメモ。
- CPU: Intel Core i7 3770S
- CPU Fan: Thermaltake Contac 30+
- M/B: MSI Z77A-GD55
- Memory: Corsair CMX16GX3M2A1600C11 (8GBx2)
- PSU: Corsair CP-9020006-JP (650W)
- HDD: Western Digital WD25EZRX (2.5TB)
- ODD: Pioneer BDR-207DBK
- Case: Abee smart J05
- Front 12cm Fan: Coolink SWiF2-1200
- Rear 12cm Fan: Noctua NF-P12 PWM
4/30 追記
爆熱という噂なので3770Sを買ったけど、定格ならアイドル時30度、ロード時45度で全く問題なし。
ちなみにチップセットの温度はアイドル時もロード時も32度。
Contac 30+の金具が何故かベタベタしていたのは謎。
smart J05の静音フィルターはオプションでいい。
そもそも無意味だし、すぐ傷つくし、あいつのせいで裏配線用の領域が狭くなる。
あと芯のケースファンがかなり煩さかったのでNF-P12 PWMに変更した。
Linux(X11)でKensingtonのExpert Mouse 7を使う
KensingtonのExpert Mouse 7(EM7)には4つボタンがあり、以下のようにレイアウトされています。
.----------. .---------. | 2:Middle | | 8:Back | `----------' `---------' .----------. .---------. | 1:Left | | 3:Right | `----------' `---------'
EM7にはスクロールホイールがないため、左上が中央ボタンで、右上が戻るボタンという変則的なレイアウトになっているようです。
このままでは使いづらいので、左上を戻るボタン、右上を進むボタンに設定します。ドライバはevdevを使ってxorg.confの該当セクションにButtonMappingを以下のように記述します。
Option "ButtonMapping" "1 8 3 4 5 6 7 9 2"
これで一般的な5ボタンマウスのレイアウトになりました。
.--------. .-----------. | 2:Back | | 8:Forward | `--------' `-----------' .--------. .-----------. | 1:Left | | 3:Right | `--------' `-----------'
注意すべきなのは、ButtonMappingでボタンのレイアウトを変えてもインデックスは変わらないという点です。
機能の割り当て
次に、各ボタンに機能を割り当てていきます。
EM7にはスクロールリングが付いていますが、ボタンを押しながらボールを転がすことでスクロールができるとより便利です。自分は、文章をじっくり読むときはスクロールリング、長いページから目当ての情報を探しだすときはボールでスクロールと使い分けています。ここでは、右上のボタン(8:Forward)をスクロールボタンに割り当てています。
Option "EmulateWheel" "true" Option "EmulateWheelButton" "8" Option "EmulateWheelInertia" "20" Option "XAxisMapping" "6 7" Option "YAxisMapping" "4 5"
続いて、先程ButtonMappingで潰してしまった中央ボタンを、左右の同時クリックに割り当てます。
Option "Emulate3Buttons" "true"
しかし、この設定だけでは意図した通り動作せず、実際には中央ボタンではなく戻るボタンが割り当てられてしまいます。
ここで一旦Emulate3Buttonsの動作を確認してみます。
- 左右の同時クリック検知する
- "ボタン2"が押されたというイベントを生成
- xf86PostButtonEvent()でイベントをポストする
ここで問題となるのが、xf86PostButtonEvent()がボタンの種類ではなくインデックスを取る点です。つまり、ButtonMappingでボタン2を別のボタンに置き換えてしまうと、Emulate3Buttonsで呼ばれるボタンもまた変化してしまいます。
これを修正するにはxf86PostButtonEvent()が呼ばれる前にMappingテーブルを走査して、中央ボタンが割り当てられたインデックスを探し出す必要があります。毎回テーブルを走査するのは無駄なので予めインデックスを格納しておけばよさそうですが、ButtonMappingはxmodmapなどでリアルタイムに変更できるので、それもまた問題があります。
とりあえず面倒なので、evdevのソースに中央ボタンを割り当てたインデックス"9"を決め打ちしました。以下にそのパッチを掲載します。
追記
ちゃんとしたパッチ書きました。
diff --git a/src/emuMB.c b/src/emuMB.c index 764b30e..287edc6 100644 --- a/src/emuMB.c +++ b/src/emuMB.c @@ -96,7 +96,7 @@ static signed char stateTab[11][5][3] = { { 0, 0, 0 }, /* nothing -> ground (no change) */ { 0, 0, 1 }, /* left -> delayed left */ { 0, 0, 2 }, /* right -> delayed right */ - { 2, 0, 3 }, /* left & right (middle press) -> pressed middle */ + { 9, 0, 3 }, /* left & right (middle press) -> pressed middle */ { 0, 0, -1 } /* timeout N/A */ }, /* 1 delayed left */ @@ -104,7 +104,7 @@ static signed char stateTab[11][5][3] = { { 1, -1, 0 }, /* nothing (left event) -> ground */ { 0, 0, 1 }, /* left -> delayed left (no change) */ { 1, -1, 2 }, /* right (left event) -> delayed right */ - { 2, 0, 3 }, /* left & right (middle press) -> pressed middle */ + { 9, 0, 3 }, /* left & right (middle press) -> pressed middle */ { 1, 0, 4 }, /* timeout (left press) -> pressed left */ }, /* 2 delayed right */ @@ -112,12 +112,12 @@ static signed char stateTab[11][5][3] = { { 3, -3, 0 }, /* nothing (right event) -> ground */ { 3, -3, 1 }, /* left (right event) -> delayed left (no change) */ { 0, 0, 2 }, /* right -> delayed right (no change) */ - { 2, 0, 3 }, /* left & right (middle press) -> pressed middle */ + { 9, 0, 3 }, /* left & right (middle press) -> pressed middle */ { 3, 0, 5 }, /* timeout (right press) -> pressed right */ }, /* 3 pressed middle */ { - { -2, 0, 0 }, /* nothing (middle release) -> ground */ + { -9, 0, 0 }, /* nothing (middle release) -> ground */ { 0, 0, 7 }, /* left -> released right */ { 0, 0, 6 }, /* right -> released left */ { 0, 0, 3 }, /* left & right -> pressed middle (no change) */ @@ -141,33 +141,33 @@ static signed char stateTab[11][5][3] = { }, /* 6 released left */ { - { -2, 0, 0 }, /* nothing (middle release) -> ground */ - { -2, 0, 1 }, /* left (middle release) -> delayed left */ + { -9, 0, 0 }, /* nothing (middle release) -> ground */ + { -9, 0, 1 }, /* left (middle release) -> delayed left */ { 0, 0, 6 }, /* right -> released left (no change) */ { 1, 0, 8 }, /* left & right (left press) -> repressed left */ { 0, 0, -1 }, /* timeout N/A */ }, /* 7 released right */ { - { -2, 0, 0 }, /* nothing (middle release) -> ground */ + { -9, 0, 0 }, /* nothing (middle release) -> ground */ { 0, 0, 7 }, /* left -> released right (no change) */ - { -2, 0, 2 }, /* right (middle release) -> delayed right */ + { -9, 0, 2 }, /* right (middle release) -> delayed right */ { 3, 0, 9 }, /* left & right (right press) -> repressed right */ { 0, 0, -1 }, /* timeout N/A */ }, /* 8 repressed left */ { - { -2, -1, 0 }, /* nothing (middle release, left release) -> ground */ - { -2, 0, 4 }, /* left (middle release) -> pressed left */ + { -9, -1, 0 }, /* nothing (middle release, left release) -> ground */ + { -9, 0, 4 }, /* left (middle release) -> pressed left */ { -1, 0, 6 }, /* right (left release) -> released left */ { 0, 0, 8 }, /* left & right -> repressed left (no change) */ { 0, 0, -1 }, /* timeout N/A */ }, /* 9 repressed right */ { - { -2, -3, 0 }, /* nothing (middle release, right release) -> ground */ + { -9, -3, 0 }, /* nothing (middle release, right release) -> ground */ { -3, 0, 7 }, /* left (right release) -> released right */ - { -2, 0, 5 }, /* right (middle release) -> pressed right */ + { -9, 0, 5 }, /* right (middle release) -> pressed right */ { 0, 0, 9 }, /* left & right -> repressed right (no change) */ { 0, 0, -1 }, /* timeout N/A */ },
これで左右同時押しが正しく動作するようになりました。
最後にxorg.confのEM7のセクションをまとめて掲載しておきます。
Section "InputClass" Identifier "Mouse0" MatchIsPointer "on" MatchProduct "Kensington Expert Mouse" Option "ButtonMapping" "1 8 3 4 5 6 7 9 2" Option "Emulate3Buttons" "true" Option "EmulateWheel" "true" Option "EmulateWheelButton" "8" Option "EmulateWheelInertia" "20" Option "XAxisMapping" "6 7" Option "YAxisMapping" "4 5" EndSection
rxvt-unicodeで半角カナが豆腐になる件
rxvt-unicodeでjisx0201なフォントを設定して半角カナを表示をすると、文字化けして豆腐になってしまう。
原因はsrc/table/jis0201_1976_0.hで定義されているunicodeをjisx0201にマップする処理がおかしいから。
これは以下のパッチで修正される。
--- a/src/table/jis0201_1976_0.h 2011-07-17 12:27:03.964003450 +0900 +++ b/src/table/jis0201_1976_0.h 2011-07-17 12:27:06.563003451 +0900 @@ -8,7 +8,7 @@ if (unicode <= 0x007d) return unicode; if (0x007f <= unicode && unicode <= 0x009f) return unicode; if (unicode == 0x203e) return 0x007e; - if (unicode <= 0xff61 && 0xff9f <= unicode) return unicode - 0xfec0; + if (unicode >= 0xff61 && 0xff9f >= unicode) return unicode - 0xfec0; return NOCHAR; }
tmuxでborderがまともに表示できない件
tmuxでTERMをscreenにして使うと、ncursesなどで使われるborderが"qqqqqqqq"の様になってしまう。
これは環境変数NCURSES_NO_UTF8_ACSを0に設定すると直る。
NCURSES_NO_UTF8_ACSの詳細はncursesのmanを参照。
tmuxで環境変数を設定するには以下のように書く。
set-environment -g NCURSES_NO_UTF8_ACS 0
さらに、tmux 1.4からは上記の設定してもborderが正常に表示できない場合がある。
理由はborderにvt100のline drawing charactersではなく、Unicodeの罫線を使うようになったから。
https://bitbucket.org/edogawaconan/tmux/changeset/2661dc9f9551
Unicodeの罫線は日本語のフォントだと全角なのでborderがずれてしまう。
そのため、パッチを書いてvt100のline drawing charactersを使う仕様に戻した。
diff -ur tmux-1.4.orig/tty-acs.c tmux-1.4/tty-acs.c --- tmux-1.4.orig/tty-acs.c 2010-09-19 00:43:53.000000000 +0900 +++ tmux-1.4/tty-acs.c 2011-05-21 16:26:44.263937939 +0900 @@ -81,7 +81,7 @@ struct tty_acs_entry *entry; /* If not a UTF-8 terminal, use the ACS set. */ - if (!(tty->flags & TTY_UTF8)) { + if (1) { if (tty->term->acs[ch][0] == '\0') return (NULL); return (&tty->term->acs[ch][0]); diff -ur tmux-1.4.orig/tty.c tmux-1.4/tty.c --- tmux-1.4.orig/tty.c 2010-12-07 06:57:56.000000000 +0900 +++ tmux-1.4/tty.c 2011-05-21 16:23:06.310937851 +0900 @@ -47,7 +47,7 @@ const struct grid_cell *, const struct grid_utf8 *); #define tty_use_acs(tty) \ - (tty_term_has(tty->term, TTYC_ACSC) && !((tty)->flags & TTY_UTF8)) + (tty_term_has(tty->term, TTYC_ACSC)) void tty_init(struct tty *tty, int fd, char *term)