「静的型付けが出来るJavaScriptの上位言語」を触ってみよう。パート5 - Dart

このシリーズもパート5。

静的型付けができJavaScriptへコンパイルできる言語をちょろりと触ってみようシリーズの最終章です。

とうとうやって参りました。Dart。

なぜ私がDartを推すかは最後に記載します。

じゃいってみましょ

Dart

http://www.dartlang.org/

ナニモノかね?

そもそもDartはDartVM上で動作する言語であることが主体 JavaScriptへのコンパイルはおまけ(?)的位置付け

"おまけ"はちょっと言い過ぎな気がしますが、後述する内容のポイントなので大げさに表現しています。

本日の見出し

コンパイラインストール

  1. sdkダウンロード
  2. 解凍してパスを通す

以上、DL&詳しくはこちら

  • MacOS以外でも同じような感じだと思う(たぶん)
  • MacOSの場合brewからもインストールできるが、バージョンが少し古かったので手動インストール
  • brew使う場合、brew install dartでOK

今回も頑なに「エディタ + コンパイラ」です。本来はDart EditorなるIDEを使うほうがよろしいかと

コンパイルしてみる

今回のテーマはあくまでJavaScriptとして使用することなのでJavaScriptへの変換を試みる。

DartVMが搭載されているブラウザであればコンパイルは必要ないのだが、現状DartVMを搭載しているブラウザはDartiumしかなく、このブラウザをメインで使っているユーザは恐らくいない。。 必然的にブラウザ上で動作させるのであれば「JavaScriptへ変換」せざるを得ない。

.dartJavaScriptへ変換するためにはDartSDKに同梱されているdart2jsというコンパイラを使用する

DartもHaxe同様JavaScriptコードはコンパイルできない

  • Haxeとの違いとしてMainクラスの定義は必要ない模様

sample.dart

main() {
  print('Hello, Dart!');
}

コンパイル

$ dart2js sample.dart
Dart file sample.dart compiled to JavaScript: out.js

オプションとしてなにも設定しない場合は、out.jsと言う名前のJavaScriptファイルに結果を出力する

  • 出力結果JavaScriptは壮絶なものとなる為割愛
    • --minifyオプションもあるがmainメソッドに関してはあまり変わらない
    • dart2jsを使用して出力するJavaScriptはもはや後からJavaScriptとして改修できるものではない
  • 出力したJavaScriptはnode.jsでの直接実行不可
    • html上で読み込まれることを想定したJavaScriptが出力される
    • 自身は動作確認用のhtmlファイルを用意して確認した。

クラス定義

class Sample {
    String name;    // プロパティ

    Sample(String name) {   // コンストラクタ
        this.name = name;
    }

    void say(String greet) {    // 引数型指定
        print('${greet} ${this.name}');
    }

    String getName() {      // 戻り値型指定
        return this.name;
    }
}

main() {
    Sample sample = new Sample('dart');
    sample.say('Hello');
    print('name: ${sample.getName()}');
}
  • 変数名の前に型を定義するあたりがJavaっぽい
  • やっぱり同名メソッドでのオーバーロードはサポートされていない
  • コンストラクタは単純なプロパティ初期化であれば以下のように定義を省略できる
Sample(this.name);
  • 同一型の変数はまとめて宣言可能
num x, y, z;

クラス定義とは関係ないが文字列内の${...}は実行時に展開される

継承はもちろんのこと、Javaライクなインターフェースやジェネリクスの継承関係も表現できる。

abstract class Client {     // インターフェース
    int execute(String arg);
}

class MockClient implements Client {
    int execute(String arg) {
        print('execuet: ${arg}');
        return 0;
    }
}

class User<C extends Client> {    // 継承関係を持ったジェネリクス

    C client;

    User(this.client);

    void action() {
        client.execute('hogehoge');
    }
}

main() {
    new User<MockClient>(new MockClient()).action();
}

↑にも書いたが、TypeScript, HaxeとくらべてJavaっぽい。 Javaになれたエンジニアなら馴染みやすそうだ。

Haxe同様、JavaScriptを書いていると言う感覚は皆無。 この点に関しては同様のメリット・デメリットがありそう。 (Haxeについては前回の記事参照)

