「コンピュータ」っていう呼び方

子供のころはcomputerの日本語訳が「電子計算機」であることに違和感を覚えたものです.

昔覚えたその違和感は,コンピュータを使ってやっていることと「計算」というワードのがどうにも結びつかないことから来たものでしょう.

情報系の知識を蓄えた今なら理解できます.その「計算だとは考えにくかったコンピュータの使い道」は,複雑な計算と諸々のデバイスとのやりとりの上に実現されているのだと.

ですが,PCで一般の人が普段やっていることを「計算」と呼ぶことには抵抗があります.背景に「計算」があるにせよ,見た目には「計算」ではありません.

そう考えるとやっぱり,今あるPCなどを指してコンピュータだ,あるいは計算機だというのは非自明な言い方でしょう.

ユーザ視点から考えた,もっと具体性のある名前はないでしょうか.「情報端末」というのはちょっと抽象的ですけど「コンピュータ」よりはしっくりきますね.


余談ですが,「一般には計算だとは考えにくいコンピュータの使い道」を表す言葉として「ユーザエクスペリエンス」が使えることに最近気づきました.ただ,これも言葉が一般的すぎて一般には使いにくい.

Monoを使うことの是非

MonoやPortable.NET*1といった.NETのオープンソース実装は,MSの特許を侵害しているのではないかという意見があります.

いちおう.NETにおけるアプリケーション実行基盤である共通言語基盤 (CLI; Common Language Infrastructure) とC#の仕様はそれぞれECMA-334とECMA-335で標準化されています.ですが,Visual C#にはECMA-334で標準化されていない言語機能がいくつかあります*2

標準化されている機能についてはサードパーティが勝手に実装するのをMSはとめないことになっていて,CLIについてはMSがシェアードソースなリファレンス実装も提供しています.では,標準化されていない機能も実装しているMonoなどの正当性はどうなんでしょう?Monoはこのまま使い続けても大丈夫なんでしょうか?

実際のところ,Monoに特許侵害があろうともMSは黙認し続けるでしょう.MSがXamarin (Monoの商用バージョン) 用のライブラリを提供していることが理由の一つです.しかしながら,MonoやPortable.NETを認める声明を直接出してはいません.


そんなこんなで特許問題への懸念が払拭しきれないMonoですが,それでも使い続けると宣言したオープンソースプロジェクトがあります.GNOMEが一例です.

GNOMEプロジェクトを間接的な影響下に置いていると思われるフリーソフトウェア界の教祖様はMonoがお嫌だそうですが,GNOMEのDave Nearyは「Monoに関して私がRMSに反対する理由」と題されたブログ記事で特許に対する彼のスタンスを明らかにしています.以下に抄訳を添えて抜粋引用します.

I’m not arguing that we should encourage its use either, but I fundamentally disagree with discouraging someone from pursuing a technology choice because of the threat of patents. In this particular case, the law is an ass. The patent system in the United States is out of control and dysfunctional, and it is bringing the rest of the world down with it. The time has come to take a stand and say “We don’t care about patents. We’re just not going to think about them. Sue us if you want.”

Monoの利用を促すべきだとも言っているわけではないが,特許侵害の恐れがあるからといって人がある技術を追求することに口出しすることには基本的に私は反対だ.この場合に限って,法律はカスだ.米国の特許システムはその統制を失って機能不全に陥っていて,他国の足を引っ張っている.「わたしたちは特許を気にしない.考えないようにする.訴えたければお好きに」という立場をとる時が来たのだ.

In all of the projects that I have been involved in over the years, patent fears have had a negative affect on developer productivity and morale.

私が数年来関わってきたプロジェクトの全てにおいて,特許問題への懸念は開発者の生産性と士気に悪影響をもたらし続けている.

訳が適当になっていますが,彼は諸々の理由からの「特許制度を完全に無視しろ」という少々危なげな主張をもって,Monoを忌避することに反対しています.

彼はこの記事の最後に次のように綴っています.

