2012年11月26日月曜日

JSXでグローバル変数を扱う際に気をつけること

ここで言うグローバル変数

一口にグローバル変数と言っても言語や環境によって意味が異なりますが,ここではWebブラウザ上でJavaScriptを扱う場合のグローバル変数を指すこととします.もう少し具体的に言えば,JavaScriptに於いてvarを付けずに利用した変数で,内部的にはwindow.変数名です.そして,JSXでグローバル変数を扱う場合には「js.jsx」をインポートした上で「var foo = js.global["foo"] as number;」のようにして使います(使用するグローバル変数がfooで,その型がnumberの場合).なので,グローバル変数fooを取得してコンソールに表示するプログラムは以下のようになります.

気をつけること 〜上書き代入してはいけません〜

上記のように簡単に値を取得できるので,ついつい代入したくなりますよね?ダメです.js.globalは代入には対応していません.正確に言えば,代入された瞬間からその変数はjs.globalではなく代入された値を保持します.以下のソースの7行目でfooに100を代入しています.8行目のようにfooを確認すると100と表示されるので一見上手く行っているように見えますが,9行目のようにjs.global[ "foo" ]を確認すると1が表示されます.

せっかくなので 〜クラス変数だと切り分けが面倒〜

実は上記が全てです.ですが,せっかくなので悩んだ軌跡を紹介します.クラス変数(static変数)と組み合わせるとデバッグが面倒になります.もちろん上記原則をきちんと分かっていれば良かったのですが,分かっていなかったばっかりに難儀しました.

元々やりたかったことは,グローバル変数を介してJSX以外で書かれたプログラムと連携することです.「もしかするとグローバル変数が初期化されていないかもしれないのでコンストラクタでnullかどうか判断して,nullだったら初期化しよう」としたのが間違いでした.以下のソースをご覧ください.3行目でクラス変数mapにグローバル変数globalを割り当てています(もちろん,本物のソースはglobalなんて変数名は使っていませんよ).と言う訳で,問題となったのは6行目です.見事に代入しちゃってます.おかげで,このJSXファイル内ではまともに動作するのに,他のJSとは連携してくれないという中途半端な状態になってしまいました.

試しに,以下のソースをコンパイルしてWebブラウザ上で実行して,コンソールからglobalの内容を表示させようとすると「ReferenceError: global is not defined」と表示されてしまいます.

普通やらないよね 〜安易にlogを使わない〜

通常ならばChromeのデバッガなどを使うところですが,そのときたまたま--enable-source-mapオプションを付けずに開発していたので,logを入れまくってデバッグしていました.その結果,動作しないことに変わりないけど,logの有無によって挙動が異なるようになりました.コンパイルされたJSファイルとにらめっこしながら,「これグローバル変数にアクセスしてないよな」などと考えながら,「logの有無による挙動の差」のほうが気になりだしました.既にプログラムは「js.global[ "global" ] = {}: Map.<string>;」を使って初期化すれば上手くいくことが分かっていました.

ますます???となってきたので思考をまとめるために「js.globalに書き込むとうまくいく」,「タイミングによって挙動が変わるのは$__jsx_lazy_initが原因か?」とtweetしたところ,@__gfx__様から「js.globalに書き戻すことが必要」と「lazy initが悪さしているかも」との教えを授かりました(tweetの内容は短縮しています).

一緒にこちらのURLを授かったので参照したところ『最後の $__jsx_lazy_init の部分が曲者で、static 変数に対してリテラル以外で初期化すると $__jsx_lazy_init によって初期化されるようです。名前から想像がつくと思いますが、これによってこの変数が使われるときに初めて初期化が行われます。』と書かれていました.なるほど,logを入れまくると挙動が変わるわけです.上のソースで言うと,5行目と6行目の間に「log glb.map;」を入れた時だけ挙動が変化しました.

ちょっと疑問なのは,if文の条件式の中で参照していると思うのですが,そうではなさそうです.単に私の検証が足りないだけかな?

結論

色々書きましたが,「js.globalを代入した変数に対してさらに代入しない(配列に追加するのは大丈夫)」「代入したければjs.globalに直接代入する」「普通は問題にならないけど,デバッグ時のクラス変数の初期化のタイミングには気をつける」「デバッガを使う」「@__gfx__様の最初のtweetですでに答えが出ていたので素直に聞く」などを心がけましょう.

ちなみに上記のソースコードは以下のようにすればきちんと動作します.※これが最適な書き方かどうかについては責任を負いません.

最後に

@__gfx__様,助言をいただきありがとうございました.

このエントリーをはてなブックマークに追加

2012年7月1日日曜日

MacOS XにJSX環境を構築する方法

セカンドマシンにJSX

これまでに,MacOS Xに様々なソフトウェアを導入する記事を書いてきましたが,すでに情報が古くなっているのと,本日のJSX推しとして,マッサラな状態からJSXを導入する方法をまとめました.ほぼそのままのインストールログをつけておきますので,参考になれば幸いです.なお,ホスト名は「sahara」,ユーザ名は「suda」です.背景が濃いグレーの箇所が実際に入力する行です.

本日インストールするソフトウェアは,

homebrew 0.9.1

git 1.7.11.1

node.js 0.8.1

npm 1.1.35

JSX 0.0.1

です.

関連ファイルのインストール

