iPhone | |
favstar のほうが iPhone から見やすいんだけど、あの馬鹿みたいな配色がないと寂しい気もするもんだ。
Perl | |
package My::Model; use strict; use warnings; use base 'Data::Model'; # ... sub count { my ($self, $model) = @_; my $schema = $self->get_schema($model); my ($iterator, $options) = $schema->{driver}->get($schema, undef, { select => 'COUNT(*)' }); my $count = $iterator->()->{'COUNT(*)'} || 0; $options->{end}->() if ref $options->{end} eq 'CODE'; $count; } 1;
これでいいんかな。
RendezvousProxy のホスト設定のとこ、"Service Text" を適当に設定してやればうまくいくっぽい。(もしかしたらこの例のように Unko じゃないとダメかも)
時代は tscreen! だけどステータスラインが二行になって困る…という人は
caption splitonly
ぽいことを書いたらうまくいくカモ!
:hide が便利ですね。
Scala をやってると contravariant な type paramter (反変型パラメータ?) という言葉が出てくる (OCaml にもあったかな) んだけど、これって一体なんなの?というのに、思ってること。
そもそも反変ってなんなのって話になるんだけど、「反」と言うからには「正」のものもあって、これは共変 (covariant) と呼ばれます。共変なものと反変なものは対になっていて、互いが互いの反対であるというイメージです。何かの基準の動きに対して、共変なものはそれと同じ方向に動く一方で反変なものは真逆の方向に動く。そんなイメージです。
ここからの例では型の例として Real (実数、いわゆるふつうの数), Int (整数) というのを使います。整数ってのは実数でもあるので、Int ってのは Real のサブタイプですね。実際には Real という型は Scala に存在しないので、Any にでも読み替えて下さい。Any は広すぎてイメージを損うので、Real というのを例に出しています。
共変な型パラメータを取るものの例を考えてみると馴染み深く List[A] というのがあって、これは型 A だけのデータからなるリストです。自然に考えることだけど、List[Int] が List[Real] のサブタイプであったほうが嬉しい。なんでかって、実数に対して行える計算ってのは当然整数に対しても行えるからです (これはつまり、Int が Real のサブタイプだってことです)。List[Real] にリスト中の数の合計を計算する sum() が可能なら、 List[Int] にだってそれを適用したい。できるべきだ。ですよね。
そうあって欲しいから、List というのはこんな風に定義することになる。
class List[+A] { // ... }
こうすると、型パラメータ A の継承関係というのが List[A] の継承関係と同じ向きに働きます (同じ向きってのでこれを共変的と呼びます)。Int が Real のサブタイプなら、List[Int] は List[Real] のサブタイプになるということです。だからこう書ける。
val list : List[Real] = List[Int](1,2,3)
整数のリストを、実数のリストとして受け取ります。ごくごく自然ですね。
これが共変的ってこと。
さて、反変的な型パラメータというものについて思いを馳せるときに、List[+A] の例を引きずって List[-A] というものを考えるのは、よくないことです。何故かというと自然じゃないから。自然と型パラメータが反変的になるような例を考えるべきです。
で、ここで自然な例というのは、関数 Function[A,B] です。この型を持つ関数は、型 A の値を引数に取り、型 B の値を返します。こいつを考えるとき、Function[A,B] と A というのは反変的にはたらくっていうことです。B に対しては共変的なんですが、ややこしいので返り値の型は _ にでも固定しておきましょう。型 A の値を引数に取り、何かをする関数 Function[A,_] について考えます。
その前にそもそもサブタイプとは何か?っていう所に戻るんだけど、簡単な定義を先に書くと:
型 A が 型 B のサブタイプであるとは、型 B の値に対して行える操作は 型 A の値に対しても行えるということ
ですよね。感覚的には
型 A が 型 B のサブタイプであるとは、型 A の実装 (インスタンス) は型 B の実装 (インスタンス) でもあるということ
と思ってます。だから List[Int] の実装である List(1, 2, 3) は、List[Real] の実装して扱える (List(1.0, 2.0, 3.0) みたいに)。逆に List[Real] のインスタンス List(3.1, 4.1, 5.9) は List[Int] のインスタンスとしては扱えない。
Function[A,_] の例に戻りましょう…。
さて、ここで前の List の例と照らし合わせれば、Real (実数) を引数にとる関数と Int (整数) を引数にとる関数との関係はどのようだろうか?というところだけど、Function[Int,_] のインスタンス f (整数に対して何かする) と Function[Real,_] のインスタンス g (実数に対して何かする) を比べてみると、g (実数に対する操作) で f (整数に対する操作) を置き換えることはできるけど、f で g を置き換えることはできない。g(3) はできるけどf(3.1) は無理。つまり g : Function[Real,_] は Function[Int,_] のいち実装になっている、ということです。g : Function[Real,_] が Function[Int,_] の実装になっているので、つまり Function[Real,_] は Function[Int,_] のサブタイプになっている。Int は Real のサブタイプだったので、この関係が逆になっている。これが反変という言葉の表すことです。
だからこう定義するべきだし、
class Function[-A,+B] { // ... }
こう書ける。
val func : Function[Int,_] = (_ : Real) => ()
そしてこれが「値を返す」ということと「値を受け取る」ということの双対性に繋ると思うのだけど、詳しくないので知りません。
生まれつき説明が下手なので言いたかったことをまとめると、反変的型パラメータが分かんなかったらリストとかスタックとかじゃなくて、関数の例でこねくり回したほうがいいですよ!ということです。