2012年4月30日月曜日

UbuntuのUnityランチャーへDart Editorを登録する

このエントリーをはてなブックマークに追加
UbuntuのUnityランチャー(画面左側に表示されているアプリケーション ランチャー)へ Dart Editor を登録する方法です。


現在のところLinux版のDart Editorは、debパッケージではなくzipファイルとして配布されています。そのため、そのままではUnityランチャーへ登録できません。登録するためには、.desktopファイルを用意する必要があります。

ここでは次の環境で確認しました。
  • Ubuntu 12.04
  • Dart Editor (build 6943)

まず、Text Editorを起動します。


エディターに次の内容を入力ます。
[Desktop Entry]
Version=1.0
Type=Application
Terminal=false
StartupNotify=true
Icon=Dartを展開したパス/icon.xpm
Name=Dart Editor
Comment=Dart IDE
Exec=Dartを展開したパス/DartEditor
Categories=Development;IDE;
IconとExecに設定するパスは環境にあわせて設定してください。例えば、私の場合は /home/dart/Downloads にダウンロードしてその場所で展開しましたので、次のようになりました。


.desktopファイルについてより詳しくは知るには、Desktop Entry Specification (freedesktop.org)を参照してください。

入力できたらそのファイルを Dart Editor.desktop という名前で保存します。とりあえずDesktopに保存しましょう。


ただし、このままでは実行できません。実行するにはファイルの実行属性を設定する必要があります。保存したファイルを右クリックしてPropertiesを選択します。


プロパティのPermissionsタブで、Allow executing file as program にチェックを入れます。


これでもう一度 Dart Editor.desktop ファイルを見ると、アイコンが Dart のものに変わっていると思います。これをダブルクリックするとDart Editorが起動します。


Dart Editor.desktopファイルからDart Editorが起動できることを確認したら、Unityランチャーへ登録しましょう。まず、Dart Editor.desktopファイルを $HOME/.local/share/applications へ移動します。フォルダを開いてメニューから Go - Location... を選択するとパスが指定できますので、.local/share/applications を開きます。 applicationsがない場合は新規に作成します。ここへDart Editor.desktopを置きます。


最後に、UnityランチャーへDart Editorを登録しましょう。 $HOME/.local/share/applications へ移動した Dart Editor.desktop を、Unityランチャーへドラッグ&ドロップすると登録されます。Dart Editorを起動してから、Dartのアイコンを右クリックして Lock to Launcher を選択しても構いません。


これでUnityランチャーからDart Editorを起動できるようになります。

2012年4月23日月曜日

Dartでフィボナッチ数

このエントリーをはてなブックマークに追加
Dartの練習です。初期配列を与えてnacci関数を呼び出すと、そのフィボナッチ数列を返すクロージャーを返します。Dartboardで実行
nacci(List sequence) {
  int type = sequence.length;
  return calc(int n) {
    if (sequence.length < n + 1) {
      int value = 0;
      for (int i = 1; i <= type; i++) {
        value += calc(n - i);
      }
      sequence.add(value);
    }
    return sequence[n];
  };
}

void main() {
  var fibo = nacci([0, 1]);
  var tri = nacci([0, 0, 1]);
  var tetra = nacci([0, 0, 0, 1]);
  var lucas = nacci([2, 1]);
  for (int i = 0; i <= 10; i++) {
    print("$i : ${fibo(i)}, ${tri(i)}, ${tetra(i)}, ${lucas(i)}");
  }
}
実行結果:
0 : 0, 0, 0, 2
1 : 1, 0, 0, 1
2 : 1, 1, 0, 3
3 : 2, 1, 1, 4
4 : 3, 2, 1, 7
5 : 5, 4, 2, 11
6 : 8, 7, 4, 18
7 : 13, 13, 8, 29
8 : 21, 24, 15, 47
9 : 34, 44, 29, 76
10 : 55, 81, 56, 123

参考:wikipedia:フィボナッチ数

文字列と数値を変換する

このエントリーをはてなブックマークに追加
Dartで文字列(String)と数値(num)を変換するには次のようにします。

文字列から数値を得る

整数(int)を得る場合はMath.parseInt、小数を得る場合には Math.parseDouble を使います。サンプルコード
main() {
  int i = Math.parseInt("123");
  double d = Math.parseDouble("1.23");
  print("i=$i, d=$d");
}
変換に失敗するとBadNumberFormatException例外が発生します。