So if you want to write a killer app in Mono, then don’t let anyone tell you otherwise. If you build it, they will come.

だからMonoでキラーアプリを作りたいなら,反対する声に耳を貸すな.作ってしまえば文句は出まい.

なんともかっこいい激励のセリフですが,キラーアプリが存在することで特許問題を無視して人が集まるのかはかなり疑問です.本当にそうならばかなり興味深い.

*1:DotGNUの一部.私は寡聞にしてPortable.NETの存在を最近まで知りませんでした.

*2:例えば,varキーワードによる変数の型推論やLINQなどのファンシーな機能はECMA-334には載っていません.標準化されているのはMS実装のサブセットのみです.

CDのリッピングに最適なフォーマットは?

今日は久々にCDを買ってきました.自分のミュージックライブラリを作業途中で放置していることを思い出したので,ついでにリッピングフォーマットを再考してみることにしました.

※最近はWindowsも使いますが,基本的にLinuxユーザの視点で書くことに注意してください

考える材料としてGoogle先生に教えてもらったのがこのスレッド(英語)

ちょっと眺めてみると,フォーマットに関しては非可逆圧縮の話題が全くなくてFLACAppleロスレス・WAVで意見が割れている感じです.

FLACは現在の自分が使っているフォーマットです.十分枯れたエンコーダやタグ編集ツールがだいたいのディストリで配布されている,コマンドでタグが編集できる,というあたりが気に入ってます.

Appleロスレス可逆圧縮では唯一iTunesiPodで再生できるフォーマットですが,僕はあいにくApple製品持ってないですし,フリーソフトウェアのエンコーダやツールがあまり普及してないのが採用しにくいところ.

「WAVでいいじゃん.HDD安いし.どんな機器でも聞けるし」という声も上がってますね.そう思っていた時期が僕にもありました.確かに,幅広いハード/ソフトで再生できるのは大きなメリットですし,今ではディスク消費も痛くありません.ですが,WAVで困るのはメタデータの管理方法.ファイル名にメタデータを書くのには限界があります.一応,タグを埋め込むこともできるっちゃできるみたいですが,やはり読みだせるソフトは限られるようです.

一方で,AirPlayやDLNAのようにネットワーク経由で音楽が聴けるシステムを提案する意見もありますね.ネットワークにデコード済みの音声ストリーム流すようにすれば,フォーマットに依存しない音楽視聴環境が作れる?今使ってるXMMS2JACKあたりを組み合わせればできるかもしれませんね.

ごちゃごちゃ書きましたが,結局データフォーマットはFLACのままになりそうです.加えて,メディアサーバ的なものの導入は検討に入れておきましょう.

STLのvalarrayを知った

Twitterで知っていろいろ触ってみました.std::valarray.std::vectorなどとは大きく使い勝手が違うので,使うときは注意が必要です.

何に使うクラス?

複数の数値それぞれに対して同じ計算を一斉にやりたいときに便利.

基本

// C++11
std::valarray<int>
    foo = {1, 4, 3, 2},
    bar = {5, 2, 0, 3};

foo.size(); // => 4
foo.max(); // => 4
foo.min(); // => 1

// 以下,{...}はstd::valarray<int>({...})の略
foo * 2; // => {2, 8, 6, 4}
foo + bar; // => {6, 6, 3, 5}
foo -= 3; // 破壊的変更
foo; // => {-2, 1, 0, -1}

foo.apply([](int x) { return x*x; });
    // => {1, 16, 9, 4}; 非破壊的
foo.apply(std::abs); // => {2, 1, 0, 1}; 要cstdlib
std::abs(foo); // foo.apply(std::abs)と同義

bar.shift(3); // => {3, 0, 0, 0}; 非破壊的
bar.cshift(3); // => {3, 5, 2, 0}; 非破壊的

応用

このクラスにはイテレータがありません.要素を部分的に変更したい場合は普通の添え字アクセスの他に,便利なアクセス法が用意されています.

