2011-10-30

Dartにおける代入可能について

まず最初に英語で書いてから日本に訳すという方法で書いてみた。何か違いが出るだろうか。

Dartはoptional typeを採用している。ある変数に代入できない型を代入しようとした場合、静的型警告が発せられる。ただし、プロダクションモードで実行された場合は、実行に何の影響も及ぼさない。

int x = "hello" ; // static type warning

では、代入可能とは一体何か。どのように定義されているのか。13.4 Interface Typesで定義されている。

型Tが型Sに代入可能である場合、すなわち、s = t でtの型がTでありsの型がSである場合というのは、

  • TはSである。

    int s = 0 ;
    

    これは当然だ。.

  • Tはnullである。

    int s1 = null ;
    

    nullは、⊥という特別な型を持っている。これは、どんな型にも代入可能である。

  • TかS、あるいはその両方がDynamicであるとき。

    void main()
    {
        var s1 = 0 ; 
        s1 = 0.0 ; 
        s1 = "hello" ;
    
        var d = 0 ;
        double s2 = d ;
    }
    

    動的型intを持つdを静的型doubleを持つs2に代入しているが、これは代入可能である。したがって、static type warningは発せられない。確かに、実行時には型の不一致を起こすが、それは実行時にしか分からないので、静的警告は発しようがない。

  • SとTがジェネリック型I<...>であり、Tの型パラメーターが、それぞれSの対応する型パラメーターに代入可能な時。

    void main()
    {
        List<int> = <int>[] ;
        List<num> = <int>[] ;
        List = [ ] ; // List<Dynamic>
    }
    

Assignable in Dart

Dart use the optional type. When you assigned to a variable and it isn't assignable, a static type warning is issued. If the code is executed under the production mode, it doesn't affect run time behavior.

int x = "hello" ; // static type warning

So, what exactly is assignable? How is it defined? It's defined in 13.4 Interface Types.

A type T may be assigned to a type S, that is s = t where the type of t is T and the type of s is S, if

  • T is S

    int s = 0 ;
    

    This is obvious.

  • T is null

    int s1 = null ;
    

    null has the special type ⊥. It can be assigned to any type.

  • T or S(or both) are Dynamic.

    void main()
    {
        var s1 = 0 ; 
        s1 = 0.0 ; 
        s1 = "hello" ;
    
        var d = 0 ;
        double s2 = d ;
    }
    

    Notice assigning d(dynamic type of int) to s2(static type of double) is not a static type warning although it is incorrect in run-time. This is because it's assignable. If either T or S are Dynamic, it can't be determined in compile time. So it makes sense.

  • if S and T is a generic type of I<...> and T's type parameters are assignable to S's corresponding type parameters.

    void main()
    {
        List<int> = <int>[] ;
        List<num> = <int>[] ;
        List = [ ] ; // List<Dynamic>
    }
    

2011-10-28

What is it like buying a PC game in Japan?

Today, I saw kotaku used an interesting metaphor to describe what is it like buying a PC game.
If Haruki Murakami's New Book Were Sold Like a Video Game

I think buying a PC game from Japan is also interesting to write about. Even without the metapher.

It started in January...

January
I've heard a famous game developer will release a new game in June. Wow that's too soon. I must pre-order it immediately. But I wonder where to buy it. And the most important thing is, is there a Japanese translation available?

February
It appears the game requires Steam activation. So the package means nothing. I don't need some junk toys they'll include in the package. I wonder who want that crap. I can't understand what Americans are thinking. Anyway, I pre-order it in so called Steam. It allows me to download a game. That's nice. The Japanese Steam listed it up and allows me to pre-order. So it should work. And I've heard they'll release console version of this game in Japan. So naturally, PC version must have Japanese translation.

March
They announced that Japanese translation will be released in August. Well, that's okay. I guess translation need some time. I've also heard they even translate the voice. That's fine. Perhaps I should try English version while waiting. It's completely incomprehensible for me. But who needs story in game anyway? This is not a dull linear JRPG. That's why I'll buy it. I'm so sick of crappy JRPG. Look at the world. Think globally. I can look up words from dictionary if I have to. I'll enjoy the combat in the English version. Then, I'll enjoy the story later in the Japanese version.

April
What Steam? What do you mean I can't buy it from the current location? I am Japanese and sure I live in Japan. Yes I know this is the English version. I want to play regardless and I'm willing to pay. Why don't you let me buy it? Don't you want my goddamn money? This is stupid. I can't understand it. I don't care how much you charge me. I've read from the online forum that we can bypass that check by using what they call it VPN or whatever. I don't know how that works. Also, there are pirates as usual. But I'm not one of them. Besides, I don't know how to pirate a game.

June
At last. The English version is released. I think some people who used VPN will write something in forum. I should better check it... What? Not only they play it today, But they play it in Japanese? How could that even be possible? Well, come to think of it, console game will be released in a few days. So technically, translation works must have been finished already. So what is the point of delay? Why do I have to wait two months!

July
Wow. This is hilarious. They said Steam deleted Japanese translation from their disks. Apparently, It wasn't supposed to be released. But why. Just release the Japanese version already. I don't want to wait any more. Also, why do they allowed to delete files in our disks? I don't understand.

August
What is this? What the FUCK is this? They said they'll delay the release until next year. No. Seriously. That can't be possible. I have enough of this Steam.

2011-10-22

Dartがダウンキャストに警告を出さない理由

Dartでは、ダウンキャストには警告を発しない。

class S { }
class T extends S { }

void main()
{
    S s = new T() ; // アップキャスト
    T t = new S() ; // ダウンキャスト
}

この例では、静的型Tの変数tに対して、静的型Sで、実際の型もSのインスタンスを束縛させているが、これは警告を発しない。アップキャストに警告を発しないというのは自然だが、ダウンキャストに警告を発しないというのは、オブジェクト指向に馴染みのない人からすれば、不思議に思われるかも知れない。現にこの場合、実際の型はTではないのだから、この場合に限っていえば、エラーである。しかし、これは正しい挙動である。では、なぜ警告を発しないのか。

なぜならば、規格に明確に書かれている挙動だからである(13.4 Interface Types)。クラスは暗黙のインターフェースを持つので、この項目はクラスにも適用される。