その他Dartの言語仕様はこちら

外部JavaScriptライブラリの使用

いろいろ調べたが、外部ライブラリの使用方法は見当たらなかった。 機能としてJavaScriptライブラリの読み込みは提供されていない模様。

もし使用したいライブラリがあれば完全にDartコードに書き起こす必要がある。

Dartはデフォルトで様々なAPIが提供されており、これを使用することでだいたいのことはまかなえる(??)

Dart API Reference

Dartium

冒頭で紹介した通り、DartはDartVM上で動作する言語、 ChromiumにDartVMを搭載したブラウザがDartiumである。

Wiki等によると、今後Google ChromeにもDartVMが組み込まれる予定らいしい。

Dartium上ではDartコードはJavaScriptに変換することなく実行できる。

html上でDartコードを読み込む為には以下のようなタグを定義する

<script type="application/dart" src="time.dart"></script>

また、併せて以下のタグも定義する必要がある

<script src="https://dart.googlecode.com/svn/branches/bleeding_edge/dart/pkg/browser/lib/dart.js"></script>

折角なのでどのくらい実行速度が違うのかdart2jsで出力したJavaScriptと比較してみます。

time.dart

main() {
    String text = '';
    DateTime now = new DateTime.now();
    for(int i = 0; i < 10000; i++) {
        text = '$text$i';
    }

    print(new DateTime.now().millisecondsSinceEpoch - now.millisecondsSinceEpoch);
}
  • 10000回文字列結合を繰り返した後のスタートエンドのタイムスタンプ差分出力

結果

  • dart: 71ms
  • dart2js: 3ms

うん。JavaScriptの方が早い。

この結果をもってどうこう言う気はない

ちなみにdartコマンドで実行した場合は65ms


Dartを簡単に紹介しました。が、今回の内容はあまりDartのメリットを感じて頂けなかったかと思います。。。

しかし、自身はDartに注目しています。

なぜかと言うと。

ここまでJavaScriptへ変換できる別言語をざっと触ってきましたが、実開発を想定した場合、コンパイル後のJavaScriptを何かの都合で少しでも触ってしまう(手を加えてしまう)ようなことがあれば、その時点で変換と言うプロセスは破綻します。

なぜ触ってしまうのか、それはさわれてしまうからです。 これまで紹介したアプローチは全て別言語からJavaScriptを出力する方法です。 JavaScriptはもちろんヒトが編集することを想定したプログラミング言語です。 だからさわれてしまうのです。

(もちろんプロジェクトの厳格なルールとして触らせなければいいのですが、それは置いといて)

Dartのアプローチは、そもそもJavaScriptを出力することを目的としていません。 JavaScriptの代わりになることが目的です。

JavaScriptが大変素晴らしい言語であることはもちろんのことです。

しかし昨今、JavaScriptは利用シーンや開発規模の変化から様々な問題も発生しています。

このシリーズで紹介したアプローチもその問題の解決方法の一部ですが、更にDartはこれらの問題を根本的に(言語仕様から)解決しようとする試みであると感じています。

静的言語からJavaScriptを生み出す仕組みではなく、静的言語をブラウザ上で実行してしまおうという試みなのです。

この試みが正しいかどうか、また成功するかどうかはわかりませんが、単純な話、上述した通り、結局編集できないのなら出力結果はプログラミング言語である必要はありません。

このことを考えればDartのアプローチはすごく自然な考え方で、それを実現しようとしているところに面白みを感じています。

本日参考にさせていただいたサイト

今回も本文には掲載しておりませんが、とても参考になりました。Dartの魅力をより詳しく紹介されています。

今回シリーズを通して「静的型付けが出来るJavaScriptの上位言語」(の本当に断片)を紹介してきました。

今後クライアントサイドのプログラムはますます増加します。

大量のソースコードを大人数で実装するような場合、静的な型解決がうむメリットは絶大です。

このシリーズで挙げたような言語は、今後かなり大きな意義を持つようになると自身は感じています。

「クライアントサイド != JavaScript

時代が変わろうとしているのかもしれませんね。