std::valarray<int> hoge = {0, 1, 2, 3, 4, 5};
const std::valarray<int> fuga = hoge;

hoge[2] = 0; // => {0, 1, 0, 3, 4, 5}; 破壊的
hoge[std::slice(1, 3, 2)] // => hoge[1], hoge[3], hoge[5]への参照
hoge[std::slice(1, 3, 2)] += 1;
    // => {0, 2, 0, 4, 4, 6}; 破壊的
fuga[std::slice(1, 3, 2)] // => valarray<int>({1, 3, 5})

sliceの他にもあるので,詳しくはhttp://www.cplusplus.com/reference/valarray/valarray/operator[]/で

よくわからないところ

std::valarray<int> ary = {0, 1, 2};

for (auto &x : ary); // 可
for (auto &x : ary * 2); // 不可
for (auto &x : ary[slice(0, 2, 1)]); // 不可
for (auto 6x : valarray<int>(ary * 2)); // 可
for (auto &x : valarray<int>(ary[slice(0, 2, 1)])); // 可

僕が仕様読んでる限りはary * 2やary[slice(0, 2, 1)]はvalarrayのインスタンスを返すはずなんですけど.そもそもイテレータが無いのにrange-based forで列挙できるのも変な話ですが.単なる勘違いかもしれません.

立命合宿お疲れ様でした

11日から13日まで弊大学で競技プログラマーの合宿が行われました.毎日1回模擬コンテストが行われ,会津大学大阪大学立命館大学の3校がそれぞれ各コンテストの問題作成を担当しました.自分もちゃっかり問題作成に関わりました.


3日目のコンテストで出題されたこの問題を先輩方にも手伝っていただきながら友人らと作りました.

「B問題作って」と先輩.「問題文をみくみくにしたい」とボカロ好きの友人.ある日,無心でボカロ曲を聴きまくった僕は布団の中でこの問題の原案を思いつきました.発案した当初はリアルな設定に近づけようと複雑にしていたので,先輩方がB問題らしくそれを簡略化していって,ボカロ好きの友人が見事に問題文をみくみくにしてくれました.僕は正直あまり仕事してません.

3日目のコンテスト中は風船やプリントを配達したり,提出されたソースを読んだりしていました.思ったほどACレートは高くなかったですね.想定誤答よりも問題文の見落としによるWAが多かった印象.それでもたくさんの人に解いていただいたので,作者の一人として嬉しいです.

学外からも50人以上の方々にご参加いただき,楽しい合宿になりました.ありがとうございました.

C++のalgorithmヘッダとか関数オブジェクトとかの話

明日から3日間,うちの大学で競技プログラマー向けの合宿が行われます.模擬コンテストは,AOJを使ってオンラインから参加できるそうなので是非ご参加ください.

さて,今回のエントリはC++の話です.競技プログラミングをC++でやるとなると,STLのコンテナ類を使いこなすことが大事ですよね.そして,algorithmヘッダで定義されている諸関数も大事だったりします.
競技プログラミング以外でも使うかなと思ってstd::は省略せずに書きます.
また,C++11のものと明示していないところは,C++03でも動くはずです.

fillは配列の初期化に便利ですね.

int array[100];
std::fill(array, array+100, -1); // [array, array+100)の範囲を-1にする.

実は,fill_nという関数もあって,

int array[100];
std::fill_n(array, 100, -1); // arrayから順に100個分の範囲を-1にする.

という風に少しタイプ量が減らせる場合があります.
特に,多次元配列を初期化する場合は効果的ですね.

int array[100][100][100];
std::fill((int*) array, (int*) array+100*100*100, -1);
std::fill_n((int*) array, 100*100*100, -1);

そして,おなじみのsort

std::sort(vector.begin(), vector.end())

sortには第三引数に比較関数を与えることができます.上の例は,vectorの型がstd::vectorとすると

std::sort(vector.begin(), vector.end(), less<int>());