規格で定義されているとしても、理由はなぜか。それは、Dartの型システムは、ほぼ確実に間違いであろうと思われるコードを見つけるためにあるからだ。間違いである可能性があっても、正当なコードである可能性もあるコードに対しては、警告を発しない。

ダウンキャストは、オブジェクト指向言語ならば、当然行うことである。

class S { }
class T extends S { }

void main()
{
    S s = new T() ; // アップキャスト
    T t = s ; // ダウンキャスト
}

これは、正しいコードである。変数sに束縛されているインスタンスの型は、まぎれもなくTである。したがって、このダウンキャストは正しい。もしこのコードに警告が発せられるとするならば、それは誤りである。このコードに警告を発するようでは、プログラマーは警告というものを信用しなくなってしまう。警告というのは、ほぼ確実に誤りである場合にのみ発せられるべきなのだ。

SとかTなどのやや抽象的な話ではわかりにくい人もいるかも知れない。もっと具体的な話をしよう。Dartではすべてのクラスは暗黙にObjectのサブクラスである。以下のコードは当然動くべきである。

void main()
{
    Object obj = "hello" ;
    String str = obj ; 
}

明らかに、このコードは正しいコードである。

2011-10-21

Bitcoinについて

Coding Horror: Multiple Video Cardsが、Bitcoinのお陰で中古GPUを格安で手に入れられたと書いていたので、Bitcoinの歴史と現状をまとめて見ることにした。

そもそも、諸君はBitcoinを知っているだろうか。いや、知らなくても無理はない。日本では、あまり有名ではないように思う。だから、まずBitcoinとは何かという説明をしようと思う。

Bitcoinとは、演算保証によって信頼を得ている貨幣である。およそ、貨幣というものが広く一般に使われるには、貨幣に対する何らかの信頼が必要である。たとえば、貨幣が金と交換できる保証であるとか、国による保証などといった、信頼が必要である。そのような強い保証のない貨幣は、広く信頼を得ることができず、一般に普及することはない。

Bitcoinは、P2P技術によって実装されたオンライン上の仮想貨幣である。すべての貨幣のやり取りはP2Pによる演算で処理され、個々の貨幣のやり取りは匿名で行うことができる。と、こう書いただけでは、信用のカケラも存在しない貨幣のように思われる。金と交換できず、国家の保証もない貨幣が、どうして信頼できるというのか。だいたい、どうやって偽造を防ぐのだ。それは、演算力である。

Bitcoinを得るには、演算をする必要がある。それも、かなりの演算が必要である。Bitcoinの貨幣のやり取りをP2P上で信頼できるほどに処理するには、暗号を使わなければならない。この暗号処理には、かなりの演算力を必要とする。Bitcoinを得るには、オンライン上でのbitcoinのやり取りに必要な演算の一部を負担する必要がある。すると、Bitcoinを不正に入手するというのは、つまりは暗号を解読するということである。それには、Bitcoinを普通の方法で得るより、はるかに高い演算力を必要とする。このため、Bitcoinの偽造は割にあわないということになる。ただし、誰かがSHA256の画期的な脆弱性を発見した場合は、この限りではない。Bitcoinネットワークを攻撃するには、Bitcoinネットワーク全体の演算力を上回る演算力が必要である。その演算力は、現在のBitcoinネットワークの規模から考えて、現実的ではない。

つまり、Bitcoinの信頼は、演算力とSHA256の暗号強度に依存しているといえる。金銀に交換することはできず、国家の保証もないとはいえ、不正ができないという点で、信頼を得ているのである。

Bitcoinの他の利点としては、国家の影響を受けないということと、プライバシーを守れるということである。国家が貨幣を管理していると、意図的に貨幣の価値を上下させられる可能性がある。Bitcoinの価値は、ユーザーが決定する。そのような中央の権威の影響は受けない。プライバシーというのは、貨幣の動きを特定されないということである。これは、ともすれば麻薬取引などの違法な売買や、脱税などの金銭の動きにも使われがちであるが、それは、別にBitcoinに限った話ではなく、金銀や紙幣でも同じなので、Bitcoin特有の問題というわけでもない。

では、Bitcoinの作者は誰か。これが、どうも怪しいのだ。もちろん、記録は残っている。2008年にSatoshi Nakamotoと名乗る自称日本人によって、Bitcoinの理論と仕様を説明する論文が発表された。最初の実装も、彼によって書かれた。しかし、彼は一言も日本語を発していないし、実装にも日本語は一切使われていない。彼の2010年以降の消息は不明である。彼のメールアドレスは、無料のメールサービスを利用しており、すべての接続は、Tor経由で行われていた。つまり、彼はありとあらゆる方法を使って、匿名性を保つ努力をしていたのである。日本人を自称したのも、事によると、正体を隠すための方便だったのかもしれないとまで言われている。

なんにせよ、Bitcoinの仕組み自体には、未だに脆弱性が見つかっていないし、Bitcoinで使う有名な暗号、SHA256も、未だに画期的な脆弱性は見つかっていない。

さて、Bitcoinは不正が難しいので、最低限の信頼性を備えていることは分かった。Bitcoinの仕様はすべて公開されており、オリジナルの実装以外にも、いくつかの別の実装がでてきた。とくに興味深いのは、演算にGPUを利用した実装である。GPUはCPUほど汎用的ではないが、うまく使えば、CPU以上の演算力を発揮できる。このため、Bitcoin mining(Bitcoin炭鉱業)と呼ばれる、いわばゴールドラッシュのような現象が起きた。高価なGPUが、Bitcoinを稼ぐために多数売れたのである。

Bitcoinはその期待によって、現実の貨幣(例えば米ドル)と交換する所が現れた。その交換レートが高かったので、高価なGPUと電気代を差し引いても、利益が出せたのである。

しかし、ゴールドラッシュが長く続くわけがない。Bitcoinはその多大な期待によって、実価値以上に高い交換レートで、現実の貨幣と交換されてきた。今や、そのバブルがはじけて、Bitcoinの現実貨幣に対する交換レートは暴落し、Bitcoin炭鉱業は以前ほど儲からなくなってしまった。国家や中央銀行のように、貨幣の価値を一定に保つ権威が存在しないのだから、これは当然である。ゴールドラッシュで儲けたのは、シャベルとツルハシを売っていた者であるというのはよく言ったものだ。ハイエンドGPUが山ほど売れたのだ。