数値リテラルとして表現可能な文字列が変換可能なようですので、次のような変換もできます。サンプルコード
main() {
  // 大きな数(1e+30)
  print(Math.parseInt("1000000000000000000000000000000"));
  // 16進数(10)
  print(Math.parseInt("0xA"));
  // 指数表現(10)
  print(Math.parseDouble("1e+1"));
}

数値から文字列を得る

単純に文字列リテラルとして、あるいはtoStringメソッドで変換できます。
main() {
  int i = 1;
  print("$i, ${i.toString()}"); // 1, 1
}
書式を指定するにはnumクラスに用意されている次のメソッドを使います。

toRadixString
指定の進数の文字列
toStringAsExponential
指定した指数値を持つ文字列
toStringAsFixed
指定桁数の小数部を持つ文字列
toStringAsPrecision
指定精度の文字列

サンプルコード
void main() {
  print("123=${123.toRadixString(10)}(10)"); // 123(10)
  print("123=${123.toRadixString(16)}(16)"); // 7b(16)
  print("123=${123.toStringAsExponential(1)}"); // 1.2e+2
  print("123=${123.toStringAsExponential(2)}"); // 1.23e+2
  print("123=${123.toStringAsExponential(3)}"); // 1.230e+2
  print("123.45=${(123.45).toStringAsFixed(1)}"); // 123.5
  print("123.45=${(123.45).toStringAsFixed(2)}"); // 123.45
  print("123.45=${(123.45).toStringAsFixed(3)}"); // 123.450
  print("123.45=${(123.45).toStringAsPrecision(2)}"); // 1.2e+2
  print("123.45=${(123.45).toStringAsPrecision(3)}"); // 123
  print("123.45=${(123.45).toStringAsPrecision(4)}"); // 123.5
}

2012年4月17日火曜日

クラスのインターフェイスを利用する

このエントリーをはてなブックマークに追加
Javaでテストコードを書いたことのある人は、次のようなコードをたくさん書いたことがあると思います。
// テストコードを含む典型的なJavaのコード

// インターフェイス
interface IDuck {
  void quack();
}

// 実装クラス
class Duck implements IDuck {
  void quack() { /* ... */ }
}

// テスト用のモック クラス
class MockDuck implements IDuck {
  void quack() { /* ... */ }
}
本来、実装に必要なのはDuckクラスだけですが、自動テストのためにIDuckインターフェイスを作り、そこからテスト用のモック クラスを用意しています。モックを自動生成するライブラリもいくつかありますが、設定の手間が必要だったり、コードがJavaの言語仕様からみると不自然な感じになったりしてしまいます。(それでも便利ですが)

Dartでも同じように書くことはできますが、Dartではクラスをインターフェイスとして利用できます。つまり、モックを作るためにインターフェイスを用意する必要はなく、クラスから直接モック クラスを作ることができます。サンプルコード
// 実装クラス
class Duck {
  quack() => 'complicated enterprise n-tier quack';
}

// テスト用のモック クラス
// Duckクラスを実装(implements)する。
class MockDuck implements Duck {
  quack() => 'quack for testing';
}

main() {
  Duck duck = new MockDuck();
  print(duck is Duck); // true
  print(duck.quack()); // quack for testing
}
MockDuckクラスはDuckクラスを実装(implements)しています。もちろん、MockDuckではquackメソッドを実装する必要があります。

なお、この機能は、Dartboard(try.dartlang.org)では問題なく利用できますが、現在公開されている最新のDart Editor(ビルド6479、2012/4/12公開)では不具合があるため利用できません。すでに修正されていますので次のリリースから利用できると思います。

2012年4月11日水曜日

Dartをチェックモードで動かす方法(更新版)

このエントリーをはてなブックマークに追加
Dartの実行モードには、プロダクション モードとチェック モードがあります。プロダクション モードでは、変数の代入などについて型による制限はありませんが、チェック モードでは型のチェックがコンパイル時と実行時に行われます。

開発時はチェック モードで動作させ、製品リリース後はプロダクション モードで動かす、といった使い方が想定されます。

そのため何も指定せずにDartスクリプトを実行するとプロダクション モードで動きます。チェック モードで動かす方法は次のとおりです。

Dart Editorの場合

スクリプトの実行設定画面の Run in checked mode のチェックを入れます。



Dartboard (try.dartlang.org)の場合

画面左上にあるChecked Modeにチェックを入れます。


dart(Dart VM)の場合

--enable_checked_mode フラグを指定します。--enable-checked-mode や --enable_checked_mode=true でも同じです。
$ cat test.dart
main() { int a = 'a'; }
$ dart --enable_checked_mode test.dart
Unhandled exception:
type 'OneByteString' is not a subtype of type 'int' of 'a'.
 0. Function: '::main' url: 'file:///test.dart' line:1 col:18

