ふと、本の虫: C++0xの新機能、finalとoverrideを読み返してみたところ、深刻な誤表記が多数存在することを発見した。
派生というべきところで継承といっていたり、オーバーライドというべきところをオーバーロードといっていたり、その他色々と誤変換も多い。困ったものだ。今書いている本にも、どれほど誤表記が混じっているものやら。
ふと、本の虫: C++0xの新機能、finalとoverrideを読み返してみたところ、深刻な誤表記が多数存在することを発見した。
派生というべきところで継承といっていたり、オーバーライドというべきところをオーバーロードといっていたり、その他色々と誤変換も多い。困ったものだ。今書いている本にも、どれほど誤表記が混じっているものやら。
ここ数年ほど、まともにデバッガを使ったことがない。そもそも、プログラムらしいプログラムを実行したこともない。というのも、今必要な能力が、規格を理解して説明することだからだ。プログラムの実行というのも、コンパイラーのpartial orderingやオーバーロード解決が正しく行われているかどうかの確認の意味合いぐらいでしか、やっていない。
C++0xの実装では、gccが他のコンパイラーより進んでいる。
gccは、週間スナップショットをのビルドを、ここから手に入れて使っている。自前でビルドするのが面倒なのだ。
ところが、このバイナリの問題なのか、あるいはgccのiostream自体の問題なのか、なぜかiostreamを使おうとするとクラッシュする。とりあえず問題になるのは、以下のようなコードだ。
std::cout << 0 ; std::cout << std::endl ;
どうも、数値やらendlやらを食わせると、クラッシュしてしまう。理由がわからない。
どうやら、いいかげんにgcc環境でのデバッガを触ってみたほうが良さそうだ。そこで、GDBを使ってみた。
ステップ実行していくと、最終的に、 __gnu_cxx::__default_lock_policy()という関数の中で、以下のようなエラーがでる。
Cannot access memory at address 0x0
∧_∧ ( ´∀`)< ぬるぽ
うむ、さっぱり分からん。しかし、こんなコードでクラッシュするのならば、もっと問題になっても良さそうなのだが、さっぱり話題になっていない。なにか私の環境がおかしいのだろうか。まあ、iostreamなど、日本語には何の役にも立たないから、どうでもいいのだが。
gcc 4.7は、finalとoverrideを実装している。
finalとは、クラスの派生と、virtual関数のオーバーライドを禁止するための機能である。
struct B final { } ; struct D : B { } ; // エラー struct C { virtual void f() final { } } ; struct D : C { void f() { } // エラー、C::fはオーバーライドできない } ;
これ以上説明する必要がないくらいに分かりやすい機能だ。現実的には、最底辺の基本クラスのvirtual関数のオーバーライドを禁止にするということはない。なぜならば、それは普通の関数とほぼかわりないからだ。あえて言えば、派生クラスで、同じシグネチャの関数を定義できなくする程度の意味しかない。大方、以下のような目的に使われるだろう。
struct A { virtual void f() = 0 ; } ; struct B : A { // 最終的な実装 virtual void f() final { /* 実装 */} } ; // Bからは、まだ派生できるが、オーバーライドはさせない。 struct C : B { } ;
overrideは、「俺はオーバーライドするぞジョジョッ!」と明示的に叫ぶための機能である。overrideを指定しておきながら、実際にオーバーライドをしていないvirtual関数はエラーとなる。
struct Base { virtual void hoge() { } } ; struct Fail : Base { void hage() override { } // エラー、オーバーライドしていない } ;
よくみると、Failのメンバー関数の名前は、hogeではなくhageになっている。そのため、hageは関数をオーバーライドしない。よってエラーとなる。
ご存知のように、virtual関数をオーバーライドするさいには、virtualキーワードは必要ない。しかし問題は、名前を間違えたり、仮引数や戻り値の型を間違えたりすると、別の関数になってしまう。
struct Base { virtual void func(int) { } } ; struct Fail : Base { // Base::hoge()をオーバーライドしたい void fucn(int) ; // 名前間違い void hoge(long) ; // 仮引数の型間違い } ;
コンパイラーは喜んでこのコードを受け取り、別の関数として解釈してしまう。コンパイルエラーにならないのはもちろんのこと、警告を発するのも難しいのだ。たとえvirtualキーワードを使っていても、問題は変わらない。普通の関数ではなく、新しいvirtual関数を導入するだけだからだ。
間違いを防ぐためには、オーバーライドするということを明示的に示さなければならない。overrideはそのためのキーワードである。
完全を期すために付け加えると、finalとoverrideを組み合わせることもできる。
struct B { virtual void f() = 0 ; } ; struct D : B { void f() final override { } } ;
意味はもちろん、finalとoverrideの両方である。
この新機能は、純粋にコンパイル時の些細なエラーを見つけやすくするための機能である。
この便利な機能がここ至るまでには、かなりの紆余曲折を経ている。そもそも、この機能はもともと、attributeを使って実現されるはずだったのだ。
// C++0xでは却下された機能 struct B { virtual void f() = 0 ; } ; class C [[final]] { [[final, override]] void f() { } } ;
しかし、色々と議論した挙句、標準機能は独自のキーワードを与えられてしかるべきだというコンセンサスが得られた。しかし、一体どんなキーワードを使えばいいというのか。キーワードの追加は、互換性の敵である。既存のコードで使われていない識別子を選ぶ必要があるが、あまりに変な名前では、意味が分からない。finalというのは、他の言語の同等機能に与えられているキーワードである。しかし、さすがにfinalなどというキーワードを今更C++に付け加えることはできない。既存のコードを破壊してしまうからである。
苦渋の末、標準化委員会は、Contextual Keywordを使う決断をした。これは、ある特定の文脈で現れた時のみ、意味をなすキーワードである。
たとえば、C++の文法上、クラス指定子のクラス名の後に識別子が来ることはない。
class Name /*ここに識別子は使えない*/ : Base { } ;
とすれば、その場所だけで有効なキーワードを作ることができる。これは文法全体には影響しないので、finalという識別子は、他の場所では問題なく使える。
struct final final { } final ; struct X final { } ;
本来、この機能にはもう一つ、hidingというキーワードが加わるはずだった。これは、attributeからcontextual keywordに移行するときに、newを再利用することになった。そして、最後の最後になって、ドラフトから削られた。
このhidingは、名前を隠すということを明示的に主張する機能である。
struct A { int value ; void f( int ) ; } ; struct B : A { int value ; // A::valueを隠す void f( double ) { } // A::fを隠す } ; int main() { B b ; b.value = 0 ; // b.B::balue b.f( 0 ) ; // b.B::f }
この、派生クラスのスコープが基本クラスのスコープ内の名前を隠すという挙動は、時として不思議な結果を招くことがある。また、うっかりして基本クラスのメンバーを隠してしまわないとも限らない。そのため、隠すということを明示的に主張するための、hidingが、finalやoverrideと同時に提案された。hidingが指定された名前が、実際には何も隠していない場合は、エラーとなる。
// C++0xでは却下された機能 struct A { int value ; } struct B : A { int vlaue new ; // エラー } ;
B::vlaueは、typoである。単純な間違いだが、現実に起こりうる間違いである。しかもコンパイラーは警告を発することができない。hidingは、overrideと同じように、明示的な隠す主張を行えるようにした。
また、このoverrideとhidingを明示的に使わなければエラーとなる、explicitも提案された。
// C++0xでは却下された機能 struct A { int value ; virtual void f() = 0 ; } ; struct B explicit : A { int value ; // エラー、newが指定されていない void f() { } // エラー、overrideが指定されていない } ;
何が問題だったかというと、hidingは、文法上、かなり広範な範囲で起こるのだが、既存の文法を虱潰しに対応させるだけの余裕がなかったのである。たとえば、using宣言が関係する場合はどうなるのか。
struct A { void f(int) ; } ; struct B : A { using A::f ; void f(double) ; } ;
この場合、名前は隠されていない。しかし、using宣言で名前を隠すこともできる。
struct A { void f(int) ; } ; struct B { void f(double) ; } ; struct C : A, B { using A::f ; // B::fを隠す }
この機能が提案されたのは、規格がほぼ固まった後であり、到底対応する時間はなかった。また、hidingのために、newキーワードを再利用するというのは、あまり賛同を得られなかった。結局、色々と議論した挙句、今、早急にhidingを言語仕様に取り入れるのは、将来のためによろしくないと結論した。そこで、hidingが取り除かれ、それに関連して、explicitも取り除かれた。なぜなら、hidingなしでexplicitだけあっても、片手落ちであるし、将来hidingを取り入れた時に、深刻な互換性の問題を引き起こすからである。
色々あって、本来の機能の半分以上がそがれてしまい、finalとoverrideだけが残ったのである。
A gay teen describes her experience at a Utah brainwashing facility : troubledteens
モルモン? 同じキリスト教である。創価学会と仏教が同じようなものだ。信長は正しいことをした。
BBC Site Uses Cookies To Inform Visitors of Anti-Cookie Law - Slashdot
EUは、俗称アンチクッキー法と呼ばれる、クッキーの利用を制限する法律を、5月25日から施行した。
イギリスのテレビ会社、BBCのウェブサイト、Radio Timesでは、これを受けて、26日より法律に対応した。最初にサイトを訪問した際、クッキーを使用していいかどうかを尋ねるのだ。
ここでクッキーの使用を拒否すると、クッキーは使用されない。ただし、二度目以降にサイトを訪問した場合、たとえクッキー使用を拒否しようと、このメッセージは表示されない。何故か。クッキー使用に同意したか拒否したかを、クッキーを使って記録しているからだ。
これは、技術を理解しない者の手によって法律が書かれたために起こる悲劇である。
そもそも、クッキーとは、クライアント側のソフトウェアが提供している機能である。クッキーの使用が嫌ならば、ブラウザーのクッキーの機能を無効にすればいい。ほとんどのブラウザーは、クッキーを無効にするためのオプションを提供している。
日本のアンチウイルス法も、同じ道をたどるのだろうか。
追記:slashdotのコメントによると、EUのアンチクッキー法は、トラッキングクッキーのみを禁止しているのであって、セッションクッキーや、ウェブサイトの利用に必要なクッキーの利用まで制限しているわけではないという。しかし、クッキーはあくまでクッキーであって、技術的には何も違いはないのだ。トラッキングクッキーと、ウェブサイトの利用に必要なクッキーとの技術的な違いは何もないのだ。EU圏の考え方は分からん。
効率よく絵が上達する方法 人体の構造を理解することは萌え絵上達への近道 | お絵かき速報!萌え絵上達法
上記スレを読んでいて、以下のレスが気にかかった。
ルーミス pdfでぐぐれ、違法サイトでもなんでもない
ルーミスは50年以上前に死去した人物なので
著作権関係が失効しているんだよ
アンドリュー・ルーミスは1959年になくなった。したがって、日本国内では、原書の著作権は2010年に失効しているといいたいのだろう。
しかし、おそらく違うはずだ。日本国内では、まだ一部の著作物の著作権が存続しているはずである。彼の著作は6冊ある。
このうちの、最初の3冊の著作権は、日本国内ではまだ存続しているはずだ。何故ならば、戦時加算があるからだ。ルーミスはアメリカ人であり、著作物はアメリカ合衆国で公開されている。一部の著作物は、終戦前に公開されている。これは戦時加算の対象になる。ということは、
1939年に公開されたFun with a Pencilの著作権は、2020年5月22日(3794日)まで、
1943年1月1日に公開されたFigure Drawing for All It's Worthの著作権は、2019年4月29日(3405日)まで、
1947年(日付不明、仮に1月1日で計算)に公開されたCreative Illustrationの著作権は、2015年の4月29日(1944日)まで、
著作権が存続しているはずである。
後の3冊は著作権が切れている。Successful Drawingは戦時加算が483日しかないので、2011年4月29日に著作権が切れているはずだ。あれ、つい先月なのか?
戦時加算に暦年主義が適用されないというのが、また計算しづらい。
終戦前に公開されて、作者が終戦後に死んだ著作物の著作権の保護期間は、不平等な戦時加算という仕組みのせいで、実に違和感がある。我が国は未だに敗戦国のなのだ。
高木浩光@自宅の日記 - ウイルス罪法案、バグ放置が提供罪に該当する事態は「ある」と法務省見解
政府は、バグ放置が罪せらるとの見解を発表した。また一歩、日本が後退した瞬間である。
そもそも、放置とは何を言うのか。大部分のソフトウェアのバグフィクス、特にセキュリティに関するバグというのは、バグ発見者の善意によってなりたっている。バグを発見したものが、ソフトウェアに対して責任をもつ会社または個人に、秘密のうちに連絡をとり、バグの内容を伝える。責任者は、秘密裏のうちにバグを直し、アップデートパッチを公開する。バグの具体的な内容が公開されるのは、パッチ公開後である。この過程を経ずしていきなりバグが公になることを、ゼロデイという。ゼロデイは、マルウェアが未知のバグを利用していたり、またバグ発見者が、何らかの理由によって(たいていは、無責任な責任者にあきれて)、いきなり公開したりすることで起こる。
バグの修正には、時間がかかる。バグ自体を治すのは、数行のコードの修正で済むかもしれない。しかし、修正が正しく動くかのテストや、パッチをユーザーに適用させるまでには、相当な時間がかかる。そのため、常にはそういう風にバグフィクスが行われるのだ。
このパッチを準備している間は、バグの具体的な内容について言及しないので、はたからみれば放置に見える。しかし、果たして放置なのだろうか。アップデートを用意する前に、バグの内容を公開するのは危険なのだ。
おそらく、この判断の根底にあるのは、まことに日本の公務員的発想なのだろう。つまり、「ソフトウェアは、いかにマヌケなユーザーによって操作されたとしても、決してユーザーの意図に反する挙動をしてはならない」という幻想を持っているのだ。これには先例がある。日本の警察はこの信念を持って両刃の刃物を禁止した。それ、プログラミングは魔法か。
このような人種が、パスワードを失念したために、暗号化ソフトウェアによって暗号化されたファイルを復号化できないと文句をつけるのである。
ことここに至れば、プログラミングが認可制になるのは、そう遠い話ではないだろう。プログラマーは国家試験を通って国家資格を手に入れなければ、プログラミングできなくなるのだ。また、ソフトウェアは、公開される前にかならず国の認可を必要とする。
国家試験の出題範囲は、CASLとCOBOLになるだろう。ソフトウェアの認可にあたっては、極めてリテラシーの低い公務員に対して、いかに我がソフトウェアは安全かということを、お題目のように唱え続けなければならない。時には、袖の下を通したり、公務員OBを雇用したりなどの便宜をはかることが必須となるだろう。
そのような未来において、我々プログラマーはお互いを同志と呼び合い、プログラミング作業はすべてテレスクリーンで監視され、二分間憎悪で偉大なる伝説のプログラマーを褒め称え、テレスクリーンは我が国のソフトウェアのバグ率が0%であることを誇らしげに報道するだろう。
およそ公務員のリテラシーは低い。私はかつて、公務員を目指すものが多く集まっているところで、「プログラミングとは何ぞや」という質問を受けた。私は、「MS WindowsやMS Office、あるいはゲームや携帯電話の画面に表示されているものに至るまで、すべてはソフトウェアによって制御されている。プログラミングとは、ソフトウェアを作るための作業である」と説明した。しかし、彼らは依然として、首を傾げるのである。
今や、車やバイクですらソフトウェアによって制御されているのに、何故彼らはプログラミングとは何かという根本的な概念すら理解できないのか。
文書をメールで送るために、Excelを方眼紙替わりに使い、ケータイのデジカメで画面の写真をとり、画像をメールに添付して送るは、それ公務員なり。
Bug 49122 – [C++0x] initializer_list is broken
なかなか興味深い。
initializer_listには、明示的なコンストラクターがない。initializer_listのコピーは、内部的な要素をコピーしないと明言されている。
initizalizer_listの実装というのは、ポインターが想定されている。例えば以下のようなコードに対しては、
std::initializer_list<int> list = { 1, 2, 3 } ;
以下のような実装になる。
int a[3] = { 1, 2, 3 } ; // 実装依存の方法で、配列aの要素へのポインターを保持するinitializer_listを生成
とすれば、以下のコードが動かないのも、当然と言える。
std::initializer_list<int> f() { std::initializer_list<int> list = { 1, 2, 3 } ; return list ; }
何故ならば、関数が返したinitializer_listの内部的なポインターは、もはや妥当なメモリを指し示していないからだ。
というわけで、関数の戻り値の型として使いたければ、std::arrayやstd::vectorなどのコンテナーを使うべきだろう。
退社報告 | 高橋名人公式ブログ 16連射のつぶやき | 高橋名人 OFFICIAL SITE 16SHOT
まあ、ハドソンは最近落ち目だったし、ゲームと言っても、桃鉄ぐらいしか売れるものがなかった。あとは、ケータイ用の粗悪なゲームばかり。結局、コナミに買収されてしまった。第一、コナミからして、粗悪なキャラゲーばかり乱発している会社ではないか。本物のゲームを作った試しがない会社である。
結局これも、ひとつの時代が終わったということだろう。当時の貧弱なハードで、なんとかゲーム性をだそうとすると、ひたすら手動で、総当りをさせたり連打させたりするようなゲームになるのも、当然と言える。また、まだアーケードゲームの影響が濃かった自体で、家庭用ゲームでも、クレジットという概念があった時代だ。残機というのも、金を投入する都合上、設けられたものだ。
それを考えると、現代のゲームは、人に優しくなった。死ぬと最初からやり直しということもなくなり、ライフは自動回復するようになった。ただし、また変な方向に進んでしまったと思う。
ひとつはキャラゲーだ。とりあえず有名な漫画やアニメ、はては芸人やスポーツ選手などの名前を買ってきて、それで愚にもつかぬゲームを乱発するようになったのだ。無論、当時とて、そういう傾向がなかったわけではないが、近年ますますひどくなるばかりだ。
もうひとつは、ゲームと映画を勘違いしているということだ。いつの頃からか、ゲームは動画を多用するようになった。ここでいう「動画」の定義とは、プリレンダリングにしろ、リアルタイムレンダリングにしろ、ユーザーの入力を受け付けず、ただ決められた映像を流すだけのことをいう。本物のゲームとは、ユーザーの入力に応じて出力の変化が起こる装置である。動画を垂れ流すだけの装置を、私は本物のゲームとは認めない。
最近、本物のゲームが少なくなった。今年発売される予定のゲームで期待しているのは、BethesdaのThe Elder Scroll: Skyrimと、Bethesdaに買収されたid SoftwareのRageだが、果たして期待通りのゲームなのかどうか分からない。E3が楽しみだ。その前に、新しいPC(せめて、新しいGPU)を買わなければ、このゲームが動かせないのだが。
sleep sortの仕様:4chan BBS - Genius sorting algorithm: Sleep sort
以下、実装。コンパイルすら通していないので、正しく動くかどうかは不明。C++0x準拠のSTLが欲しい。
#include <iostream> #include <vector> #include <thread> #include <chrono> // 個々の要素のソート、というか表示遅延 void sort_element( unsigned int elem ) { std::this_thread::sleep_for( std::chrono::duration<unsigned int>( elem ) ) ; std::cout << elem << std::endl ; } // イテレーターの参照結果はunsigned int型に変換できる型であること template < typename Iterator > void sleep_sort( Iterator first, Iterator last ) { std::vector< std::thread > v ; for ( ; first != last ; ++first ) { v.emplace_back( sort_element, static_cast<unsigned int>( *first ) ) ; } for ( auto & t : v ) { t.join() ; } } int main() { std::vector<unsigned int> v = { 5, 3, 6, 3, 6, 3, 1, 4, 7 } ; sleep_sort( v.begin(), v.end() ) ; }
このプログラムの実行には、少なくとも7秒かかる。
追記:iostreamは、多分スレッドセーフじゃない。スレッドセーフにも色々な強さがあるが、どのような順番で出力されるかは、分からない。したがって、完全を目指すならば、何らかの方法で出力をシーケンスさせる必要がある。
しかし、このプログラムでは、待ち時間の最小単位が1秒である。1秒というのは、多くの実行環境で、処理が完了するのに十分な時間である。sleep sortが大抵の場合で動く理由は、そこにあるのだ。
以下のコードで、生成されたファイルを実行するとクラッシュする。
#include <iostream> int main() { std::cout << std::endl ; }
どうもstd::endlをストリームに食わせようとするとクラッシュする模様。今使っているweeklyビルドの問題なのか、gccの問題なのか。
このブログ記事に書かれている内容は、アイロニーだらけである。
つまりだ。俺は英語を書いてるわけだ。
他の言語も覚えようとしてるんだけどさ、英語こそが、俺の一番得意な言語なわけだしさ。
もし英語の知識とやらが、正しい文法とかスペリングだと言うのなら、そもそも俺だって、英語ができないということになるかもしれん。
まあ、それはさておく。エラーメッセージをローカライズすべきかどうかというスレタイのスレで、こんなレスつけたやつがいた。
エラーメッセージはローカライズされるべきじゃないし、分かりやすくあるべきでもない。
エラーメッセージというのは、共通の言語を使うべきだ。たいていは英語だ。一般的に言えば、開発チームの使ってる言語だ。そうすれば、そのAPIを使う開発者は、インターネットでテキストを調べることができる。フランス人の開発者が、フランス語のエラーメッセージを得たところで意味がない。
エラーメッセージというのは、開発者は理解できるが、実行環境の詳細は漏らさない形で書かれるべきだ。単なるユーザーに対して、エラーメッセージを表示すべきではない。つくっているものがAPIフレームワークで、ユーザーというのが開発者である場合はともかく。
このコメントには、マイクロソフトのレドモンドの悪習がふたつある。とくに、最近のマネージドコードにあるわけの分からんエラーメッセージに共通する悪習だ。
- 読みやすく、理解しやすいエラーメッセージは邪悪であるという掟
- 「ネットで探せ」というのが、エラーメッセージに英語を使う理由であるという掟
このアホくさいクソな悪習に賛同する奴は、根本的な問題を分かってない。たとえ英語ネイティブであろうと、英語で書かれているものがすべて理解できるわけではないし、そもそも、まともな開発スタイルでもない。ユーザーの手を縛り上げるようなiPhoneアプリケーションは、iPhoneの利用の妨げになるのと同じだ。
開発者の心得:インターネットでエラーメッセージを探すのは、「エラーメッセージが理解出来ないから」である。どんな言語を使っても同じだ。
世界には大勢の開発者がいる。英語が分からない者も大勢いる。英語を学ぶ者も大勢いる。どの程度、英語ができるようになるかは、人それぞれである。本文で使われているようなとんでもない方言だってあるのだ。大抵は、英語を学ぶのにとても苦労しているので、代わりに別の言語を学ぶ。例えばC#とか。そういう人間には、英語より、フランス語とか日本語の資料でC#を学んだほうが、仕事を見つけるのが楽なのだ。
英語を学んだ者は、英語で情報を得ることができるが、だからといって、英語を理解しないものより優れているとは限らない。だから、そういう堅苦しい問題よりも、より多くの開発者を集めることに労力を割くのだ。
英語を話し、英語限定のソフトウェアを作っている開発者よ。英語に流暢な人間であっても、お前の書いたものが理解出来ない奴は必ずいる。物事を他人に伝えるという能力が如何に劣っているかを自覚しろ。そういう態度を改めることこそが、分かりやすいソフトウェアを作ることにつながるのだ。
英語を話すということは素晴らしいことだ。ある国では、英語が分かるということは、仕事を見つけるために必須である。しかし、ある言語習得が必須である理由というのは、他の国の開発者だって同じだ。
結局、物事をより広く、便利に提供するということは、何の害もないのだ。
しかしまた同時に、英語が分からない人間に物事を理解させるというのは、恥ずべきことではない。ぶっちゃけ言うと、奴らに英語を強制させるほうが恥ずべきことじゃないのか?
そんなわけで、.Netフレームワークを使う開発者で、世の中のプログラミング作業を簡単にしたいのならば、自分の制作物の使用に際して、英語を強制させないという選択肢を取れるわけだ。
あるいは、アホになるかだ。
どっちでもいいけど。
本文で最大のアイロニーは、当然、本文がすべて英語で書かれているということである。私の能力上の都合で、私は読者に英語を強制しているわけだ。でも、お前らは俺よりうまくやることだってできるさ。
この英語は翻訳しづらかった。理由は、一文が長いためだ。
Javascript PC Emulator
Javascript PC Emulator - Technical Notes
これは、QEMU作者による、Javascriptで書かれたPCエミュレーターである。その上で、Linuxカーネルを動かしている。どうも、Chrome 12では、バグにより動かないようだ。Firefox 4なら問題なく動く。にわかに信じがたい。
技術メモを読むとわかるが、これはかなり限定的なエミューレションである。しかし、Linuxカーネルを動かすには十分である。
エミュレートしているのは、主に以下のチップである。
エミュレートされているx86 CPUには、FPUがない。しかし、LinuxにはFPUエミュレーションがあるので、問題ない。
もちろん、viやemacsも起動するし、TinyCがあるので、なんとC言語によるプログラミングも可能である。
まえに、Javascriptで書かれたファミコンエミュレーターをみたとき、誰かがx86エミュレーターも書くんじゃないだろうかと予想した。まさか、こんなに早く、実物を目にするとは思わなかった。
ところで、JavascriptにTyped Arrayというドラフト規格ががあることを初めて知った。これは良さそうだ。
コンピューターのハードの中で、最も進化が遅いのは、ディスプレイである。ディスプレイ解像度やPPIは、なかなか上がらない。
ところで、サムソンが興味深い発表をした。
なんと、10.1インチでWQXGAの液晶パネルらしい。PPIは300ほどらしい。ただ、どうもこれはPenTile RGBWパネルで、300PPIというのも、サブピクセルを数えているらしい。もしそうだとすると、詐欺臭いスペックだ。
私は、今使っているものより高性能なディスプレイが欲しい。まず、300PPIはほしいし、大きさも24インチほどはほしい。問題は、そのようなパネルを開発できたとしても、その解像度に対応するケーブルが、現時点ではないということだ。帯域という点からみても、限界なのだろう。しかし、解像度があがれば、別にRGBでなくてもいいのではないだろうか。ビデオカードは、YCbCrで出力することを真剣に考えるべきではないだろうか。4:2:0で出力すれば、帯域は4:4:4の半分になる。ただ、それでも300PPIで24インチとなると、ディスプレイポート換算で5本ほどは必要になってしまうのだが。
投げ銭が送られてきたので、CPUクーラーを買うことにした。ネット上で買っても発送に数日かかるし、CPUクーラーは、価格.comでも、それほど極端に安いものはない。久しぶりに寺町に行くことにした。しかし、寺町もずいぶん寂れたものだ。京都に引っ越してきた7年前は、まだもう少しPCショップがあったと思うのだが、だいぶ潰れてしまった。もっとも、秋葉原でさえ、もはや電気街の体面を保てなくなっているのだから、時代の流れだろう。
空冷のCPUクーラーというのは、ファンとヒートシンクから成り立っている。今回壊れたのはファンだ。したがって、ファンだけ交換すればいいのではないかと考えた。しかし、どうやらCPUクーラーというのは通常、ファンとヒートシンクが一体化されているらしい。そのため、CPUファンだけというのは、なかなか売っていない。
普通のCPUクーラーの値段は、どれも数千円である。ただし、普通というのが、かなり変わっている。どのCPUクーラーも、ヒートシンクがやたらに大きく、ゴテゴテとしたヒートパイプがニョキニョキと複雑に交差している。あるいは、ロープロファイル用の極端に小さなクーラーになる。これも、やはりヒートパイプが複雑に走っている。あるいは、CPUに接する部分と、ヒートシンクとが、ヒートパイプで接続されただけで、完全に独立しているようなものもある。リテールクーラーのようなシンプルなヒートシンクが見当たらない。
考えてみると、CPUクーラーをわざわざ別個に買う人間というのは、大抵、バルク品のCPUを買ったか、リテールクーラーに満足できない種類の人間である。購入層がそういう人種である以上、製品もその要求を反映するのは当然といえよう。
それにしても、手動でファンの回転数を調整できる機能など、誰が必要としているのか。ショップ店員によると、主に、ファンの回転数を制御する機能を持たないマザーボードのためなのだという。今時、そんなマザーボードがあるのだろうかと疑問に思ったが、たくさんあるらしい。
ともかく、値段としては、どれも大差がないので、店員と相談したあげく、売れ筋の製品を買った。
さて、取り付けるのは、覚悟していたが一苦労した。なにしろせまい。作業しながら、マザーボードをケースから取り外したほうが、結局手っ取り早かったのではないかと後悔した。
大変な苦労の末、CPUクーラーを取り付けた。早速起動してみる。ファンは問題なく回転している。CPU温度も、BIOSの報告を信じる限り、問題ない。いや、むしろかなり温度が低い。ファンもヒートシンクも巨大なためだろう。しかも恐ろしく静かである。なるほど、最近のPCの騒音は、CPUファンによるものだったのだな。
これは悪くないと、ひとしきり満足したところ、いきなり画面が消えた。不思議に思って再起動すると、やはりしばらくして画面が消える。どうしたことかと調べてみると、どうもGPUファンが回っていない様子だ。三度目に起動しようとすると、BIOSのPOSTエラーがビープ音で再生される。一体どうしたことだろう。CPUファンを取り付ける際にうっかり壊してしまったのだろうか。それにしても、ファンが回らない壊し方というのは解せない。
しかたなく、GeForce GTX260を取り外し、昔使っていた、GeForce 8600GTSを取り付けた。GPUのファンは正常に回転しているのを、念のため確認した。最近はゲームもしないし、とりあえずは問題ない。ドライバーのインストールに、しばらく時間がかかった。
結果として、静音PCが出来上がった。HDDの音しか聞こえない。
さて、とりあえずは安定しているようだが、どうも信頼がおけない。バックアップは常にとりつつ、C++参考書の執筆を急ごう。いいかげんに新しいPCがほしいが、金がないのはもとより、どうも今は時期が悪いように思われる。もちろん、いつだって時期が悪いのだが。
急にPCから異音がしたので、ケースを開けて検証したところ、CPUファンの回転が、明らかに遅いことを確認した。一旦電源を落とし、もう一度電源を入れてみると、CPUファンが回らなくなった。ああ、CPUファンが逝ってしまったようだ。
とりあえずworkaroundとして、普通の扇風機の風を横からあててみた。アイドル時でも、CPU温度が以前より5℃ほど高いが、とりあえずは安定している。
しかし困った。CPUファンというものは、それ単体では売っていない。大抵はヒートシンクとセットになっている。これが、結構高い。数千円はする。今の懐具合では、相当に痛い。
少し前に電源が壊れたので取り替えたばかりだというのに、また新たに故障した。無理もない。このPCは、もうかれこれ4年は使っているのだ。そろそろ寿命なのだろう。
しかし、もし他の、簡単に交換が効かない部分が壊れてしまえばどうしようもない。例えば、マザーボードが壊れてしまえばだいぶやっかいだし、HDDが壊れると、これまでに構築した環境がなくなってしまう。新たにPCを買う金はない。C++の参考書の執筆もできなくなる。さて、困った事だ。
そろそろ、真剣に仕事を探し始めなければならない。いろいろと工夫してみたが、どうも参考書の完成まで、金がもちそうにない。とはいえ、C++の参考書が、片手間で執筆できるとも思えない。やれ難儀だ。
しかし、果たして本という形態が、今の時世にあっているのだろうか。本の執筆を始めるまでは、このブログはC++記事を多く提供できていた。しかし、本の執筆を初めてからというもの、有益なC++の記事はほとんどない。執筆に忙しく、ブログを書く余裕がないからだ。
結果的には、片手間でブログを書いていたほうが、有益なC++の情報を提供できていたのだ。当時は、バイトもしていたし、クソの役にも立たない専門学校にも通っていた。その当時の方がよっぽど有益な情報を提供できていたのだ。
それが、本を書くということで、この二年、ほとんどC++の規格だけを検証してきた。そのため、今の私のプログラミングの知識は、実務的なプログラミングから、だいぶ離れてしまっている。だから、今からプログラミングの仕事というのは、望めないだろう。私のプライドがC++を正しく理解していない職場に甘んずることを、断固拒否するであろうし、かといって、実務的なプログラミングに要求される、C++言語以外の知識が伴っていないのだ。
C++の参考書の執筆中は無収入で、出版にこぎつけたとしても、労力に見合った収入は期待できない。それで今、CPUファンとヒートシンクを買う金にも窮しているわけだ。
結局、こう考えていくと、C++の参考書の執筆は、他人のためにも自分のためにも、無益ではなかろうか。何でわざわざ無益なことをやっているのか。
まあ、「プログラミング言語を記述して、何かを作る」というよりも、プログラミング言語の文法と機能を学ぶことに喜びを見出すようになったバカの報いなのだろう。
そんな解説は存在しない。
このタイトルに釣られた者は、生涯memory_order_seq_cstを使うこと。その他は気にしなくていい。memory_order_seq_cstはデフォルトとなっているので、プログラマーはメモリーオーダー自体を指定する必要がない。
そもそも、この記事に釣られた人間が、アトミック操作ライブラリーを使いこなせるわけがない。おとなしくmutexやcondition variableやfutureを使っておいたほうが賢明だろう。
John Carmackが興味深い意見を述べている。
Id Software’s John Carmack picks a side in the Nvidia/AMD GPU war | PC Gamer
現時点では、CPUに統合されたGPUは、非力である。しかし、次の世代では、状況が変わってくるのではないかと述べている。それも、五年後だとか。
果たしてそうなるだろうか。今や、大多数の個人用のPCは、イーサネットカードやサウンドカードを搭載していない。マザーボードに統合されているものが、十分な性能を持っているからだ。GPUは、いずれCPUに統合されてしまうのだろうか。
グラフィックカードというものが、処理速度という理由ではなく、より描画の画質を向上させるという目的で、一部の好事家だけに使われるような時代が来るのだろうか。現在、サウンドカードは、そのような状況になっている。しかし、まだGPUは、処理速度を気にしなくなるほど十分な性能に至っていない。
delegateという言葉がある。これは、デザパタ(笑)業界では、委譲とか委任などと訳されている。実に悪い翻訳である。むしろ、単にデリゲートと言ったほうが分かりやすい。
どうして、既存の翻訳家は、こういうまずい訳をあてたがるのだろうか。例えばRegression testだ。退行テストなどという珍妙な訳を当てた人間は、腹を切って詫びるべきである。
さて、delegateはデリゲートと音訳することに関しては、異論は出ないだろう。ただ、C++0xのコンストラクターのデリゲートには、もっと翻訳しにくい単語がでてくる。
たとえば、delegating constructorだ。これはどう訳したものやら。デリゲーティングコンストラクターではわけがわからない。Finding Nemoをファインディング・ニモと訳すのと同じぐらい馬鹿げた訳だ。いったいどこのバカがこのタイトルに決めたのか知らないが、多くの日本人は、ファイティング・ニモだと勘違いしている。これはいっそ、デリゲートコンストラクターとでもした方が分かりやすいだろう。意味が異なってしまうが、まあ、仕方がない。
最後の刺客は、principal constructorである。これは非常に分かりづらい。プリンシパルという音訳は、あまり一般的ではない。これを単純に音訳したならば、どこか滑稽で、まるでルー大柴になってしまう。それは避けねばならない。
ではどうするか。元コンストラクターというのが、まあ、精一杯考えたあげくの案だが、どうもこれもよろしくない。むしろ、最初のコンストラクターとでも訳したほうが無難か。意味としては、最初に呼び出されたコンストラクターなのだから。
今書いているC++0xの参考書は、C++0xを母国語とするプログラマーに向けて書いている。この種類のプログラマーを、C++0xネイティブと呼ぶことにする。C++0xをC++0xとして解説することを目的としていて、他の言語との機能や文法の比較はない。これは、C++03とて例外ではない。つまり、今書いているC++0x本は、C++03からの変更点ということを、特別に意識して書いているわけではない。
この執筆方針は、長期的に見れば、当然である。例えば、今出版されるC言語の参考書には、K&R Cからの変更点とか、BCPLからの変更点などといったことは、まず書かれないだろう。他の言語との比較というのは、その言語自体を学ぶ方法としては、あまり役に立たない。何故ならば、それは単によく似た機能であって、同じではないからだ。
例えば、今、「C++0xのラムダ式とJavascriptの関数リテラルは基本的に同じだ」と言えば、C++0xネイティブとJavascriptネイティブの両陣営から総攻撃を受けるだろう。何故ならば、この二つは全く別の機能だからだ。
とはいえ、本書の対象読者は、前提条件として、C++をある程度理解していることが求められる。今C++をある程度理解している者とは、C++03をある程度理解している者である。そこで、C++03とC++0xの違いが気になるのは当然だ。
C++03からの差分という形で説明すれば、とりあえず短期的には分かりやすい。しかし、今K&R Cを教えるのが時代遅れなように、C++03を教えるのも、時代遅れである。そもそも、私はすでに、C++03のコードが書けなくなってしまっている。C++0xネイティブの本を執筆する者として、当然の心構えである。C++03はもはや劣った言語であり、今更使うべきではないのだ。
例を挙げると、コンストラクターのデリゲートがある。これは、劣ったC++03プログラマーからすると、新機能である。しかし、C++0xネイティブの視点から見れば、単に従来のメンバー初期化子と、何ら変わることはない。したがって、別にわざわざ特別に章節をたてて説明するほどのものでもない。
しかし、コンストラクターのデリゲートを、メンバー初期化子と同じものとして解説するのは、やはり大多数の非C++0xネイティブからすれば、分かりにくいのではないか。
Hashify
22500文字の文書をURLに保存する驚愕のサービス「Hashify」【増田(@maskin)真樹】 : TechWave
ドキュメントをURLとして埋め込み、そのURLをURL短縮サービスによって短縮することによって、実用的に使うことができる。
言いかえれば、ドキュメントとしてのURL文字列を、URL短縮サービスに保存させているわけだ。
Web Real-Time Communications Working Group Charter
W3Cが、サーバーを介さない、ブラウザー間のリアルタイム通信のためのAPIを策定するWGを立ち上げたらしい。つまり、ブラウザー同士のP2P通信ということになる。
このAPIが策定されれば、サーバーを介さない音声や動画、その他の通信が、ブラウザー上で可能になる。
C++には、とても細かいルールが大量に存在する。
たとえば、あるクラスに、同じ型のdirect non-virtual base classとvirtual base classが存在する場合、メンバー初期化子は曖昧でill-formedとなる。
struct A { } ; struct B: virtual A { }; struct C: A, B { C() ; }; C::C(): A() { } // ill-formed: which A?
関節のvirtual基本クラスはメンバー初期化子で初期化できる。しかし、直接のvirtualではない基本クラスと同じ型を使っている場合、曖昧でエラーとなる。
もちろん、これはC++という言語にとっては極めて重要なルールであるが、果たして、普通のプログラマーにとっても重要だろうか。これを知っていることで、よりよいコードを書けるのだろうか。
今書いているC++の参考書は、これらの些細なルールをも、漏れなく記載しているが、果たして本当にこんな説明が必要とされているのだろうか。
もちろん、ささいなことだが重要なルールもある。例えば、関数形式のキャストと宣言文とでは、文法が曖昧になる場合がある。その場合、宣言文として解釈可能な場合は、すべて宣言文として解釈するというルールがある。すなわち、以下のコードがill-formedになる。
int main() { short a( 0 ) ; int b( int(a) ) ; b = 0 ; // ill-formed }
なぜか、実は、このbというのは、int型の変数の宣言ではなくて、int型の引数をひとつ取り、int型を返す、関数bの宣言なのだ。aは仮引数名であり、aの周りにある括弧は、冗長である。
int main() { int b( int a ) ; // 関数宣言 b() ; } int b( int a ) { return 0 ; }
このような落とし穴は、説明する価値がある。もちろん、今書いているC++の参考書にも載せてある。おそらく、C++プログラマーならば大抵一度は引っかかるのではないだろうか。
South Parkは、以前に比べて酷くつまらなくなったように感じる。たぶん、MattとTreyも、だいぶ歳をとったためじゃないかと思う。以前ほどの単純な面白さがなくなっている。アメリカ人に、単純な面白さ以外のコメディが作れるわけもないので、今のSouth Parkはつまらない。
久しぶりに、保元物語や平治物語を読んだ。平治物語の解説を読んでいて、はっとしたことがあった。
平家物語の作者は諸説あるが、もっとも有名な説は、信濃の前司、行長である。何しろ、徒然草に書いてあるのだから、無視はできない。
徒然草、第二百二十六段
後鳥羽院の御時、信濃前司行長稽古の譽ありけるが、樂府の御論議の番に召されて、七徳の舞を二つ忘れたりければ、五徳の冠者と異名をつきにけるを、心憂き事にして、學問をすてて遁世したりけるを、慈鎭和尚、一藝ある者をば、下部までも召しおきて、不便にせさせ給ひければ、この信濃入道を扶持し給ひけり。この行長入道平家物語を作りて、生佛といひける盲目に教へて語らせけり。さて山門のことを殊にゆゝしく書けり。九郎判官の事は委しく知りて書き載せたり。蒲冠者の事は能く知らざりけるにや、多くの事どもを記しもらせり。武士の事弓馬のわざは、生佛東國のものにて、武士に問ひ聞きて書かせけり。かの生佛がうまれつきの聲を、今の琵琶法師は學びたるなり。
白楽天の七徳の舞を説明する際、七徳のうちの二徳を忘れたので、五徳の冠者とあだ名を付けられた。それを、「心憂き事にして、學問をすてて遁世」したのだという。
一体、その程度の恥で出家するものなのだろうか。しかし、これは当時の時代背景を考えれば、おかしいことではない。
まず時代である。徒然草は親切にも、「後鳥羽院の御時」と書いてくれている。これは非常に重要である。この時、鎌倉幕府が力をつけていき、朝廷側としても、どうしても政府には武が必要であるということを意識しなければならない時代であった。
七徳というのは、何の七徳かというと、武の七徳である。春秋左氏傳の宣公十二年に書いてある。
春秋左傳 : 宣公 : 宣公十二年 - 中國哲學書電子化計劃
夫武、禁暴、戢兵、保大、定功、安民、和眾、豐財者也
白楽天の詩は、武の七徳に基づいて七徳の舞を作った唐の太宗を褒め称える内容である。
七德舞、七德歌、傳自武德至元和、
元和小臣白居易、觀舞聽歌知樂意、樂終稽首陳其事、
太宗十八舉義兵、白旄黃鉞定兩京、擒充戮竇四海清、
二十有四功業成、二十有九即帝位、三十有五致太平、
功成理定何神速、速在推心置人腹、亡卒遺骸散帛收、
饑人賣子分金贖、魏徵夢見天子泣、張謹哀聞辰日哭、
怨女三千放出宮、死囚四百來歸獄、翦須燒藥賜功臣、
李勣嗚咽思殺身、含血吮瘡撫戰士、思摩奮呼乞效死、
則知不獨善戰善乘時、以心感人人心歸、
今來一百九十載、天下至今歌舞之、
歌七德、舞七德、聖人有祚垂無極、
豈徒耀神武、豈徒誇聖文、太宗意在陳王業、王業艱難示子孫。
唐の太宗は、隋末期の戦乱の世を、武力で平定した皇帝である。だから、「武の七徳」を重要視し、自筆の文章、「帝範」と「貞観政要」でも使っている。この二書は、平安末期に天皇も講じている。政治に武が必要であるというのは、当時の時代精神として、当然の認識であったわけだ。
その当時において、武の七徳を忘れたとあっては、相当の恥に違いない。学問の誉どころか、時代の動向が分からない阿呆とみなされたはずである。してみれば、出家するのも無理はない。
平治物語の冒頭も、
いにしへより今にいたるまで、王者の人臣を賞ずるは、和漢両朝をとぶらふに、文武二道を先とせり。文をもつては万機のまつりごとをおぎのひ、武をもつては四夷のみだれをしづむ。しかれば、天下をたもち、国土をおさむること、文を左にし、武を右にすとぞ見えたる。たとへば人の二の手のごとし。一も欠けてはあるべからず。
と始まり、またその少し先で、唐の太宗の逸話を披露する。武を相当に意識した書き出しである。平治物語では、清盛は勇敢な好人物である。また、何度でも勅命に従う忠勤な臣下である。重盛はタフ気取りのアホ勇者である。
さて、一方平家物語では、武は非常に野蛮なものと書かれている。清盛は邪智暴虐の限りを尽くす朝敵である。平家物語における重盛は、平家と朝廷の間を行き来して、なるべく穏便に事をすまそうとした人物である。史実では、殿下乗合を起こしたのは重盛なので、相変わらずその性格は激しいものであったが、どうも後天的な努力により、なるべく抑えようと努力していたらしい。その結果として、平家物語では、平家の一門でありながら、朝敵とはならず、むしろ過剰なまでに美化されているのである。
これもあるいは、武の七徳を忘れるほど、政治における武を重要視していなかった行長によって書かれたためであろうか。
ASCII.jp:シェアを伸ばすAndroidを襲った「駆除できないウイルス」の恐怖|モバイルマルウェアの脅威と対策
malwareはexploitによってroot権限を得ているが、ユーザーはroot権限をもってないし、公式な方法では得ることができないので、malwareを手動で削除することができないのだとか。まったく、スマートフォン業界は理解に苦しむ。自分の自由にならないデバイスは使うべきではないのだ。ゲームコンソールにも同じことが言える。
asahi.com(朝日新聞社):米軍グアム移転費水増し 日本の負担軽減装う 流出公電 - 政治
どうやら、朝日新聞がWikileaksから7000件の東京発の米公電を入手したそうで、その中から公開されたのが、これらしい。
気になるのは、他の公電にはどのようなものがあるのかということと、果たしてどのくらい公表されるのかということだ。朝日だから、あまり期待していないが、どこがやったとしても、困難であろう。その公電の信憑性は疑わしいし、裏取りの取材をすると、時間がかかる。この問題に限って言えば、かつて国会でも取り上げられたことがあったらしく、今回の米公電とおぼしきソースの中に、そういう内容のものがあったから、まあ、比較的、公開しやすかったのだろう。とはいえ、残りの公電が全て本物だということにもならないので、またこれも難しい。まあ、朝日だし。
何故Justin Bieberは米国匿名掲示板で叩かれるのか-米国版2chと格差社会 - My Life After MIT Sloan
特に努力も苦労もしていない奴が、のうのうとお気楽な芸術を公開しているのが、米ネット民の反感を買っているらしい。さもありなん。
4Gamer.net ― 津田大介&南治一徳&清水亮らが語る,ゲームとプログラミングの今は昔。ゲームやプログラムはもちろん,大震災にまで話が及んだ座談会を掲載(ミドルウェア/開発ツール)
ゲーム業界は、黎明期に比べて、今はなんと夢のないことよ。結局、黎明期に飛び抜けた人間が、今も業界のトップに立っているわけだ。しかし、かつて飛び抜けていたからといって、今も優れているかどうかは疑わしいものだ。例えば、ドラクエはどこのキャバ嬢か分からんようなガングロ妖精を登場させ、風来のシレンは、かつての栄光など見る影もない。マリオもゼルダも移植ばかりだ。もはや、日本産のゲームにみるべきものはない。
以下のコードをコンパイルするとエラーになる。
class X { int value ; friend class Y ; } ; class Y { public : template < typename T > static auto f(T t) -> decltype( t.value ) { return t.value ; } } ; int main() { X x ; Y::f(x) ; }
gccは、おそらくバグのため、このコードをコンパイルできない。興味深いのは、エラーメッセージだ。
In function 'int main()': error: 'int X::value' is private error: within this context
そもそもmain関数内というのが間違っている。。X::valueにアクセスしているのは、Y::get関数である。
試しに、クラスXからmain関数をfriendにしてみると。
class X { int value ; friend class Y ; friend int main() ; } ;
なぜかコンパイルが通ってしまう。明らかにおかしい。
なかなか笑えるバグだ。発見者はバグレポートを投げたほうがいいと思う。
Chrome extensionの青空縦書きリーダーをアップデートした。
注入するCSSのセレクターを、bodyから*に変更し、さらに!importantを指定するようにした。また、line-heightを指定できるようにした。
Software localization is difficult. There are so many differences in natural langauges we use. In this post, I want to write about how not to localize your software. That is, there are so many softwares and libraries trying to deal with the localization, badly. They believe their works helps localization. But in reality, it just make things worse.
First and the most important. Collation is a bad idea. I have no idea what the collation is all about. Because, Japanese doesn't have that kind of concept. So if your software dealing with collation, you're doing thing that isn't generic among most natural langauges in the world.
Just look at the wikipedia entry for the Collation.
Collation - Wikipedia, the free encyclopedia
See Languages at the left side. If collation is so generic and it matters in all languages, then why there are only 19 languages for corresponding entry in the list. Why there is no Japanese, Chinese, Korean? Because, we don't have such a concept.
Case, accent, character ordering, these things does not exist or simply doesn't work at all in Japanese.
Plural handling. Please, Don't. Just don't do that. If you think plural handling is important for localization, you shall not implement the localization library in the first place.
For ease of localization, software should implement the most generic feature that makes sense in all natural languages. Plural handling is not a generic concept. We should rather change our natural language to make it easier for processing.
English. If localization library requires English knowledge, then it sucks. Really. It's horrible. The fact we need localization is not all people understand the single language. Software developer is no exception.
You may argue that programmer should understand English, localization is for user. That doesn't work at all. Programmers are, in the same time, users. If you can hire enough programmers who knows English well in that country, then you don't need a localization for English software in that country.
If you're living in a country where English is not a official language, but you and all citizens can understand English, then English defeated your language. What language do they use to teach students? English? Then, your language is dead. You don't need a localization at all.
We need a localization because we don't know that language. If your software does one of above in the name of localization, please don't. It's just doesn't work at all.
I bet if you insist English, you also insist plural handling. Consider, how can we completely abandon our language when you can't even abandon one of your silly grammar in your language? Nobody can.
These close minded non-generic implementation almost always has assumption how language should be processed. For other languages, it doesn't make sense and it must be modified. So we need to patch source code or binary. In that case, localization library become just another obstacle for localization. Localization cost is as same as localizing hard-coded software.