Recently in ActionScript 3.0 Category

Action Script 3 用スペルチェックライブラリ (コードネーム Squiggly) の最初のプレビューリリース版が Adobe Labs に公開されました。(Squiggly@Labs

Squiggly を使った簡単なデモが Adobe Labs に公開されていますのでまずはそちらをご覧ください。(Squiggly demo) フィールドがフォーカスされるとスペルチェックが行われて間違いのある単語には赤い下線が表示されます。また、下線の引かれた単語で右クリックすると修正候補が表示され選択することができます。実行には Flash Player 10 が必要です。

Squiggly のダウンロードページはこちらです。(Squiggly downloads) ASDoc は別途提供されています。(squiggly_p1_asdoc_092109.zip : 72KB)

Squiggly の使い方

ダウンロードしたパッケージに含まれる AdobeSpelling.swc をパスに追加すると Squiggly が使えるようになります。下は、Squiggly を使ってスペルチェックを行うコードの例です。

import com.adobe.linguistics.spelling.*;
 
// スペルチェック用オブジェクト生成
private var _sp:SpellChecker= new SpellChecker("en");
 
// 辞書オブジェクトの生成
private var _dict:SpellingDictionary = new SpellingDictionary();
 
// イベントハンドラの追加と辞書データファイルの読み込み
_dict.addEventListener(Event.COMPLETE, handleLoadComplete);
var myUrl:URLRequest = new URLRequest("usa.zwl");
_dict.load(myUrl);
 
// 辞書をスペルチェック用オブジェクトに設定
private function handleLoadComplete(evt:Event):void
{
  _sp.addDictionary(_dict);
}
 
private function checkWord(word:String):Boolean 
{
  // スペルチェックを実行
  if(_sp.checkWord(word))
    return true; // エラー無し
  else
    return false; // エラー有り
}
 

このサンプルでは Squiggly のクラスが 2 つ使われています。スペルチェックを行うクラス SpellChecker と、スペルチェック用辞書データを保持するクラスの SpellingDictionary です。

SpellChecker は間違ったスペルの単語に対して修正候補のリストを作成するメソッド getSuggestions() も持っています。getSuggestions() は最大 10 件までの候補を配列として返します。候補が見つからなければ空の配列が返されることになっています。

下のコードは、とりあえず getSuggestions() の使用例ということで。

Flash Player 10 から動的に生成したサウンドを再生する機能がサポートされています。ベータ 2 で変更された点などもありますので遅ればせながらご紹介します。

まず、この機能を使うには Sound オブジェクトに Event.SAMPLE_DATA のイベントハンドラを設定します。そうすると Sound オブジェクトの動作が通常と変わり、定期的にイベントハンドラを呼び出しては再生するデータを読み込むようになります。このとき SoundChannel は読み込まれたデータを一連のオーディオデータストリームとして再生します。

var mySound:Sound = new Sound();
mySound.addEventListener(Event.SAMPLE_DATA, onSampleData);
var myChannel:SoundChannel = mySound.play();
 
function onSampleData(event:SampleDataEvent):void 
{
  // この中で SoundChannel にデータを書き込む
}
 

SAMPLE_DATA 用イベントハンドラ内では、イベントオブジェクトから渡される ByteArray オブジェクトにオーディオデータを書き込みます。イベントオブジェクトの型は Flash Player 10 から新しく追加された sampleDataEvent で、以下の属性が利用できます。

public data : ByteArray   // オーディオストリーム内のデータ
public position : Number  // オーディオストリーム内の位置
 

ByteArray オブジェクト (event.data) に書き込む値は 32 ビット big endian 浮動小数点数形式の 44.1KHz ステレオデータです。従って一つのサンプルデータの大きさは 8 バイト (4 バイトのデータが左右それぞれ) になります。

下は sampleData イベントハンドラの例です。単純なサイン波形をデータとして書き込んでいます。再生すると聴覚検査で聴くような音がすると思います 。

既に一部で伝えられているように、先週 ECMA TC39 から次期 ECMAScript 標準に関するアナウンスがありました。

Flash Player 9 の発表以来、Adobe は ActionScript を ECMAScript 標準第 4 版として提案された ECMA-262 Edition 4 (ES4) に完全準拠させるという目標を公にしてきました。この ES4 は、Adobe, Mozilla, Opera, それから Google を主要なサポーターとして標準化が進められていましたが、一年ほど前に Microsoft と Yahoo! 主導で ECMA-262 Edition 3.1 (ES3.1) のワーキンググループが開始されて以来、2 つの異なる ES3 後継仕様案が並存する状況が続いていました。

先週の発表は、ES4 に関する標準化作業を中止し ES3.1 に集中することが決定されたというもので ECMAScript Harmony プロジェクトと名付けられています。ES3.1 は ES4 のサブセットではありません。つまり AS3.0 は ES3.1 非互換になるということです。例えば ES3.1 の仕様には namespace や package は含まれません。これらの機能は ES3.1 以降の拡張に際しても含まれないことがはっきりと述べられています。また、型指定や継承といった機能の採用については (そもそも class の定義自体が異なるのですが) 今後の議論を待つことになります。JS1.7 や JS1.8 として Firefox 2, 3 に追加された機能も Harmony 路線では見直されるようです。

この件に関して Adobe からの正式なコメントはまだありませんが、Adobe のオープンソースチームのディレクターである Dave がコメントを blog に公開しています。(Standards, ECMAScript and representing the past

要約すると、

  • ECMAScript 標準化委員会参加企業の利害の不一致により仕様の一本化が難しい状況になっていた
  • Web に共通の言語を持つことが必要という観点から Harmony に賛同する
  • その上で、Web の革新を更に進めるため ActionScript の拡張は続ける
  • オープンソースコミュニティ活動の継続・発展も標準化委員会との活動と同様に重要

ということで、ECMAScript の標準化には引き続き参加する一方 ES3.1 のレベルまで AS3 の機能を戻すということは考えられていないようです。(blog 記事に対するコメントには、これを機会に ECMAScript 準拠をやめちゃえというものもいくつか見られました - 例えば private コンストラクタや関数オーバーロード機能の実装など...) 既に多くのユーザに使用されている言語を、その可能性を制限する方向で変更するのは Adobe の理念に反すると Dave としては思っている様。

いましばらく、正式なコメントの発表はお待ちください。

Flash Player 10 ではローカルファイルを直接 Flash アプリケーションに読み込んだり Flash アプリケーション内のデータを直接ローカルファイルに書き出す機能が追加されています。

Flash Player 9 でも FileReference を使ってローカルファイルにアクセスすることは可能です。が、その機能はファイルのアップロード/ダウンロードを行うためのもので、Flash アプリケーションからは、一旦サーバを経由しないとローカルファイルのデータを扱うことができませんでした。直接ファイル I/O の出来る日が来ることを心待ちにしていた方も多いことでしょう。

というわけで、Flash Player 10 では flash.net.FileReference クラスに以下の API が追加されています。

public function get data():ByteArray // 読み込まれたデータ (読み取り専用のプロパティ)
public function load():void          // 指定されたファイルの読み込み開始
public function save(data:*, name:String = null):void 
                                     // 保存先を選択するダイアログを表示、その後データ保存開始
 

ファイルの読み込みを開始するには load() メソッドを使用します。読み込むファイルの指定は、browse() メソッドを呼ぶとダイアログが表示されるので、その中でユーザが行います。

このときプログラムから読み込むファイルを指定することはできません。これは SWF がロードされたら勝手にローカルファイルを送信してしまうといった類のアタックからユーザを保護するためです。

load() は呼び出されるとすぐに戻るので、その後の進み具合はイベント経由で確認することになります。このあたりは従来の FileReference の使い方と同じです。

下は、ファイルを読み込む簡単なサンプルです。

最近質問を受けたので見てみたら Flash のヘルプドキュメントが古いのに気づいたので今日はこの話題です。(LiveDocs の AS3 リファレンス は最新です)

さて、まず下の例を考えてみます。

var foo:Boolean = true;
var bar:Object = {};
 
trace(foo && bar);  // 論理積 : 出力は [object Object]
trace(foo || bar);  // 論理和 : 出力は true
 

論理積と論理和の結果は、演算子の左側の式 (この場合は foo) の値で決定されます。ごく単純化すると、ルールは

論理積 (&&) : 左側の式が false なら左側の式の値、true なら右側の式の値
論理和 (||) : 左側の式が true なら左側の式の値、false なら右側の式の値
 

です。つまり、実際に論理演算が行われているわけではないのですね。演算結果の値も Boolean 型になるとは限りません。

さて、AS3 のプログラムでは Boolean もオブジェクトなので、左側の式を評価した後その値の型が何であっても同じルールを適用することができます (されます)。とにかく左辺の式を評価したら、結果を Boolean 型に変換して値を参照します。

それぞれの型を Boolean 型に変換した場合の値は以下のようになります。

まず、Adobe Labs に Flash Player 10 ベータの ASDoc が公開されています。(flashplayer10_as3langref_052008.zip: 6.46MB) それから、Flash Player 10 用 Flex SDK の Nightly Build (安定していないビルド) がダウンロードできます。(Flex 3 SDK Downloads) May 15 以降のビルドをダウンロードすれば Flash Player 10 の新しい機能を使ったアプリ開発ができます。

さて、今日の本題です。既報のとおり、Flash Player 10 には新しい高機能なテキストエンジンが搭載されます。上でご紹介した ASDoc には flash.text.engine というパッケージ (FTE と呼ばれています) が追加されていますが、縦書きやマルチカラムといった新しい機能を利用するには、この FTE の API を使うことになります。

ところが、FTE は低レベルの API なので、これを使いこなすには新しいテキストエンジンの構造をきちんと理解する必要があります。つまり、 かるく試してみるにはちょっと敷居が高いのです。

そのため、もう少し簡単にテキストフォーマットを記述するための新しいマークアップ言語が提供される予定です。

前回の続きです。なぜ "" == foo が true と評価されるのか、まず、暗黙の型変換が行われる際のルールを一つ確認します。

暗黙の型変換の基準

暗黙の型変換が行われる際の基準となる型は、変数に関連付けられた型注釈ではなく、値であるオブジェクト自体の型です。ですので変数の型に注目していても暗黙の型変換の結果は分かりません。

例えば、今回問題になっている例 foo:Object = 0 では、値である 0 の型が暗黙の型変換の基準になります。foo の型ではありません。そのため if 文の条件は文字列とと数値の比較として扱われます。

var foo:Object = 0;
if ("" == foo) { // 実際には "" == 0 が評価される
  trace("foo is null String");
}
 

そうすると、今回のケースでは "" と 0 が等価であるかどうかが評価されていることになります。

今回は AS3 の型システムの特徴についての話です。strict モードの人には関係ない話が続きましたが、ここからはコンパイラの環境設定に依存しない話題です(たぶん)。

まず、下のコードについて考えてみます。 オブジェクト型の変数 foo に数値の 0 を代入して空文字列と比較しています。

var foo:Object = 0;
if ("" == foo) {
  trace("foo は空文字列です");
}
 

上の If 文は空文字を検出するためのものに見えますが、実際にはこれを実行すると ”foo は空文字列です” が表示されます。

この結果は予想通りだったでしょうか?想定外だった人はこの先を。

上記の結果は、AS3 が弱い型の性質を持っているために起こります。AS3 では ’+’ 等のオペレータに対して複数のデータ型が混在すると処理の前に暗黙の型変換が行われます。これによって例えば trace("count:" + 0) のように文字列と数値を”足して”もそれらしい結果を得ることができるわけです。

暗黙の型変換は上の trace() の例のようにしばしば便利な機能として使われますが、一方で予期せぬ結果になるケースもある面倒なものだったりもします。例えば、この記事の最初に挙げた例も暗黙の型変換の結果によるものですが、実際にどのような変換が行われて true と評価されたのかは直感的には理解し難いものです。

前回に引き続き変数宣言の有無による違いを少し追求してみたいと思います。今回はパフォーマンスの違いについてです。よく知られている話だとは思いますがいちおう。

変数宣言の有無とパフォーマンス

まずは、以下のコードを考えます。Date のオブジェクトを生成して getTime() メソッドを 10 万回呼び出しています。変数宣言は行われていません。

date = new Date()
for (i=0; i<100000; i++)
  date.getTime()
 

手持ちの環境で上のコードを実行してみます。すると、for ループの箇所の実行に約 470ms かかりました。

これを下のように変えてみます。2 行目で var を使った変数宣言を追加しています。それから for ループ内では、2 行目で新しく追加した変数経由でメソッドを呼び出しています。

date = new Date()
var dateVar = date  // 追加
for (i=0; i<100000; i++)
  dateVar.getTime()
 

こちらはループの実行に約 340ms かかりました。処理時間が 130ms 程短縮されています。

ちょっと前の記事 (AS3 で動的言語のススメ) に書いたように strict オプションを指定しないことで AS3 の記述の自由度は格段に上がります。とはいえ、”With great power comes great responsibility” の言葉どおり、選択肢が増えた分だけ、コードを記述する側の責任が大きくなることは意識しておく必要があります。

手抜きの書き方を勧めたことに少し責任を感じて、今回は var による変数宣言の有無による変数の振舞いの違いに少し触れてみたいと思います。

var 無し変数の初期化

Flash CS3 でも Flex でも AS3 コンパイラの厳密な型チェックのオプションをオフにすれば var 宣言無しで変数が使用できるようになります。例えば下のコードは問題なくコンパイルできます。

public class Foo
{
  public function setMyGlobal(val:int):void
  {
    i = val;
  }
  public function printMyGlobal():void
  {
    trace(i);
  }
}