そのため、ハイエンドGPUが中古市場に溢れ、冒頭でも言ったように、Jeff Atwoodとかのゲーマーがその恩恵を受けている。

もちろん、これはBitcoinの為替が適正なレートに下がっただけであり、Bitcoinの暗号自体は、未だに破られていない。

Bitcoinの合法性であるが、独自通貨の発行が合法かどうかということにかかっている。これは、国ごとに違うので、なんとも言えない。ただし、オンラインでの売買の興隆をみれば、独自通貨の発行自体は、将来的には大抵の国で合法になる方向に動くだろう。さもなければ、ゲームやPaypalのようなサービスが成り立たない。

私自身はBitcoinには興味がなかったのだが、知り合いに、Bitcoinの仕組みに共感し、自分でも実装を書き、ハイエンドGPUでせっせと掘っている人物がいるので、近況を聞いてみた。彼は、単に技術的な好奇心のためにやっているのであって、小遣い程度の金には興味がなく、したがって、最近のBitcoinと現実貨幣の交換レートの暴落は気にしていないらしい。

私はふと、このBitcoinが、一時期のP2P技術を利用したファイル共有に対する期待に似ているのではないかと思った。あの当時、P2P技術を利用したファイル共有には、なにかゴールドラッシュのような期待があった。確かに、現時点では違法かもしれないが、それは法律が現実に追いついていないだけであって、将来的には素晴らしい可能性を秘めているのではないかという期待があった。

現実としては、法律は一向に変わらず、P2P技術は、Skypeを始めとする通信、ソフトウェアのアップデートの配布などの、裏方技術には使われているが、表立って存在を意識するほどではなくなってしまった。Bitcoinも同じような過剰の期待に押されていたのではないだろうか。

このような意見を、かの知り合いにぶつけてみたところ、彼はこれを認めた。曰く、「たしかに、そういう過剰な期待があるのかもしれない」と。「Bitcoinに触発された後発の仕様もいくつか出ている。Bitcoinは、実際の価値はさておき、コンセプトとして一定の価値があることは確かだろう」とも言っていた。

国家に左右されない貨幣が主流になる時代は来るのだろうか。

アイドック株式会社、紙書籍と電子書籍の抱き合わせ商法を発表

デジタル著作権管理(DRM)ならキーリング|愛読者カード運営代行サービス「i 読(あいどく)」提供開始!!
i読…愛読者カード運営代行サービス
via : これで自炊は不要? 愛読者カード返送者にのみ電子書籍を配信する「i読」 -INTERNET Watch

レコードをカセットテープに録音する? おいおい、何言ってやんでぇ。そんなのオイラの目の黒いうちゃぁ許しちゃおけねぇよ。レコード針やターンテーブルの生産会社が潰れちまうだろうがよ。代わりにこれ、レコードを買うと録音したカセットテープをプレゼント。あ、ほら、もう録音なんてする必要がねぇってもんだ。これにて一件落着。あっぱれあっぱれ。

DTP? よしてくれよ、写植職人が路頭に迷うぞ。最低限でもだな、今の写植と同じ仕組みでなければな。もちろん操作方法も同じだ。

活版印刷? おいおい、版木職人を飢え死にさせる気か? まあ仕方がないから、版木本を買えば、活字本もおまけしてやろうじゃないかい。

版木? そんなの許しちゃおけねぇ。真の書というものはよく手書く者によって写されるべきなんだよ。このままだと、写本職人が失業するだろうがよ。そこでこれ、写本を買うともれなく版木本をプレゼント。

紙? おいおいバカ言っちゃいけねぇや。日常の文章は木簡や竹簡に書いて、高級な文章は絹に書くのが常識だろうがよ。紙なんていう最近できたもんに字なんか書けるかってんだ。

字? おまえなぁ、生きておる智慧が、字などという死物に書きとどめられるはずがない。絵にならまだしも画けようが。それより口伝の続きじゃ。さて我がご先祖は~、怨敵をことごとく討ち平らげ~、この地に来たりて安住し~。さあ覚えるんじゃ。

2011-10-19

Dartで誤って無限ループに陥るコード

Dartは非常にシンプルな言語であるが、恐らく初心者が、誤って無限ループに陥ると思われる箇所がいくつかある。

ファクトリーコンストラクター

class X
{
    factory X() =>  new X() ; // 無限ループ
} 

void main()
{
    X x = new X() ;
}

このコードは、無限ループに陥る。なぜならば、new X()というのは、ファクトリーコンストラクターXを呼び出す式である。これは、つまり自分自身を再帰呼び出ししていることになる。結果として、無限ループになる。

正しいファクトリーコンストラクターの書き方は、別のコンストラクターを呼び出すものである。

class X
{
    X.internal() { }
    factory X() => new X.internal() ;
}

クラスのゲッターとセッター

クラスのゲッターとセッターは、クラスの変数への簡単な読み書きを提供するための特殊なメソッドである。これは、暗黙に生成される。

class X
{
    int val = 0 ;
// 以下のようなゲッターとセッターが暗黙的に生成される
    // int get val() => val ;
    // void set val( int value ) { val = value ; }
}

void main()
{
    X x = new X() ;
    x.val ; // ゲッター呼び出し
    x.val = 0 ; // セッター呼び出し
}

ご覧のように、セッターとゲッターは関数であるが、特別な文法で呼び出すことができるのだ。

サブクラスでは、この暗黙のゲッターとセッターをオーバーライドすることができる。つまり、ゲッターとセッターで、なにか複雑な処理を行うこともできるのだ。

class X { int val = 0 ; }
class Y extends X
{
    int get val() => val ; // 無限ループ
}

これは無限ループとなる。なぜか。考えてみて欲しい、クラスYのスコープにおけるvalとは何なのか。それは、もちろんYのスコープで宣言されているvalである。つまり、Yのゲッター関数valということになる。これは、自分自身の再帰呼び出しである。つまり、無限ループになる。

正しいサブクラスによるゲッターとセッターのオーバーライドは、スーパークラスのゲッターとセッターを呼び出すものである。

class X { int val = 0 ; }
class Y extends X
{
    int get val() => super.val ;
 
}

これで、再帰呼び出しは起こらない。

ちなみにいうと、ゲッターとセッターはトップレベル関数でも使える。