frogc( Dart-to-JavaScript compiler)の場合

デフォルトで有効になっています。
$ cat test.dart
main() { int a = 'a'; }
$ frogc test.dart
test.dart:1:18: warning: type "dart:core.String" is not assignable to "dart:core.int"
main() { int a = 'a'; }
                 ^^^


こちらもどうぞ

2012年4月10日火曜日

Dartで未来(Future)の処理を実装する

このエントリーをはてなブックマークに追加
この記事の内容は古くなっていますので、新しい解説記事を書きました(2013/5/8)Future を使いこなす

Dartでは、「まだ受け取っていない(未来の)値をどのように処理するか」を記述することができます。

まずは逐次型処理から考えてみましょう。ひとつの処理が終わってから次の処理を行う逐次型処理は、次のように記述できます。
void main() {
  // 処理1
  // 処理2
}
このプログラムは、処理1が終わってから処理2が実行されます。処理2が処理1の結果を受け取って処理される(処理2は処理1の結果に依存している)のであれば、この順で書くしかありません。たとえば次のような例が考えられます。
void main() {
  double a, b;
  a = Math.random(); // 処理1
  b = a * 2; // 処理2
}
このプログラムは、処理1の結果であるaの値が定まらないと、処理2の結果であるbの値も定まりません。

ここで、処理1と処理2を別々に書きたい場合があります。つまり、例えば次のように書きたいということです。
void main() {
  // 処理2
  // 処理1
}
もしこのように書けるのであれば、処理1を別の関数やクラスに追い出すこともできます。しかし逐次型プログラミングではこのような書き方はできません。

まだ計算されていない未来の結果に対して処理を記述したいという要求は、処理1が複雑だったり、処理1の途中でエラーが発生する可能性があるような場合に出てきます。たとえば通信の入出力処理と、その結果を加工するような処理です。もし複雑な処理1とそれが終わった時の処理2を別々に記述することができるのであれば、見通しのよいプログラムを書くことができます。

このような要求はfutureと呼ばれるプログラミング パターンによって解決できます。DartではFuture<T>Completer<T>でこれを実現します。サンプルコード
void main() {
  final Completer<double> comp = new Completer<double>();
  final Future<double> fut = comp.future;
  fut.then((double a) {
    // 処理2
    double b = a * 2;
    print("b=${b}");
  });
  
  // 処理1
  double a = Math.random();
  print("a=${a}");
  comp.complete(a);
}
実行例
a=0.00013735424727201462
b=0.00027470849454402924
Completer<T>の型パラメーターTは、処理が終わったあとに受け取る値の型です。Completerのfutureプロパティで、そのCompleterで処理が終わったときに呼び出されるFutureのインスタンスが取得できます。このFutureインスタンスの型パラメーターもTになります。

処理が終わったらCompleterのcompleteメソッドを、処理結果とともに呼び出します。これによってFutureのthenメソッドに渡した関数が呼び出されます。

Futureを用いた実装では、処理2を処理1より前に書くことができています。このまま処理1を別の関数やクラスに持っていくこともでき、呼び出し側は処理2が終わったらその結果を受け取った時の処理だけを書くことができるようになるのです。


処理中のエラーを補足する

処理の途中で発生したエラー(例外)をFutureへ伝えるには、CompleterのcompleteExceptionを呼び出します。この例外はFutureのhandleExceptionメソッドで受け取ることができます。handleExceptionメソッドでtrueを返すと、そこで例外の処理が完了したことを通知します。サンプルコード
void main() {
  final Completer comp = new Completer();
  final Future fut = comp.future;
  fut.then((double a) {
    double b = a * 2;
    print("b=${b}");
  });
  fut.handleException((Object exception) {
    print("exception=${exception}"); // exception=Error!
    return true;
  });
  
  // 処理で発生したエラーをFutureに伝える。
  comp.completeException("Error!");
}

複数のFutureの処理を続けて行う

2つのCompleterが存在し、それぞれ処理が終わったところでなにかの処理を順番に行わせるためには、Futureのchainメソッドを利用します。この機能を利用すると、複数のCompleterで処理を行わせ、その結果を順次処理できます。