まずはXcodeをインストールします.Lionを使用している人はMac App Storeからどうぞ.LeopardやSnowLeopardの人は付属CD-ROMに入っているようです.なお,SnowLeopardまでは開発に使う基本コマンドが出荷時からインストールされていたのですが,Lionからは手動でインストールが必要です.やり方は以下のとおりです.

  • Xcodeを起動する
  • 「Xcode」メニューから「Preferences...」を開く
  • 開いたウィンドウの上部のアイコンが並んでいるところで「Downloads」をクリックする
  • 「Command Line Tools」の右にある「install」ボタンをクリックして基本コマンドをインストールする
  • それでは,homebrewをインストールします.「sahara:~ suda$」はプロンプトです.実際のコマンドはsuda$よりも後ろです.1行目はURLが長すぎて折り返して表示されていますが,1行で入力してください.途中でenterキーの押下と管理者のパスワードの入力を求められるので指示に従ってください.

    メッセージを見ると「何かインストールする前に'brew doctor'を実行すべきだ」との指示があるのでそのとおりにします.すると,以下のようにエラーが起きてしまいました.どうやら/usr/local/share/manに書き込めないことが原因のようです.sudo付きで実行すれば良いのかな?と思いましたが,指示は「以下のディレクトリにchownすべきだ」なので,どうせならchmodしちゃえ(←後々弊害の出る可能性あり)と勢いでやってしまいました.

    続いてbrewをアップデートします.併せて,インストール後にバージョンを表示させておきます.

    以上でhomebrewのインストールが完了です.続いてgitをインストールします.

    次にnode.jsをインストールします.なんと,最新版の0.8.1がインストールされます.

    make installが表示されてからはコンパイル作業を行なっているのか,マシンパワーによってはそれなりに待たされます.諦めてしばらく待ってください.続いて上記7〜9行目のメッセージに従ってnpmをインストールします.

    ドキュメント周りでエラーが出ているようですが,とりあえず無視します.

    JSXのインストール

    以上でようやくJSXのインストールまでこぎつけました.インストール手順としては,github上のリポジトリの取得→セットアップ→PATHの設定です.環境が整っていればすぐに終わります.

    ブログ上でnpmのモジュールツリーが化けていますが,画面上ではきちんと表示されているはずです.後は~/JSX/binにPATHを通すなり,PATHの通っているディレクトリにjsxのシンボリックリンクを作成してください.通常は~/binにPATHが通っているのですが,Lionではそもそも~/binが存在しなかったので/usr/local/binにシンボリックリンクを作成する例を示します.※場当たり的対応なので,~/binを作成してPATHを通した上で,~/binにjsxのシンボリックリンクを作成することを勧めます.

    うまく設定できていれば,2行目のようにディレクトリ名を付けずに実行できます.

    それでは,MacでJSXを楽しんでください.

    このエントリーをはてなブックマークに追加

    2012年6月29日金曜日

    JSXによるガジェット開発 ー時計編ー

    ガジェット開発にもJSX

    JSXでのプログラミングにもだいぶ慣れてきたので,今回はちょっとしたアプリを作ってみたいと思います.俗に言うガジェットですね.手始めにガジェットの中でも定番と言える,時計を紹介します.

    時計を作ろうとして,こちら*1のtimer.jsx(タグ)を見ながらTimerを試し,その勢いでWeb版を開発しました.あまりに簡単で拍子抜けしました.これだけだと面白く無いので,さらに勢いに乗ってアナログ時計も開発しました.

    ディジタル時計

    あまり解説するような内容はありませんが,強いて言えば,繰り返す内容をまとめた関数を用意してください.上記プログラムでは7行目から15行目です.そして,16行目で関数fを100 [msec]毎に実行するよう設定しています.単純に動作させたいだけならsetIntervalの中に無名関数を定義しても構いません.後で繰り返し動作を止めたい場合は,関数にしておいてください.

    「時計は1秒に1回動けば良いので,100[msec]は過剰じゃないか?」と思われるかもしれませんが,実際にはちょっとずつずれる可能性があるので念には念を入れています.・・・と思っていたのですが,こちら*2によるとほとんどずれないみたいですね.

    肝心の表示ですが,8行目で時刻を取得し,10〜12行目で時・分・秒に分け,14行目でmainに渡された要素に表示しています.これだけのシンプルな仕組みなので,数字が1桁の場合は左詰めになります.Timerのサンプルということでご容赦ください.

    デモです.

    アナログ時計

    こちらは,あまりにディジタル時計が簡単だったので作成した副産物です.例によって手抜きできるだけシンプルを心がけています.

    11行目で繰り返す関数を,変数watchに入れています.書式がディジタルと異なるのは,まだ私がJSXに慣れていないためです.

    watch内では,12行目で描画領域をクリアして,14〜17行目で1時から12時の印を描いています.この辺は,前回紹介だけした仮想座標をサポートした描画ライブラリを使用して,描画領域をX, Y共に-1〜1にしています.そして,ディジタル時計同様,19〜23行目で時刻の取得と時・分・秒・ミリ秒への分割を行っています.

    さらに,25〜27行目で,表示すべき角度を計算しています.数学的な角度は時計で言う3時から反時計回りなので,その分の調整を行っています.さらに29行目〜33行目で短針・長針・秒針の描画を行っています.

    近くにあった時計の秒針が赤でスルスル動くタイプだったので,こちらのプログラムでも赤く,かつ,スルスル動くようにしています.スルスルと動かすため,36行目で動作間隔を100[msec]にしています.

    デモです.

    github上のソースコード

    以下のリンクからソースコードを参照できます.バグがあったらこっそり教えていただけると助かります.

    gitigal_watch.html:ディジタル時計を表示するhtmlファイル.

    digital_watch.jsx:ディジタル時計のソースコード.

    digital_watch.jsx.js:コンパイルされたディジタル時計のコード.ブログに載せる都合上,最終行に var dw = JSX; を追加しています.

    analog_watch.html:アナログ時計を表示するhtmlファイル.

    analog_watch.jsx:アナログ時計のソースコード.

    digital_watch.jsx.js:コンパイルされたアナログ時計のコード.ブログに載せる都合上,最終行に var aw = JSX; を追加しています.

    vcanvas.jsx:先日から変更なしですが念のため掲載しておきます.仮想座標をサポートしたグラフィック描画クラス.まだメソッドが揃っていません.

    参考にしたサイト

    *1:timer.jsx ( タグ ) - Code/JSX - CODE CODIUM.

    *2:setIntervalとsetTimeoutを調べた結果余分なことになった - 三等兵

    貴重な情報をありがとうございました.

    このエントリーをはてなブックマークに追加

    2012年6月27日水曜日

    GUI版DFT by JSX

    やはりグラフが必要

    コマンドライン版のDFTがとりあえず完成したのを受け,次はGUI版だと意気込んでみたものの,なかなか時間が取れなくて公開が遅くなってしまいました.数値を表示するだけのDFTは,表示が寂しいとかそう言うレベルではなく,分析結果が全く分かりません.やはりグラフィック表示が必要です.

    どこに時間が掛かっていたかと言うと,グラフ表示するための「仮想座標をサポートした描画領域」のクラスを作成したからです.こちらのクラスはまだ完成度が低く公開するには時期尚早ですが,githubには上げておきます.使い方の説明は,その内このブログで公開する予定です.

    そんなこんなで,ようやく公開するに耐えるDFTアプリができました.今のところ,分析できる波形が「単純なsin波」「位相が30度ずれたsin波」「矩形波」のみです.もっと色々と機能をつけることもできますが,まずは公開を優先したのでご容赦ください.以下,デモです.分析したい波形のボタンをクリックすると,元波形と周波数成分が表示されます.

    デモ

    ※Blog全体を表示している場合,エラーが出て動作しません.この投稿のみを表示すれば動作します.現在原因究明中.追加:JSXの仕組み上,複数のJSXプログラムを同一ページに配置できません.お手数ですが,この投稿のみを表示した状態でお試しください.追加:無理やり同一ページ内に複数のJSXプログラムを配置するための改造を行いました.

    ボタンで元波形を選択してください
    Please select an original wave by buttons

    元波形
    original wave

    周波数成分(赤:実部,青:虚部)
    Spectrum ( red: real part, blue: imaginary part )

    ソースコード

    ソースコードを以下に示します.

    mainメソッドに,「元波形を表示するcanvasのid」「周波数成分を表示するcanvasのid」「sin(x)ボタンのid」「sin(x+30)ボタンのid」「矩形波ボタンのid」を渡してください.7行目から13行目で,与えられたidを元に,仮想座標をサポートするVCanvasの初期化などを行います.次に15行目でサンプル数(ここでは80)をpに代入します.

    19行目から57行目はグラフィック表示のためのdftメソッドの定義です.内容は,描画領域のクリア(20, 21行目),軸などの描画(23〜29行目,40〜47行目),DFT(35〜38行目),グラフ描画(31〜33行目,49〜56行目)などです.

    58行目から始まるsinメソッド,63行目から始まるsin2メソッド,68行目から始まるrectangleメソッドは,それぞれ波形を計算し配列waveに代入し,上記dftメソッドを実行します.これらは,その直後(74〜76行目)でそれぞれのボタンが押された際に実行されるメソッドです.無名関数で定義しても良かったのですが,確認のために一度変数に代入しています.

    80行目以降のFGクラスはFunctionGeneratorクラスです.色々な波形を生成するメソッドを定義していく予定ですが,今のところ何もできないに等しいです.

    GUIアプリを作ってみた感想

    JSXを初めて見たときは,「Javaっぽい」と思ったのですが,実際にGUIアプリを組んでみると「Javaより数倍楽」ということに気づきました.描画領域に簡単にアクセスできて,ラッパークラスを簡単に定義できて,intとdoubleを厳密に区別しなくて済む=numberクラスの存在がどれだけ幸せか計り知れません.一方JavaScriptとの比較では,メソッドや変数の型チェックが厳密であることの良さも実感できます.

    公開したプログラムは,教材として利用することを想定しているので,他人がカスタマイズすることも考慮に入れています.ですので,ボタンを追加したり削ったりすることも考慮したいのですが,現状のJSXでは引き数の数が定義に基づいて固定されてしまっているので,可変長引数のサポートが望まれます.と言いつつ,Nylonに対応できれば,操作部と計算・表示部の独立性が高くなるので,早くNylon.jsxを開発したいと思います.

    総合的に判断して,JSXは今後のシミュレータ教材開発言語として最適です.徐々にノウハウを貯め,ライブラリを充実させ,どんどん授業に使っていこうと思います.

    注意事項:JSXのサンプルなどを見ると,クラス名にApplicationが使われることが多いのですが,ブログ上に複数のJSXプログラムを張り付けると,クラス名が重複してしまい動作しないことがあります.クラス名は面倒でも個別に付けたほうが良さそうです.JSXをコンパイルして作成されたJSは,全てグローバル変数JSXに紐付けられます.よって,複数のJSXプログラムを同一ページ内に配置するとコンフリクトし,最後に読み込んだスクリプトしか実行できなくなります.コンパイル後にJS内の「JSX」を別の単語に置換すれば良いものと思われますが,スマートな解決策を期待したいところです.

    github上のソースコード

    以下のリンクからGUI版DFTのソースコードを参照できます.バグがあったらこっそり教えていただけると助かります.

    dft_gui.html:GUI版DFTのHTMLファイル.

    dft_gui.jsx:GUI版DFTの中枢部.

    vcanvas.jsx:仮想座標をサポートしたグラフィック描画クラス.まだメソッドが揃っていません.

    dftlib.jsx:DFTに関するライブラリ.あまり独立したファイルにする意味が無いのは秘密.

    dft_gui.js:dft_gui.jsxをコンパイルして作成されたJS.特に最適化オプションは付けていません.

    追記

    同一ページ内に複数のJSXプログラムを配置できないことについて追記しました.(2012/6/27)

    このエントリーをはてなブックマークに追加

    2012年6月15日金曜日

    JSXでDFT(改訂版)

    DFTの改訂版

    以前の記事を書いた際には,まだまだJSXのことがよく分かっておらず,変な記述が多かったのと,一部バグがあったのでソースコードを改訂しました.とりあえずソースをご覧ください.

    設計上,変えた箇所はFunctionGeneratorを独立したクラスにしていることです.バグがあったのは,元波形を合成しているところで各サンプルをサンプル数で割っていたのですが,これでは波形の振幅がおかしくなってしまうので,dftメソッド内で割るようにしたことです.

    技術的に変わったところは,

    1. 元波形の関数をmainで定義し,その関数を渡して元波形を生成するようにした
    2. 表示が見づらかったので1000倍→intに変換→1/1000倍して見やすくした

    などです.dftメソッドがシンプルになったので,インスタンスメソッドにしている意味が無くなりました.現状ではaiとarを一度に返すことができないので別のメソッドで取得していますが,JSXが2つ以上の返り値を返せるようになったらクラスメソッドに変更できます.2つ以上の返り値を返せるようになりませんかね?

    DFTの実行結果

    実行結果です.多少は見やすくなったと思います.

    おわりに

    徐々にJSXに慣れてきたので,次はGUIアプリ版のDFTを作りたいと思います.もちろん,グラフ表示も付けたいと思います.その他要望などありましたらコメント欄にお書きください.

    ソースコードをgithubのこちらに置いておきます.pを増やしたり,元波形の関数を変更するなどお試しください.

    このエントリーをはてなブックマークに追加

    JSXの関数あれこれ

    関数の定義方法

    素のJavaScriptでは,関数を定義する方法が4つありました.それぞれ使いどころが異なるのですが,細かい説明は省略します.以下,2つのパラメータを受け取り,それらの積を返す関数を考えます.

    1. Function foo( x, y ) { return x * y; }
    2. function bar( x, y ) { return x * y; }
    3. baz = function( x, y ) { return x * y; };
    4. qux = new Function( "x", "y", "return x * y;" );

    一方,JSXでは以下の方法で関数を定義できます.JavaScriptではクラスの概念があやふやですが,JSXではクラスメソッドとインスタンスメソッドと単なるメソッドに区別されます.以下の中では,1がインスタンスメソッド(インスタンスを作成して「インスタンス名.メソッド名」で呼び出す)で2がクラスメソッド(「クラス名.メソッド名」で呼び出す)です.3〜5が単なるメソッド(メソッド名で呼び出す)です.単なるメソッドは変数に代入する形になるので,変数のスコープ外からは使用できません.また,「->」の表記方法は後になって追加されたので,初期にJSXをセットアップした人はエラーとなってしまいます.その場合はJSXを更新してみてください.

    1. function foo( x: number, y: number ) : number { return x * y }
    2. static function bar( x: number, y: number ) : number { return x * y }
    3. var baz = function( x: number, y: number ) : number { return x * y; };
    4. var qux = ( x: number, y: number ): number -> { return x * y; };
    5. var quux = ( x: number, y: number ): number -> x * y;

    関数を関数に渡す

    使う機会は限定されますが,JavaScript同様,関数に関数を渡すことが必要な場面があります.例を挙げると,GUIアプリや非同期処理などでコールバック関数を指定する時です.関数を渡す際には,上記3〜5のように一旦変数に代入することも,無名関数を直接記述することもできます.

    まずは関数を受け取る側の記述例です.やっていることは単純に,パラメータとして関数と2個の数値を受け取り,受け取った関数にその数値を渡して実行し,実行結果を表示するものです.

    次に,上記メソッドに関数を渡して実行する例を示します.上記メソッドはクラスメソッドなのでクラス名が必要です.今回は_Mainクラスに記述されているものとします.

    今回は関数の渡し方について記述しました.githubにソースコードを置いておきましたのでご利用ください.

    func.jsx

    最後になりますが,こちらのページにはお世話になりました.ありがとうございました.

    JSX の進化速度が半端ない | ぐるぐる~

    このエントリーをはてなブックマークに追加

    2012年6月8日金曜日

    JSXによるマウスでお絵描き

    ようやくソースコードの整理が終わったので,恥ずかしながら公開します.マウスでお絵描きするサンプルプログラムです.ペンの色や太さを変更する機能や,保存機能など全く実装していません.あくまで,マウスの座標を取得したり,Canvasを使うサンプルとして御覧ください.

    pen.html

    pen.jsx

    利用方法ですが,以下のようにJSXファイルをコンパイル(?)してください.

    jsx --release --output pen.jsx.js pen.jsx

    その後,pen.htmlとpen.jsxjsを同じディレクトリに置いてWebブラウザで開いてください.コンパイルされた後は.jsxファイルやweb.jsxは不要です.当方で試した際には「file://〜」の状態でも動作しました.

    デモ

    以下の四角の中でマウスをドラッグしてみてください.黒い点が描画されます.一部,四角の領域の位置調整の部分でコンパイルされたjsファイルに変更を加えています.どうしてもこの部分をJSXで記述することができませんでした.未熟です,はい.領域内の座標の取得方法を覚えたので,更新しました.(2012/6/21)

    <注意!>Firefoxで動作しなくなっています.2012/6/21に加えた変更によるものです.具体的には,マウスの座標を取得するために,MouseEventのインスタンスのoffsetXとoffsetYプロパティにより値を取得していました.しかし,Firefoxにはこれらのプロパティが存在しないため動作しません.普段はGoogle Chromeを使って作業しているため,チェック漏れがあったことをお詫び申し上げます.(2012/6/29)

    その後,FirefoxにはlayerXとlayerYプロパティがあることを調べました.ところが,web.jsにこれらのプロパティが存在しないことが分かり,あろうことかこれらを加えてgithubのJSXツリーにPull Requestを出しました.(若くないけど)若気の至りでした.layer[X,Y]はW3Cに承認されていないプロパティだったのです.

    そのことを親切に教えてくださったFuji, Goroさんに感謝します.きっと,Pull Requestを見て「え?今さらこんなコト言ってくる人がいるぞ」という気持ちだったのではないでしょうか.冷静になってlayer[X,Y]が存在しない理由をきちんと考えていれば,こんな恥ずかしい思いはしなくても済んだのに・・・と思っていたら,即座にTwitter上で,マウス座標の取り方を解説しているページを授けていただきました.

    そのページによると,やはりマウス座標の取得方法は混沌としているとのこと.これはものすごく役に立つと思って喜びながら日付を見ると,およそ3年前の記事.どれだけ遅れているんだ俺は.

    気をとりなおして解説します.まず,マウスイベントからウィンド座標を取得します.これにはclient[X,Y]プロパティを使います.これだけではスクロールするとずれるので,ウィンドウ座標系内でのノードの座標をgetBoundingClientRect()メソッドによって取得し,引き算します.

    具体的なマウス座標の取得方法は以下のとおりです.
    var es = e as MouseEvent; // マウスイベントの取得
    var ee = es.target as Element; // イベントの発生したノードの取得
    var rect = ee.getBoundingClientRect(); // ノードのウィンドウ座標の取得
    var x = es.clientX - rect.left; // マウスイベントのウィンドウ座標 - ノードのウィンドウ座標
    var y = es.clientY - rect.top; // マウスイベントのウィンドウ座標 - ノードのウィンドウ座標
    この記事が誰かの参考になることを祈ってます.

    最後になりますが,こちらのページにはお世話になりました.ありがとうございました.

    【閲覧注意】JSX で何か作ってみた。 | Big Sky

    DOM level 3のマウスイベントにおけるカーソル位置の詳細 | 本の虫

    追記

    githubにソースコードを置いておきました(2012/6/14)

    pen.html

    pen.jsx

    素のままのデモを実行したい場合はこちらをクリックしてください(2012/6/14)

    マウスドラッグによる座標の取得方法を変更しました.(2012/6/21)

    Firefoxでの不具合について記述しました.(2012/6/29)

    マウスドラッグによる座標の取得方法を変更しました.(2012/6/30)

    このエントリーをはてなブックマークに追加

    メモ:JSXの配列の扱い

    JSXの基本的な文法

    JSXはJavaに近い書式です.また,詳しくは知りませんがActionScriptにも近いようです.とは言え,新しい言語と出会った際にやってみる「配列に値を代入して,表示してみる」という簡単なプログラムを作ろうとしても,細かい文法の違いで苦労しました.と言うわけで配列に関する基本的な文法についてメモしておこうと思います.

    配列の初期化

    最初は,こんな簡単なことでも迷ってしまったので書いておきます.簡単なのは直接値を代入する場合で,以下のプログラムの2行目のように書きます.他の言語のように,「まずは配列を宣言して・・・」と考える場合は同5行目のように書きます.

    配列の要素数

    配列の要素数ですが,固定ではなく可変のようです.配列の要素数を得るには6, 7, 12行目のようにlengthを使います.配列に追加したい場合は10行目のようにpushメソッドが使えますし,配列同士を結合したい場合は15行目のようにconcatメソッドが使えます.

    逆に,配列の要素を減らしたければpopメソッドやshiftメソッドがあります.

    配列の内容表示とループ

    すでに上のプログラムで用いているように,logメソッドで表示します.全要素の表示は31行目のように単純にtoStringメソッドを用いれば良いのですが,併せて配列の要素数分だけ繰り返すための書式も紹介しておきます.

    上記のプログラムを全て一つのファイルにまとめて,以下のように実行できます.今回は仮にarray.jsxというファイル名をつけたものとします.ソースコードをgithubのこちらに置いておきます.

    jsx --run array.jsx

    だんだんと基本的な書式が分かってきましたが,まだまだ足りないところがあるので,続く予定です.今回はこの辺りで失礼します.

    追記

    空の配列の作成方法その3を追加しました(2012/6/14)

    githubにファイルを置き,リンクを追加しました(2012/6/14)

    このエントリーをはてなブックマークに追加

    2012年6月7日木曜日

    メモ:Macのターミナルの設定

    .bashrcの話

    このブログを読む方はすでに承知のことと思いますが,Mac OS Xの中枢部はBSD Unixの系統です.なので,ターミナルをひらくと見慣れた画面が開き,いつものコマンドを使うことができます.その割に,ホームディレクトリに.bashrcや.bash_profileが見当たりません.検索してみると,.bash_profileを作ってそこから.bashrcを読み込ませれば良いとのことなので,さっそく指示に従ってみます.

    まずは.bash_profileです.

    続いて.bashrcです.かなり偏った内容なので,各自好きな設定をどうぞ.

    .bashrcの2〜4行目は,Java言語のソースコードの文字コードをUTF-8として指定します.5行目はJSXのための設定です.

    以下のブログ・記事を参考にしました.ありがとうございました.

    ■[Mac]Mac - bash入門
    UNIX Settings...

    追記

    javadocのaliasにcharsetの設定を加えました(2012/6/14)

    このエントリーをはてなブックマークに追加

    2012年6月6日水曜日

    JSXでDFT

    JSXという言語

    JSXという言語が彗星のごとく現れました.この言語を使ってプログラムを書くと,ギンギンに最適化されたJavaScriptに変換できるということで興味を持ちました.ドキュメントを読んでいくと,文法がJavaに近いこととJava並に型チェックにうるさいことなどが分かりました.

    これまでMeSHやNylonの開発にJavaScriptを使ってきたのですが,thisが何を指すか不明確であることや,変数のチェックがないことによるエラーに悩まされてきました.そこに現れたのがJSXです.言語仕様はJavaのように窮屈ですが,今後ライブラリやサービスを提供していくにあたり,妙なエラーに悩まされたくないので,まずは試してみることにします.

    DFTのソースコード

    DFTは,言わずと知れた離散フーリエ変換(Discrete Fourier Transform)です.周波数分析の強い味方です.今回はC言語で書かれたDFTを移植してみます(※FFTではありません).JSXのドキュメントがまだまだ整備されていないので,ちょとしたプログラムでも試行錯誤の連続でした.とりあえずソースをご覧ください.

    ドキュメントの探し方が悪いのか,Math系(Math.PI,Math.sin,Math.cos)が見つかりませんでした.「文法がJavaに似ているので同じ書き方だろう」と信じて試したところ動いたのでほっとしてます.

    文法的に面倒だと感じたのは,インスタンス変数やインスタンスメソッドの呼び出し時にthisが必須なことでした.まぁ特に大きな問題ではないですね.

    困ったのが配列の初期化でした.Java言語でいう「int x[] = new int[10];」を書きたかったのですが,試行錯誤の上断念しました.仕方ないので宣言時に「var ar = [0];」として強引にarを整数の配列として認識させ,このままでは0が邪魔なので,コンストラクタで「this.ar.pop();」して空の配列としています.その内,ドキュメントが整備されると思います.ドキュメントが整備されたら,この書き方を笑ってください.

    後は単純に配列とループです.詳しいアルゴリズムは巷の書籍やWebページを参照してください.ループと言えば,Rubyのようなイテレータが楽で良いですね.

    DFTの実行結果

    実行結果です.今回の例では,func_yによって定められている関数を分析しています.具体的には 3sin(x) + 7cos(3x)を分析しているので,1倍と3倍の周波数の数値がそれぞれ3と7になっているので,きちんと動作していることが分かります.欲を言えばe-17とかが目立つので,printfが欲しいところです.

    おわりに

    今回はJSXの文法を確認するためにC言語で描かれたDFTを移植してみました.ものすごく恥ずかしいソースコードですが,JSXの文法確認のために公開します.

    JSX自体はnode.js上で動作するのでグラフィック環境がありませんが,RhinoなどのJava VM上で動作するのなら,Javaのグラフィック機能を使ってみたいですね.それよりはWebブラウザ上で動作させるのが真っ当なので,今後試してみたいと思います.

    今回参考にしたC言語のソースですが,自著であるこの本のものを使用しています.「三井田惇郎,須田宇宙,"数値計算方 第2版", 森北出版株式会社」.宣伝ではなく,参照元を明確にする意味で記しておきます.

    最後になりますが,JSXの公開に感謝します.

    追記

    ソースコードをgithubのこちらに置いておきます(2012/6/14)

    このエントリーをはてなブックマークに追加

    2012年2月13日月曜日

    Audio Data APIのサンプル

    JavaScriptでサウンド合成

    HTML5のおかげでFlashが不要になると言われています.では,これまでFlashを使わなければならなかった用途に何があるでしょうか?グラフィックス描画,フォント,アニメーション,通信などがメジャーなところですが,それ以外にもサウンド出力があります.合成した波形を音として出力する機能は,特に欲しい機能でした.厳密には,Javaでも合成サウンドの出力は可能だったのですが,それだけのためにJavaを使う人は私以外にいないはずなので,Flashの独壇場と言えるでしょう.

    ところが,HTML5の旗印のもと,様々な機能がJavaScriptから利用できる時代になりました.Firefoxに実装された,Audio Data APIもその一つです.Audio Data APIとは何かと言うと,合成した波形を音として出力するAPIです.と言う訳で,今回はAudio Data APIを利用して,簡単な合成音を鳴らしてみたいと思います.

    Audio Data API入門

    Audio Data APIは非常にシンプルなAPIです.音を扱うAPIとして,Webkit系に実装されているWeb Audio APIも存在して,一括りにされることが多いのですが,狙いが全く異なります.Web Audio APIは,音源位置を指定したり,FFTしたり,一定間隔でバッファに記録する機能を持つなど,様々な機能を持っています.よって,これら2つのAPIは,別物と捉えておいたほうがすっきりします.

    ではAudio Data APIの使い方ですが,必要な手順は5つです.

    1. Audioのインスタンス作成

    2. 1で作成したオブジェクトにチャンネル数とサンプリングレートを設定

    3. Float32Arrayのインスタンスを生成し,波形データを生成

    4. 3で生成したオブジェクトを1で生成したオブジェクトと結びつける

    5. 再生する

    言葉にするとイメージが掴みづらい箇所もありますが,手順としてはシンプルです.それでは実際のコードで見てみましょう.

    Audio Data APIのサンプル

    Firefox限定ですが,実際に耳で確かめてください.以下のボタンをクリックすると,ボタンに書いてある周波数の音を再生します.上3つと下3つは,鳴らすためのパラメータ指定方法を2つ作成したので,そのチェック用です.上は周波数を基準周波数と基準からの相対値で指定します.下は周波数を直接指定します.詳しくはソースを読んでいただければ幸いです.







    このエントリーをはてなブックマークに追加

    2012年2月3日金曜日

    最近のツイートのまとめ 20120203

    Twitterでつぶやいたことを後々探そうとしても出てこないことが多いので,このページにまとめておきます.内容はブログ用に編集しています.リツイートは元情報の方のお名前を付けておきます.リンク集+αと思ってください.

    JavaScriptでPhotoshopファイルを解析する「psd.js」

    http://dothtml5.com/archives/20120201_psdjs.html

    データを読み込んで利用することは,プログラム言語よりもデータ構造を知ることができるか否かにかかっています.とは言え,まさかJavaScriptでPhotoshopのデータを読み込めるようになるとは思っていませんでした.@RSS_hateb_Roy 様より.

    Node.js 日本ユーザグループ

    http://nodejs.jp/

    node.jsのバージョンアップを受け,ドキュメントが最新開発版(v0.7.2)に対応したようです.関係者の方々,ありがとうございます.@meso 様より.

    HyperZebra Preview Release

    http://web.me.com/pgoo/Site/HyperZebra.html

    MacOS6の頃にMac会を席巻していたカード型データベース(っぽい環境)HyperCardが蘇ります.当時としてはちょっとしたデータを整理したり,ちょっとしたアプリを作ったりと便利に使っていました.@openspc 様より.

    CSS3で吹き出し付丸ボタン

    http://coder.blog.uhuru.co.jp/css/css3-balloon-btn

    タイトル通りですが,CSSを使って丸いボタン(画像付き)の作り方です.ボタンの内容をフキダシで表示できるのもグッドです.@chimiochimio 様より.

    この完成度に震えが止まらない!Node.js史上最高のIDE、Cloud9をインストールしよう。

    http://codedehitokoto.blogspot.com/2012/01/nodeidecloud9.html

    node.jsの開発環境としてviを使ってきましたが,デバッグしづらいのが難点でした.その辺りを解消してくれるIDEです.

    Mac OS X Lion(10.7)にCloud9 IDEをインストール

    http://r.otsuya.co/post/11045590787/cloud9-ide

    上記のCloud9に関連した補足です.タイトル通りですが,Mac OS X LionにCloud9をインストールする方法です.

    Twitter Bootstrapが大幅バージョンアップ!して凄まじいことに・・・

    http://www.ideaxidea.com/archives/2012/02/twitter_bootstrap_v2.html

    Twitter社によるWebデザイン素材Bootstrapの新バージョン(v2.0)です.以前のバージョンも便利でしたが,さらに強力になりました.Github上のBootstrapは以下からどうぞ.

    http://twitter.github.com/bootstrap/index.html

    テスト問題作成ツール – QuizGenerator – クイズジェネレータ

    http://quizgenerator.net/2012/01/ibooks_embed/

    iBooks2では,これまでの「本」に相当する静的なコンテンツだけでなく,JavaScriptを用いた動的なコンテンツにも対応しています.動的なコンテンツの一環としてクイズ問題を埋め込むツールの紹介です.@realbasic2009 様より.

    これは便利!コピペで使える実用的なCSSテクニックいろいろまとめ9つ

    http://w3q.jp/t/1207

    CSSの利便性が急激に向上しているまでは理解できるとして,どのように作れば良いのかになるとお手上げ気味です.

    CSSのelement()関数

    http://hail2u.net/blog/webdesign/element-css-function.html

    任意の要素を画像として参照するelement()関数の紹介です.まだFirefoxにしか実装されていないようですが,確実に便利です.

    iBooks AuthorでHTML5の電子書籍作ってみた

    http://ascii.jp/elem/000/000/665/665232/

    iBooks AuthorでiBooksコンテンツ内にウィジェットを仕込むためのハウツーです.その他,JavaScirptのプログラムの埋込みや,HTML5 audio要素の埋込み,Google Mapの埋め込みについても書かれています.まだ試していませんが,HTML5 video要素を埋め込むことができればe-Learning環境として活用できるので期待しています.

    Sugar: A Javascript library for working with native objects.

    http://sugarjs.com/

    JavaScriptのネイティブオブジェクトを拡張するライブラリです.ソースコードを見ながら拡張して行ったら「Ruby並に便利になるんじゃね?」と期待が膨らみます.

    CSS3 breadcrumbs

    http://www.red-team-design.com/css3-breadcrumbs

    パンくずリストを作成するためのCSSです.以前にも他のサイトで見た気がしますが,メモが残っていないので今度こそ残しておきます.@skuare 様より.

    VMware Toolsのインストールと時刻合わせ

    http://d.hatena.ne.jp/hsksnote/20111211/1323618653

    Scientific Linuxの話ですが,GUI無しでVMware Toolsをインストールする方法と時刻合わせの方法です.

    クライアントサイドだけでファイルを保存する「FileSaver.js」

    http://www.moongift.jp/2012/01/20120120-2/

    サーバを介さずにブラウザ側のみでファイルを生成(?)してダウンロードするライブラリです.

    「crocro.jscam」JavaScriptでWebカメラの画像を取得するライブラリ

    http://crocro.com/html5/jscam/wiki.cgi

    タイトル通りですが,もはやJavaScriptに限界は無い感じです.

    RRubyでのBenchmarkの取り方をば。

    http://a-newcomer.heroku.com/29

    意外と知らないけど,知っていると便利です.

    オレオレDropBoxをrsyncで作る。

    http://d.hatena.ne.jp/takuya_1st/20120116/1326735955

    ZFS+rsyncサーバ+WebDavで,クライアントにこれを入れれば十分かな?そのうち試してみます.

    SRWare Iron

    Windows版 : http://www.srware.net/en/software_srware_iron_download.php

    Linux版 : http://www.srware.net/forum/viewtopic.php?f=18&t=2934

    Mac版 : http://www.srware.net/forum/viewtopic.php?f=18&t=2962

    Google Chromeの元となっているChromiumをベースに軽量化されたブラウザIronです.ChromeからGoogle社への情報提供機能やアップデートチェック,PDF Viewerを取り除いたと思えばだいたい合っています.20日間ほど使用したところ,特に問題は見られませんでした.

    Node.js と Titanium で SlideShare リモコンを作ってみた

    http://d.hatena.ne.jp/scalar/20120112/1326395054

    MeSHと同じようなことをやっているけど,JavaScriptに慣れた人が作るといろいろ便利という例.@sugyan 様より.

    Twitter の特定のユーザーの最新ツイートを JavaScript で取得する方法

    http://weble.org/2011/08/01/twitter-recent-tweet

    すみません,twitter APIを読み解く時間がありませんでした.そのうち試してみます. @soraiy 様より.

    最近のWeb制作で必ず1度はお世話になる便利なジェネレーターまとめ6つ

    http://w3q.jp/t/1065

    最近のCSSは複雑になってしまったので手打ちできないです.素直にジェネレータを使います.

    html5のW3C FileAPIについて、調べてまとめた。

    http://d.hatena.ne.jp/takuya_1st/20120106/1325835641

    いつも分かりやすい解説をありがとうございます.と3回感謝しても足りないレベルです.

    ブラウザキャプチャサービス【無料】

    http://www.cman.jp/BrowserCapture/

    様々なブラウザや解像度で,自分のサイトのスクリーンショットを表示してくれるサービスです.

    homebrew でMacコマンドをLinuxのGNU風に置換する

    http://d.hatena.ne.jp/takuya_1st/20111230/1325272152

    環境のちょっとした差に敏感な人はどうぞ.

    このエントリーをはてなブックマークに追加

    2012年1月27日金曜日

    Mac OS Xにnode.jsなどをインストール

    パッケージ管理システム

    Macでは,macportsと言うパッケージ管理システムが有名だったのですが,root権限が必要などの理由により,最近はhomebrewが勢力を伸ばしてきました.そこで,homebrewを使用してnode.js関係のインストールを行う方法を示します.せっかくなので,インストールログをつけておきます.なお,ホスト名は「sahara」,ユーザ名は「suda」です.背景が濃いグレーの箇所が実際に入力する行です.

    本日インストールするものは,

    homebrew

    node.js

    mongoDB

    npm

    です.

    インストール

    まずはXcodeをインストールします.Lionを使用している人はMac App Storeからどうぞ.LeopardやSnowLeopardの人は付属CD-ROMに入っているようです.なお,Javaも必要なようなのでインストールしておいてください.

    それでは,homebrewをインストールします.以下の1行目の$以降を入力してください.途中でenterキーの押下と管理者のパスワードの入力を求められるので指示に従ってください.

    以上でhomebrewのインストールが完了です.ちなみに,コマンド名は「brew」です.さっそくnode.jsをインストールします.

    ぼーっと待っているだけでインストール完了です.続いてbrewをアップデートして,mongoDBをインストールします.不要でしたらupdateのみ実行して,mongoDBのインストールは飛ばしてください.

    起動方法や自動起動設定は上記ログに書かれているので,必要な方を実行してください.続いてnpmをインストールします.昔はhomebrewでインストールできたようですが,方針の違いから,現在はインストールできなくなっているので,以下に示すようにcurlとshでインストールします.

    後はnpmを使用して必要なパッケージをインストールして下さい.以下,「Express」「Socket.IO」「EJS」「Mongoose」をインストールします.

    npmのモジュールツリーが化けていますが,原因不明です.それでは,Macでnode.jsを楽しんでください.

    追記

    ブログのデザイン変更と,コマンドを打ち込む箇所を明示しました.(2011/2/2)

    このエントリーをはてなブックマークに追加

    2012年1月25日水曜日

    Nylon iframe

    Nylon iframeとは

    昨日の日記に続いてXDMの話です.Nylonの仕組みを拡張して,iframeを超えてメッセージセンディングを行うモジュールを開発しました.プログラムはgithubで公開しています.

    Nylon iframeの使い方

    まずはNylonとnylon.iframe_parentを初期化します.idがdestFrameのiframeに,localhost配下のhtmlを読み込んでいるものとします.その場合の初期化は以下のように行います(変数名は手抜きです).通常,onloadイベント内に記述してください.

    同様に子フレーム側でもnylon.iframe_childの初期化を行い,onconnectメソッドで接続時の関数を定義します.親フレームから接続されると,自動的にonconnectメソッドが呼び出されるので,その中でイベント受信時のコードを記述します.

    このとき,フレーム間の通信は以下のように行います.

    この通信内容は,お互いのフレームだけでなく,タグ"test"を受信する他のNylonモジュールにも伝達されます.このような作りになっているので,iframeの有無に寄らず動作するモジュールを開発することが可能です.

    ソースコード

    Nylon iframeによる,親子フレーム間で通信を行うサンプルを以下に示します.まずは親フレームです.好きな名前で保存してください.localhost以外のサーバに置く場合は17行目を変えてください.なお,通信相手のサーバのチェックは,17行目の第2パラメータに基づいて自動的に行われます.

    続いて子フレームです.ファイル名はframe2.htmlで保存してください.ファイル名を変えたい場合は,親フレーム側の12行目を変更してください.さて,親フレーム側と同様,通信相手のチェックは自動的に行われます.Nylon iframeでは始めに接続してきたフレームのサーバ情報を記録しておき,そのサーバ以外からの通信であれば自動的に無視するようにしています.

    これにより,子フレーム側はどのWebページから呼び出されても動作します.これは部品化(ガジェット化)を容易にするための仕様です.そのため,onconnectメソッドが存在し,少々トリッキーではありますが,利便性とセキュリティを確保しています.

    Nylon iframeにより,iframe間の通信が容易になりました.しかも,何らかの機能がiframe上にあっても親フレームにあっても利用できます.これにより,機能のモジュール化が進み,最終的にモジュールを組み合わせたWebシステム開発が楽になります.

    このエントリーをはてなブックマークに追加

    2012年1月24日火曜日

    XDMの基礎知識

    XDM - Cross Document Messaging -

    AJAXでは,セキュリティの都合により,そのWebページが格納されているサーバとしか通信を行えませんでした.これに対してJSONPを使って回避することも可能ですが,JSONPはscriptタグによるJavaScriptのロードそのものであり,トリッキーなコードになることは否定できません(jQueryを使うことで回避できますが,ここでは置いておきます).そんな時に使われるのが,XDMです.

    XDMとは,大雑把にいってしまうと,iframeを作う技術です.そうです.frameは抹殺されたのですが,iframeは残っています.それで,iframeの特性として「表示上は同一ページだが,セキュリティ上の扱いは親フレームとは別に扱う」ことになっています.すなわち,親フレームとは異なるサーバに置いてあったとしても,子フレームは自身が格納されているサーバとは通信を行えることになります.偉そうに言ってますが,ここまでは昔から可能でした.

    昔と違うのは,親フレームと子フレームの間の通信が(別サーバであっても)可能になったことです.ただし,悪意のあるページからiframeで呼び出されて好き勝手されては困るので,通信相手のサーバ情報を取得して,正規の通信であることを確認可能となっています.

    XDMによる送信(親フレーム側)

    フレーム間の通信には前回WebWorkersでも使用した「postMessage」と「addEventListener」を使います.レシーバの指定が少々異なるので,例を使って説明します.まずは,localhostにWebサーバがあり,以下のように,送信ボタン,iframe,受信データの表示領域が定義されているとします.

    このとき,親フレームから子フレームへの送信は以下のように行います.

    順に説明すると,1行目はボタン要素の取得,2行目はiframe要素.contentWindowによって,通常のページで言うwindowに相当するオブジェクトを取得しています.

    3行目からは,ボタンクリックのイベント定義です.4行目でdataという名前のハッシュを作り,helloという文字列と現在時刻を収めます.

    5行目が子フレームへの送信です.第1パラメータが送信内容で,先ほど作成したdataをJSON化したものです.今のところ,文字列でないと送信できないので,その対策です.そして,第2パラメータが子フレームが格納されているサーバを表します.つまり,プログラム作成者が子フレームのサーバをしっかりと把握している必要があります(プログラムで動的にサーバを取得する場合はこの限りではありませんが,どのような状況で動的に取得するのかは不明です).もし子フレームのサーバ指定を間違えると,例えば間違えて「http://hoge.com」と指定すると「Unable to post message to http://hoge.com. Recipient has origin http://hoge.com.」というエラーがコンソールに表示されます(Google Chromeの場合).

    子フレーム側の記述

    一方,子フレーム側でデータを受け取るには,addEventListenerを使います.ここでは,親フレームから送信された内容を,そのまま返信する例を使って説明します.

    1行目はXDMにより,メッセージを受け取った際のイベント定義です.2行目は,通信相手のサーバ情報の確認です.この例で分かるように,event.originで通信相手のサーバ情報を確認できるので,セキュリティ面からきちんと確認しましょう.

    3行目はデータの返信です.親フレームの要素を取得する方法が分からなかったため,event.source(送信してきた要素)に対してpostMessageしています.パラメータは先程と一緒です.あ,event.dataで送られてきた内容を取得できるので,取り出して加工したい場合はJSON.parse( event.data )などとして使ってください.

    親フレーム側の受信方法

    最後に,親フレーム側での受信方法です.やり方は子フレームの場合と全く一緒です.ここでは,送られてきた内容をパースして,表示領域に貼り付ける所まで一緒に書いておきます.

    1, 2行目は子フレームと全く一緒の記述方法ですが,メッセージを受け取った際のイベント定義と,送信元のサーバ情報のチェックです.3行目は送られてきたデータをパースして変数dataに格納します.4行目,5行目は送信元サーバ情報と送信内容を変数outに収めます.そして,6行目で表示エリアにoutの内容を貼り付けます.

    ソースコード

    今回のサンプルコードを示します.まずは親フレームです.好きな名前で保存してください.localhost以外のサーバに置く場合は17行目と21行目を変更してください.

    続いて子フレームです.ファイル名はframe.htmlで保存してください.ファイル名を変えたい場合は,親フレーム側の9行目を変更してください.localhost以外のサーバに置く場合は11行目を変更してください.

    XDMにより,親フレームと子フレームの間の通信が(それなりに)簡単に記述できるようになりました.実際に使用する際には子フレーム側を別サーバに置くことがあると思います.その場合はpostMessageや送信元サーバのチェック部分を書き換えてください.いずれも,そのファイルが格納されているサーバではなく,通信相手のサーバを記述します.

    このエントリーをはてなブックマークに追加