int _val = 0 ;

int get val()
{
    print("このままでは菌類が死滅してしまう") ;
    return _val ;
}

void set val( int value )
{
    print("勉強でも仕事でも 楽しんでやったものが、一番自分の力になるものさ。") ;
    _val = value ;
}

void main()
{
    int x = val ;
    val = 1 ;
}

ChromeがText-to-Speech APIを提供

Chromium Blog: New Text-to-Speech API for Chrome extensions

Chromeがエクステンション向けにText-to-Speech APIを提供するらしい。これは面白そうだ。

2011-10-18

Dartの興味深い機能

named parameterとnamed argument

void f( int x, [ int y = 0, int z = 0 ] ) { }

void main()
{
    f( 0 ) ; // f( 0, 0, 0 )
    f( 0, 1 ) ; // f( 0, 1, 0 ) 
    f( 0, z : 1 ) ; // f( 0, 0, 1 ) 
}

まあ、コードを読めば一目瞭然の機能だろう。省略可能なのは、named parameterだけである。名前を指定できるのも、named parameterだけである。normalFormalParameterは省略も名前指定もできない。

noSuchMethod

class X
{
    void noSuchMethod( String function_name, List args )
    {
        print("$function_name") ;
        for ( var elem in args )
        { print("$elem") ; }
    }
}

void main()
{
    X x = new X() ;
    // 関数名と実引数が表示される
    x.f() ; 
    x.hoge(1,2,3,4,5) ;
    x.fuga("All base is belong to us.")
}

これは解説が必要だろう。もし、クラスからメソッド名のlookupに失敗した場合、そのクラスからnoSuchMethodという名前のインスタンスメソッドが探され、第一引数としてメソッド名を、第二引数として、実引数のリストを渡し、呼び出されるのだ。もし、noSuchMethodという名前のインスタンスメソッドがなければ、NoSuchMethodExceptionが投げられる。

ということはだ、noSuchMethodというインスタンスメソッドを定義していれば、あたかもoperator .を定義したかのように振る舞うのだ。もちろん、実際にはoperator .はないし、メソッド呼び出しにしか適用できないが、DSLオタクは歓喜するだろう。

typedef

typedef int func_type(int) ;

void f( func_type func )
{
    int x = func( 0 ) ;
}
main()
{
    f( (int x) => x + 1 ) ;
}

typedefは、静的型の別名を定義するための構文である。現在のところ、関数の静的型の別名を定義することしかできない。

これはなぜかというと、関数は、具体的な静的型を直接に指定するのは面倒なのだ。こんなふうになってしまう。

void f( int func(int) ) { }

インターフェースFunctionはあるが、あまりにアバウトすぎる。だから、厳密な静的型を意味する識別子を定義するために、このtypedefが存在する。

べつに、これを使う必要はない。たとえば、varで受けても問題ない。DartはOptional Typeを採用しているからだ。静的型は実行時には、ほとんど意味がない。

量子浮遊

こいつは最高にクールだ。

2011-10-17

さっそくDartの規格上のバグを発見

私の唯一誇れる能力は、読解力である。そのため、私がプログラミング言語の規格を読むのを好むのは、自然なことである。このたび、Dartの規格上のバグを発見した。なかなか笑えるので紹介する。もちろん、実装者にとっては洒落にならないが。

以下のコードは、現行ドラフトの文面に従うと、well-formedなDartコードである。

main()
{
    a : { break a ; }
    b : { continue b ; }
}

なぜかというと、現行のDartのドラフト規格は、ラベル付きのbreak文とcontinue文は、label文の中に入ることができるとされている。ラベル文には、文を書ける。また、ブロック文も文である。よって、Label : { } はwell-formedなDartコードであり、その中でbreakやcontinueを使うのもwell-formedである・・・はずだ。

傑作だったのは、現行の実装が、このコードを実際にコンパイルできてしまうということだ。break文の方は、期待通りに動いた。つまり、

a : { print("before") ; break a ; print("after") ; }

は、beforeを出力する。

continue文の方は、コンパイルは通るが、実行時に、不思議なエラーを吐いて強制終了してしまう。もし規格通りに動いていたならば、無限ループになったはずだ。

この件はすでにバグ報告済みである。

DartのFlorian Loitschとのチャット

IRCのチャットで興味深かったチャットの断片をいくつか。

ezoe: 単項マイナス演算子をユーザー定義するにはnegateを使わないといけないのはちょっと驚きだね。
floitsch:何か代案でも?
ezoe:いや、別に不満ってわけでもないけど、理解するのに戸惑ったし、パースでも早くなるのかな?
floitsch:-は二項演算子にすでに取られてるからね。
floitsch:もちろん、引数の数を見て判断することもできるけど、それは他ではやってない処理だから、"operator negate"を導入することにした。
ezoe:なるほど、つまり例外的なルールを作りたくなかったのか。

ezoe:そういえば~/演算子ってのもあるけど、他の言語でこの演算子を使ってるのは知らないな。
floitsch:多分ないよ。
floitsch:切り捨ての除算が欲しかったんだ。
TheSheep://?みたいな?
floitsch:そうそれ。
floitsch:それも考えたんだけど、すぐ却下した。
TheSheep:他の言語でも使ってるよ。
TheSheep:特にpythonとかw
ezoe:一行コメントみたいだね。
TheSheep:あ!
floitsch:ほらね
floitsch:他の言語で、/や//以外で、切り捨て除算の演算子があるなら、教えてほしい。

ezoe:ふーむ、>>>演算子もあるね。
floitsch:イエス
floitsch:僕が推したやつだよ。
ezoe:どのコアライブラリが何のために使ってるの?
floitsch:なにも。
ezoe:えーと、まあ、ユーザー宣言可能な演算子が増えるってのはいいことだけど、でもコアライブラリすら使ってないんじゃ・・・
floitsch:>>>はunsigned shiftを意味する。
ezoe:>>は?
floitsch:signed shift
floitsch:そもそも、無限の精度をもった整数のunsignedな値って何さ?
floitsch:だから、コアライブラリでは>>>を定義していないんだ。

