2011-10-17

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を使う必要はない

}

2 comments:

Anonymous said...

切り捨て除算の演算子にはdivやremがよく使われてますね。記号ではありませんが中置記法です。

Egtra said...

BASIC言語だとそっちの除算にはバックスラッシュを使います。