と同じ意味です.昇順にソートされます.第三引数に与えているのは比較関数を表わすオブジェクトで,引数a, bを取ってa < bを返すような関数です.降順にソートするには,

std::sort(vector.begin(), vector.end(), greater<int>());

とすればいいわけです.大小比較関数を引数に取る場合は,lessがデフォルトで渡されることを覚えておくといいですね.

ちなみに,リバースイテレータがある場合は

std::sort(vector.rbegin(), vector.rend());

とすることでも降順ソートになるかと思います.

第三引数で渡す関数オブジェクトとは一体なんなのかと.
lessは要するにこんな実装らしいです.

template <class T>
struct less
{
    bool operator()(const T& x, const T& y) const {return x < y;}
};

一方sortの第三引数の型はtemplateで定義されていて,中で()演算子を付けて関数を実行しているようです.

つまり,C++でいう関数オブジェクトとは,後ろに()をつけて関数のように使えるオブジェクトのこと.関数ポインタも関数オブジェクトとして扱えるので,比較関数を自前で書く場合は,普通の関数として書いておいて関数ポインタを渡すという感じになるでしょうか.

bool lessByAbsolute(int a, int b)
{
    return std::abs(a) < std::abs(b);
}
std::sort(vector.begin(), vector.end(), lessByAbsolute);

こういうやり方で,名前空間を汚すのは嫌だという方もいるかと思いますが,C++11ではラムダ式が書けるようになったので,今の例は

std::sort(vector.begin(), vector.end(), [](int a, int b) {return std::abs(a) < std::abs(b);});

と書けるようになりました.
algorithmヘッダには関数を引数に与えてこそ効果を発揮する関数が多いので,ラムダ式が一般的に使えるようになればその重要性は増してくることでしょう.C++11では,all_of,any_of,none_of*1,copy_ifといった新しい関数がalgorithmヘッダに追加されたようです.

このイテレータを介したプログラミングではかなり興味深い実装ができます.C++03でも,単純なプログラムであればhttps://gist.github.com/lefb766/5127844のようにアレゲなコードが書けてしまいます.ところが,algorithmヘッダの関数群はデータコンテナの媒介無しでは処理を組み合せることができません.つまり,これらの関数を組み合わた処理を書きたい場合は,データコンテナのインスタンスにに逐次的に副作用を与えていく書き方しかできないわけです.複数回の関数適用が必要な場合は,途中のデータを一旦は全てメモリの上に載せる必要があるので結局効率の悪いプログラムになってしまいます.欲を言えば,コマンドラインみたいにパイプライン実行されるとか,遅延評価されて必要になったときに一気に処理するみたいな機構が作れればいいんですけど.スレッドが言語標準でサポートされた現在ではそんなことも実現可能なのでしょうか.自分のC++力が足りない.

*1: RubyのEnumerablel#all?,あるいはEnumerable#any?みたいなものを想像していただければ

お菓子の買い出し、そしてラーメン

昨日のエントリーは2本目にしてはりきりすぎましたね.正直あのペースでは絶対に続かないと思ったので今日のエントリーは軽く今日のハイライトをお送りします.

今日は通常のRiPProの活動後に,お菓子とジュースをみんなで買い出しに行きました.来週に行われる立命館大学競技プログラミング合宿で,コンテスト中に食べるものです.参加登録時に皆さんからお寄せいただいたリクエストを元に数多くのお菓子で団ボールが一杯になりました.男だけの集団でスーパーのお菓子コーナーをうろついていたのですが,今思えばかなり怪しかったしょうね.

買い出しの後,部室にいた何人かと天天有へ.実は行くのが今回が初めてでしたが,中々美味しかったです.スープの種類が選べる形式だったので,また別のスープにチャレンジしてみたいですね.

活動後の外食といえば,大学最寄り駅前の某二郎ラーメンか同駅前の定食屋のほぼ二択状態だったのが,近頃は他の店にも行くようになってきています.良い傾向.お金が飛んでいくけど.