TheSheep:dartのintってjavascriptではどの型に対応するの? number?
floitsch:そう、JSのnumberさ。
TheSheep:それ固定精度じゃないじゃん。
floitsch:まあ、JSにコンパイルされたらdoubleさ。
floitsch:もちろん、それに起因する驚くべき挙動もそのままさ。
ezoe:なんだって?
floitsch:すべてのdartの数値は、JSのdoubleにコンパイルされる。
TheSheep:JSで動くツケさ。
floitsch:その通り
ezoe:そんなの整数じゃない・・・DartCが特別なコードを生成して多長演算をしてくれるかと思ってたのに。
floitsch:そりゃ遅すぎる。
TheSheep:そりゃ「遅い」
floitsch:そんなに悪くはないよ。
floitsch:ほとんどの数値は32bit以下だからね。
floitsch:それ以上が必要な場合は、開発者は分かるはずだ(Javaのlongとか)
ezoe:dart VMは任意の精度の数値を提供しているの?
floitsch:イエス

(末尾再帰最適化の話がでた後で)
ezoe:ファクトリーコンストラクターから同じコンストラクターをnew経由で呼び出してしまったことがある。俺は何を期待してたんだっていうw
floitsch:はは、結果を長く待たずに済んだことを祈るよ。
ezoe:でも、初心者は同じ間違いをすると思うんだ。
floitsch:直接の再帰呼び出しは、簡単に判定できるはずさ。
floitsch:IDEによって補足されて警告が出せるようになるといいかも。
ezoe:そうなってほしいな。うっかり書くこともありえると思う。

DartCではDartの数値をJavascriptのNumberにそのまま割り当てているとは驚きだった。JavascriptのNumberは、御存知の通り、内部的には浮動小数点数なのだ。まあ、大抵の場合は、その精度が気になることはないとはいえ、まさか規格で無限精度と定められているものを無視するとは。まあ、JSへのコンパイルは、移行措置のようなものなので、その程度の実装でも困らないのだろう。それより、数値計算の遅くなってしまうほうが問題だ。

ファクトリコンストラクターの条は、私がファクトリーコンストラクターを試したときに遭遇したうっかり間違いである。とりあえず、手っ取り早くファクトリーの文法を確かめようとして、以下のように書いてしまった

class X
{
    factory X()
    {
        return new X() ; // 再帰による無限ループ
    }
}

ファクトリークラスからは、別のコンストラクターを呼びださなければならない。

class X
{
    X.detail() { }
    factory X()
    {
        return new X.detail() ; // ファクトリーではないコンストラクターを呼び出す
    }
}

main()
{
    X x = new X() ; // ユーザーコードからはX.detailを使う必要はない

}

2011-10-16

数学を学ぶべきなんだろうか

Dartの規格に、次のような文がある。

The static type of null is ⊥.

The decision to use ⊥ instead of Null allows null to be assigned everywhere without complaint by the static checker.

現行のドラフト規格にはbeがニ連続するtypoあり。

この⊥が何を意味するのか分からなかった。しかたがないので、IRCで人に聞いた。

私:この⊥ってやつはなんだ?
人:"bottom"
私:bottom? 何かプログラミングか数学の用語なのか?
人:lattice theoryから来てる。
人:top(本当は特別な文字があるけど)ってのがすべての上にたつ汎用的な存在で、たとえばObjectだね。
人:bottomは何よりも特殊な存在なんだ。
私:つまり、bottomであるnullからみれば、すべての型はスーパークラスのようなものだということか。
人:そういうこと。

ちなみに、topの記号は⊤で、UnicodeではU+22A4である。⊥はU+22A5である。

なぜか、昔から数学はさっぱり理解できなかった。高校生の時、理系クラスに進もうとしたら、親に反対された。特に普段、勉強しろとも言わない親ではあったが、子供の勉強を反対するというのも奇妙だ。その時の言葉が印象に残っている。

「あんたに数学は無理よ。私達にだってできなかったんだから」

まるで、なにか遺伝的、先天的に数学ができないかような物言いだったのである。私の両親はそれなりに高学歴である。これは一体どういうことか。

親の案の定、私は数学をさっぱり理解できず、高校時代は、古文、漢文、英文を読んで過ごした。なぜか、私の親と同じ道をたどっているのである。

思えば、私も変な子供だったものだ。何故か昔から読書が好きだったし、小学生の頃には、すでに古事記や論語や徒然草などを読んでいた。もちろん、これは親がそのような本を家に置いていたし、「論語のどこそこ 」とか、「徒然草の第何段」といった会話が成立するほどの教養を持っていたからということもあるのだろうが、やはり不思議なことだ。何か、遺伝的なものがあるのだろうか。

今だって、私の感じるプログラミングの面白さとは、コードを書くのではなく、プログラミング言語の文法を理解することなのだ。何故こうなってしまったのだろう。

2011-10-15

DartのOptional Typeについて

Dartの素晴らしさがまだ分からない無知無識の者が、Dartの型システムについて深刻な誤解をしている。ここでは、Dartの型システムであるOptional Typeについて、ひとつ解説をする。これを読めば、Dartの如何に大昔のJavascriptより優れているかが、一目瞭然であろう。

強い静的な型付けは、C++のような、ほとんどを静的に決定する言語では非常に便利である。しかし、動的な言語では、むしろ邪魔にさえ感じる。

Dartの型システムは、Optionalである。型を明示的に書こうが書くまいが、自由である。

変数には、型を指定してもしなくてもよい。

var x = 0 ;
int x = 0 ;

関数の引数には、型を指定してもしなくてもよい。

int f( int x ) => x ;
f( x ) => x ;

ジェネリックのタイプパラメーターには、型を指定してもしなくても良い。

List<int> l = <int>[ 1, 2, 3 ] ;
List l = [ 1, 2, 3 ] ;

異なる型を代入することもできる。

int x = "肩のうしろの2本のツノのまんなかにあるトサカの下のウロコの右" ; // static type warning

これでは、型の意味が無いではないかと思う者もいるだろう。それは、Dartにおける型の目的を理解していないからである。Dartにおける型システムは、最適化のためにあるのではないのだ。ツールを助けるためにあるのだ。