chainメソッドの戻り値として次に呼び出されるべきFutureを返します。
void main() {
  final Completer<int> comp1 = new Completer<int>();
  final Completer<int> comp2 = new Completer<int>();

  comp1.future.chain((int a) {
    print("a=${a}");
    return comp2.future;
  }).then((int b) {
    print("b=${b}");
  });

  // comp1とcomp2のcomplete順を入れ替えても結果は同じ。
  // a=1
  // b=2
  comp1.complete(1);
  comp2.complete(2);
}

結果を変換するFutureを作る

Futureのtransformメソッドを使うと、結果の値を変換して格納することができます。transformに変換処理を行う関数を渡して呼び出すと、その変換処理を伴うFutureが返ります。
void main() {
  final Completer comp = new Completer();

  // 単純なFuture
  comp.future.then((int a) { print("a=${a}"); });

  // 変換処理を伴うFuture
  final Future tf = comp.future.transform((int a) => a * 2);
  tf.then((int b) { print("b=${b}"); });
  
  comp.complete(1);
}
実行結果
a=1
b=2

複数のFutureの結果を待つ

複数のFutureがすべて完了するのを待つためにはFuturesのwaitメソッドを使います。Futureのリストを渡すと、すべてのFutureの完了を待つ新しいFutureが返りますので、そのFutureインスタンスに対してthenメソッドを呼び出します。サンプルコード
void main() {
  final Completer<int> comp1 = new Completer<int>();
  final Completer<int> comp2 = new Completer<int>();
  
  // 複数のFutureがすべて完了するまで待つ。
  final Future<List<int>> fs =
    Futures.wait([ comp1.future, comp2.future ]);
  fs.then((List<int> results) {
    // 結果をすべて表示する。
    for (int result in results) {
      print("result=${result}");
    }
  });

  // 完了
  comp1.complete(1);
  comp2.complete(2);
}
実行結果
result=1
result=2

Futureのプロパティ

Futureには結果や状態を知るためのプロパティが用意されていますので、これらの動作をよく理解することがFutureを使いこなすことにつながります。

なおここで処理中とは、completeあるいはcompleteExceptionメソッドが呼び出される前、正常終了後はcompleteメソッドが呼び出されたあと、エラー発生後はcompleteExceptionが呼び出されたあとのことです。
isComplete
処理中:false
正常終了後:true
エラー発生後:true
hasValue
処理中:false
正常終了後:true
エラー発生後:false
value
処理中:FutureNotCompleteException例外がスローされる
正常終了後:結果の値
エラー発生後:エラーの値(completeExceptionの引数)
exception
処理中:FutureNotCompleteException例外がスローされる
正常終了後:null
エラー発生後:エラーの値(completeExceptionの引数)

2012年4月5日木曜日

Windows版DartiumがDart Editorに同梱されました

このエントリーをはてなブックマークに追加
Dart Editorの最新版(ビルド6167)が公開され、Dart VMを搭載したWebブラウザDartiumが、Windws版Dart Editorの配布物にも同梱されるようになりました。これでLinuxやMacと同じように、Windowsでもフル機能を使った開発が行えるようになりました。

Linux版やMac版も新しいバージョンが公開されています。すでに使われている方も、ぜひ更新して使ってみましょう。

Dart Editorは公式サイトからダウンロードできます。

Tutorial: Dart Editor

ダウンロードしたファイルを展開すると、dartフォルダーの下にDartEditorの実行ファイルがありますので実行します。


Dart Editorのウィンドウが開きます。


サンプルのClockを開いてみましょう。


ツールバーの緑の矢印ボタンで実行します。


Dartiumが開いて実行されます。


Manage Launches(実行構成管理)にあるEnable debuggingのチェックボックスをチェックしてから実行すると、デバッグ実行ができます。


ブレークポイントを設定してステップ実行したり、


実行中のコードにある変数の値を見ることもできます。


どうでしょうか。とても便利に使える開発環境になってきたと思います。

2012年4月4日水曜日

DartiumのWindows版がダウンロードできるようになっています

このエントリーをはてなブックマークに追加
Dart VMを搭載したChromiumブラウザのDartiumですが今まではLinux版とMac版だけが公開されていて、Windowsで利用するには自分でソースコードからビルドする必要がありました。

最近になって、Windows版のDartiumもバイナリーがビルドされるようになり、公式サイトからダウンロードできるようになっています。

Chromium with the Dart VM


少し確認した限りでは、半月ほど前と比べて格段に安定して動くようになっています。

現時点ではDartium単体でダウンロードできるものの、Dartの開発環境であるDart EditorのWindows版にはDartiumは同梱されていません。しかしナイトリービルドではすでに同梱されるようになっていますので、近いうちにリリース版がダウンロードできるようになるでしょう。