まず、Dartの変数について一言説明しておかなければならない。Dartの変数とは、「メモリー上のストレージの場所を示す」ものである。これは、Javascriptのような言語に親しい物には、馴染み深い概念である。そのような言語に馴染みのないものには、とりあえず、ポインターだと考えておけばよい。もちろん、ポインターは、実際には異なる概念である。ポインターとは、やはり、メモリー上のストレージの場所を指し示す、すなわち「アドレス」を格納するために必要なだけのサイズのストレージであって、Dartの変数ではない。DartやJavascriptのような言語では、変数はすべてメモリー上のストレージへの参照であり、その参照を格納するストレージを意識することはない。

Dartにおける変数とは、内部的には、単にオブジェクトへの参照なのだから、型という仕組みがなかったとしても、不思議ではない。たとえば、DartやJavascriptでは、

var x = 0 ;
x = 1.5 ;
x = "肩のうしろの2本のゴボウのまんなかにあるスネ毛の下のロココ調の右" ;

このようなことができる。Dartにおける「代入」とは、単に変数が参照する場所を変えているだけである。変数自体は、固定されたストレージを持たないのだ。もちろん、実装上はストレージを持つが、それはユーザー側からは隠されている。

しかし、Javascriptのように、ソースコード上では、変数が型情報を持たないとすると、少々厄介である。

たとえば、ある変数はある型だと想定して使っているのに、うっかりと別の型を代入してしまったばかりに、型が変わってしまう。もちろん、コンパイルエラーどころか、警告すら出せないので、このバグを探すのは非常に難しい。プログラマーは、自分の目でバグを探さなければならないだろう。

Dartにおける型とは、言わばannotationなのだ。

int x = 0 ;
x = 1 ; // OK
x = 1.5 ; // Static type warning.

このように、型が合わない場合、コンパイル時に警告を出すことができる。そのため、プログラマーは目でコードを探す必要がなくなる。

現代では、IDEによるコード支援が盛んである。例えば、識別子を補完したり、メソッド名を補完したりしてくれるのは、非常に便利である。ところが、Javascriptのように型がないと、これは少し難しい。

var x = "肩ぐるまして後ろ向きに乗り2本のゴボウを持った歌舞伎顔の男" ;
x. // ←ここに注目

xという識別子に続いて、ドットを使っているのに注目してもらいたい。賢いIDEならば、ドットを打った時点で、プログラマーはメソッドを呼び出したいのだと解釈し、メソッドの一覧を表示してくれることだろう。ただし、この場合、xの型を静的に求めるのは難しい。

上記のような二例であれば、静的な解析でも可能である。ところが、Javascriptには、不可能な場合もあるのだ。

function f( x )
{
    x. // xは何かって? (´・ω・`)知らんがな
}

これはどうしようもない例である。

Dartでは、型をannotationのように指定することができる。そのため、静的ツールは静的に型を決定することができる。

f( String x )
{
    x. // Dartならば、IDEによってメソッド名の一覧を表示可能(`・ω・´)シャキーン
}

文法上、型を書くことができるというのは、コメントで書くよりもずっと分かりやすい。

var x = 0 ; // type of x suppose to be int. 
int x = 0 ; // horay! no comment is needed!

しかし、実行時に型が一致しなくても、エラーとはならない。つまり、実行を続けることができるのだ。ただし、警告は出るので、バグを見つけることができる。もし、型を固定したくなければ、varを使うこともできる。自由である!

2011-10-14

Dennis Ritchieに関する良記事

Rob Pike - Google+ - I just heard that, after a long illness, Dennis Ritchie…

氏の死去を始めて公にしたページ。

Dennis Ritchie, 70, Dies, Programming Trailblazer - NYTimes.com

NY Timesの記事。個人的な経歴もまとまっていて、なかなかの良記事。

Dennis Ritchie « Sutter's Mill

Herb SutterによるRitchieの回顧。Ritchieは、それまで不可能だと言われていた、portableでefficientな言語を発明した男である。

Interview with Dennis Ritchie, Bjarne Stroustrup, James Gosling

Herb SutterによるRitchieへのインタビュー。Ritchieは、ほとんどインタビューを受けない男であったので、貴重である。

2011-10-13

何故Dartが史上最高の言語なのか

史上最高にして、恐らく今世紀最高となるプログラミング言語は、Dartである。DartはC++以外の既存のプログラミング言語のほとんどを駆逐する事ができる潜在性能を持っている。これからの真のプログラマーは、C++とDartという二大言語に加え、目的に応じて、アセンブリやシェーダーなどの専用言語を学ぶことになるだろう。

Dartの美しさを理解出来ない近眼者が、愚にもつかぬ批判をしている。恐らく、彼らは規格書が読めないのであろう。曰く、「Javaのパクリ」、曰く、「目新しい新機能がない」。Javaのパクリという阿呆は、Javaのような聳え立つ糞の信者なのだろう。ただJavaと同じようなキーワードや文法を使っているからといって、それがJavaのパクリであるとは片腹痛い。Dartからみれば、Javaなど歯牙にもかけぬ愚物である。目新しい機能がないという批判もあたらぬ。およそ斬新な新機能というのは、人目を引くのは確かだが、一般に普及しがたいものである。

Dartは、すでにその価値を証明されている機能を、ごく自然に提供している言語である。いや、重要なのはむしろ、提供していないモノにこそある。Dartは、他の言語にあるような、不必要なクソを提供していない。例えば、パースが難しかったり、時間がかかるようなcontext sensitiveな文法はないし、複雑怪奇な暗黙の型変換も存在しない。この点において、改行が終端記号とみなされるJavascriptは、近い将来にDartの後塵を拝する事になるであろう。

Dartの主目的である、Javascriptの置き換えという目的には、ソースコードのコンパイルを高速に行えることがまず第一である。それには、パースが難しかったり、文脈に依存して意味が変わったりするような文法を、極力避けるべきである。Dartはこの点において、特に優れている。

例えば、Dartでは、二項マイナス演算子と、単項マイナス演算子をオーバーロードすることができる。二項マイナス演算子のオーバーロードには、おなじみの、-という記号を使えばいいのだが、単項マイナス演算子のオーバーロードには、negateというキーワードを使用する必要がある。

class C
{
    C operator - ( C other ) => this ; // binary minus
    C operator negate () => this ; // unary minus
}

main()
{
    C c = new C() ;

    c - c ; // binary minus
    -c ; // unary minus
}

これは恐らく、パースを高速にするためであろう。operator -と読み込んだならば、その時点で、それは二項マイナス演算子のオーバーロードであると決定できる。

例えば、Dartには正規表現ライブラリがあるが、正規表現リテラルは存在しない。これも、パースを高速に行うためであろう。そのかわりに、DartにはRaw String LiteralやMultiline string が存在する。

// Raw string literal
@"\n\r\f" ; 

// Multiline string
"""もんちゃらへっぴー
もけもけさー""" ;

まだ書きたいことは様々あるのだが、ともかくDartの規格書をすべて読んでしまわないことには、詳しい説明をすることができない。Dartを批判する前に、まず規格書を読んでみるべきである。今の実装はまだ不完全で、バグも多い。言語を実装によって判断するのは愚か者のすることである。とにかく重要なことは、Dartは今世紀最高のプログラミング言語であり、輝かしい未来が約束されているということだ。

デニス・リッチー逝去

Rob Pike - Google+ - I just heard that, after a long illness, Dennis Ritchie…

Steve Jobsより、こっちの方が大ニュースだ。しかし、リッチーは世界に多大な影響を与えたにも関わらず、あまり表にでない人物であった。もしリッチーがいなければ、今日のプログラミング言語は、かなり別の文法を使っていたかもしれない。

2011-10-12

Dartすごい。マジすごい。美しい

Dart : Structured web programming

というわけで、Dartが発表されてからこのかた、Dartの規格を読んでいたのだが、これはすごい。マジですごい。ヤバイほどすごい。美しすぎる。

私が多少なりともかじっている言語は、C++とJavascriptとアセンブリである。私は、もうこれ以上、学びたいと思う新言語が出てくるとは思っていなかった。たしかに、C#はWindowsでアプリを作るには面白そうだし、PythonやらRubyやらは、かなり人気だ。しかし、これらの言語を学びたいとは思わなかった。昔、Schmeに興味を持ち、SICPを買った。しかし、未だ綺麗なまま、本棚の中に眠っている。Haskellに興味を示したこともあったが、やはり最初の感動が覚めると、学ぶ気にはならなかった。つまりは、わざわざ学ぶほどの魅力がなかったのだ。しかしどうやら、私は間違っていたようだ。Dartが来た。

Dartは美しい言語である。規格書を読むと、その美しさが一目瞭然である。従来のどの言語にもない完璧なまでの美しさを備えている。

Dart Programming Language Speci cation

まず、規格書が短い。現在のドラフトは、たったの78ページしかない。この規格書は、コア言語だけを定義している。この短さには理由がある。Dartのコア言語は、美しいほどにシンプルだからである。

たとえば、Dartには、暗黙の型変換が、boolean conversion以外に存在しない。Javascriptのように、改行が文脈によっては終端記号と解されるような仕様もない。この美しい言語を設計したのは神ではなかろうか。よくぞここまで思い切ったものだ。

ときくと、そんな厳格な言語がWebのクライアント言語として使えるはずがないと思う人もいるかもしれない。実は、暗黙の型変換のチェックは、コンパイルエラーとはならない。静的型警告(static type warning)が発せられるだけで、コンパイルには影響を及ぼさない。たとえば、

void main
{
    int x = 0.1 ; // static type warning
    print("${x}") ;
}

これは、静的型警告を出すが、コンパイルや実行には、何の影響もない。もちろん、出力も、0.1である。これは、あたかもvar x = 0.1 ;と書いたかのように振る舞う。

記述は厳格に、実行は寛容にというのが、過去に成功したWeb上でのクライアント言語に共通する理由である。HTML然り、Javascript然り。Dartはこの点からみても、失敗する余地はない。

コア言語側には、組み込み型というものがない。intやdoubleといった基本的な型でさえも、ライブラリである。

そして重要なことに、DartはJavascriptの代替として、Chromeに組み込まれることが決定している。もちろん、DOMも使える。

とにかく、Dartは信じられないほどに美しい言語だ。早くこの言語でプログラミングがしたい。Dartが使えるようになれば、Javascriptなどは即座に絶滅してしまうだろう。

おいおい、オメーのブラウザ、Dartも使えねーのかよ。さっさとDartが使えるブラウザーにしろよ。

下駄の鼻緒が切れた

「下駄の鼻緒が切れると縁起が悪い」という迷信があるが、あれは迷信などではなく、事実である。

私はここ二年ほど、下駄を愛用している。何故いまどき下駄なのかと不振に思う人もいるだろう。これは、特に下駄を履くことによる不利益がないからである。

まず、下駄の値段は数千円であり、通常の安い靴と何ら変わりない。私の使用頻度では、下駄は一年ほど使えるので、この点においても、安物の靴と何ら変わりない。走るのではなく、長距離を行くのでもなければ、靴と比較した場合の不利益がほとんどないと言って差し支えない。

唯一の不利益といえば、下駄を履くと足が汚れるので、玄関先で足を洗ってから上がらなければならないことぐらいだ。歌舞伎や昔の時代劇などで、家に上がる前に、足を拭く動作がみられるのも、このためである。

ところで、今朝、下駄を履いて歩いていると、突然、下駄の鼻緒が切れた。見ると、下駄の歯があまりにも擦り切れていて、鼻緒をかけている縄が地面に接触するようになったため、次第に縄がすり切れていき、とうとう切れたらしい。以前の下駄は、そうなるまえに下駄の歯が完全にすり切れてしまったので、鼻緒が切れる前に買い換えたのだった。

当然、その場で思い当たったのは、「下駄の鼻緒が切れると縁起が悪い」という迷信である。今日、私は、この迷信が、実は事実であるということを身を持って思いしらされた。

下駄の鼻緒が切れたせいで、その下駄を履いて歩けなくなってしまったのだ。仕方なく、私は下駄を脱ぎ、裸足で歩いて帰らざるをえなかった。この不便は、下駄の鼻緒が切れたという事象によってもたらされたものである。下駄の鼻緒が切れたという直接的な理由で不便を被ったのだから、「下駄の鼻緒が切れると縁起が悪い」という迷信は、実は正しいと言える。

2011-10-07

欧陽修の未発見の書簡、発見さる

日本で宋・欧陽修の書簡…中国で「盗んだ」、「韓国でなくて幸い」 2011/10/06(木) 17:38:42 [サーチナ]

九州大大学院比較社会文化研究院の東英寿教授は3日、宋代の政治家で詩人・文筆家として知られる欧陽修の書簡96篇を発見したと発表した。中国でも同ニュースは報じられた。かつては「13世紀に鎌倉幕府が設立した金沢文庫が収蔵していたもの」と紹介されたが、「日本が中国から盗んだものだ」などのコメントが寄せられた。「発見されたのが韓国でなくて幸いだった」との書き込みもある。

天理大学付属天理図書館が所蔵していた1191-96年に編纂(へんさん)された欧陽修全集「欧陽文忠公集」に、これまで知られていなかった欧陽修の書簡96篇が掲載されていた。同「公集」は木版による原刻本。中国国家図書館や日本の宮内庁も所蔵しているが、天理図書館所蔵の原刻本は、編纂作業が終わってから、抜け落ちていた書簡を追加した版であるとみられる。

環球網などの記事は「(日本側が古い時代に)中国で購入し、13世紀に鎌倉幕府が設立した金沢文庫が収蔵していたもの」「日本では国宝に指定」などと紹介したが、コメント欄には「日本が戦争中に中国から盗んだものだ」、「中国の文化財だ」などの書き込みが相次いだ。

「幸いなことに、(発見場所は)韓国でなかった」などと主張する書き込みも多い。「『欧陽修は韓国人だった』とされてしまう可能性が100%」だからという。

どうせ中国にあっても度重なる革命や、記憶に新しい文化大革命で焚書されてるだろうに。それにしても、このニュースは自己言及的である。なにしろ、あの欧陽修である。あの日本刀歌をつくった欧陽修である。

徐福行時書未焚
逸書百篇今尚存
令厳不許伝中国
擧世無人識古文

2011-10-06

スティーブ・ジョブズ死亡

Apple - Remembering Steve Jobs

Apple社はヴィジョンとクリエイティビティあふれる天才を失い、世界は驚嘆すべき男を失った。幸運にも彼を知り、ともに仕事をした者は、最良の友であり師でもある人物を失った。スティーブは彼以外に成し遂げられぬ会社を後にして旅立った。彼の魂は、Apple社に生き続けるであろう、永遠に。

スティーブ・ジョブズ:自分の立ち上げた会社をクビになったが、後に買収しなおした、世界一カリスマのあった男。すい臓がんにより2011年に没す。享年五十六歳。

非staticデータメンバーの初期化子

今月にビルドされたgcc4.7で対応していることを確認。

struct S
{
    int member = 123 ;
    S() = default ;
    S( int value ) : member(value) { }
} ;


int main()
{
    S s1 ; // s.member == 123
    S s2(456) ; // s.member == 456
}

なお、非staticデータメンバーの宣言にauto specifierを使うことはできない。これは、auto specifierが、ブロック、名前空間スコープ、for文の初期化句にしか使われてはならないとされているためである。

struct S
{
    auto member = 0 ; // error
} ;

ちなみに言っておくと、staticデータメンバーにはauto specifierを使うことができる。これは、staticデータメンバーが、実は名前空間スコープであるからだ。staticデータメンバーは、クラス定義の中に書かなければならないとか、クラス名による修飾をしなければならないなどの制約はあるが、名前空間スコープに属する名前である。

struct S
{
    static auto const member = 0 ; // OK, type is determined to be "const int"
} ;

もちろん、staticデータメンバーに初期化子が許されているのは、constなリテラル型だけであるので、autoがそれ以外の型に推定された場合は、エラーとなる。

struct S
{
    static auto member = 0 ; // Error, the type of static member is not const literal type.
} ;

ちなみに、gccには七ヶ月前、上記のコードを通してしまうバグがあったが、バグレポートを送ったところ、現在では修正されている。

2011-10-03

花粉症?

ここしばらく、体はだるくないし熱もないが、謎のくしゃみと鼻水と目のかゆみに悩まされている。一日中というわけではなく、起きた直後がひどいように思われる。

さて、思いつく病気は花粉症だが、果たして。

2011-10-01

火の用心に効果はあるのか

毎年この時期になると、拍子木をやかましく打ち鳴らして「火の用心、火の用心」と叫ぶ集団が出現する。果たして、あれはなにか意味があるのだろうか。あれを聞いたことで、用心を心がける人間が、果たして存在するのだろうか。近所迷惑だとは思わないのか。

目の前に火鉢や囲炉裏がある時代は知らず、現代では、常に火を灯している場面は、少なくなっている。

たとえば、電子機器や配線からの発火は、少なくとも発火するまでは、火は存在しない。それに、発火するまで事前の兆候がなく、またコレといった対策も取りづらい問題である。

そもそも、現代の火災の原因の最上位は、「放火」である。

参考:総務省消防庁

放火は、いくら個人が用心しようとも防ぎようがない。ある人間が火をつけようと考えたならば、その手段を手に入れるのは、この日本ではたやすいことであるからだ。

次いで、「たばこ」が原因としてあげられる。これは、用心できる種類の原因である。

ということは、あの集団は「火の用心、火の用心」と叫ぶよりも、「禁煙、禁煙」と叫んだほうが効果的ではないだろうか。

それにしても日本は、廃品回収といい、古紙回収といい、騒音に対する規制が緩いように思われる。

ついさっきも、家の前を「火の用心」と叫びつつ通過する集団がいたので、このような疑問をぶつけてみた。彼らの言い分は、実に不思議である。

私「何故このようなことをしているのか、近所迷惑だとは思わないのか」
翁「町内会で決まっている。学校からも要請がある」
私「それで何の疑問も抱かずやっているのか」
翁「そうだ」
私「誰が決めたのか」
翁「町内会の代表である私が決めて、私がやっている」
私「自分で決めて自分でやっているのか」
翁「町内会で誰も反対しなかった」
私「そもそも、効果があるのか」
翁「ついこの間もこの近所で火事があって云々」
私「それで効果はあるのか」
翁「これを聞いて用心する人が少しでもいればそれでいい」
集団「この人頭おかしいんやわ、ほっといていこいこ」

集団は、なおも質問しようとする私を、「頭がおかしい」と言い捨て、過ぎ去っていった。この翁は、いつも家の前でタバコを吸っている翁である。ために、公道が煙たくてしょうがない。火災の原因No.2の喫煙者が火の用心を叫ぶのは不思議だ。