2011年10月4日火曜日

NetBeans IDE 7.1 Beta リリース

NetBeans IDE 7.1 Beta がリリースされました
ダウンロードはコチラからできるようになっております

恒例のスプラッシュです


今回のバージョンアップでは、 JavaFX 2.0 のサポートをはじめ、 Web アプリケーション開発では CSS3 のサポート、 PHP 開発では Smarty テンプレートサポート、Git サポートの追加などがあります
その他の追加機能や各詳細はリリースノートを参照ください

何かお気づきの点などありましたら、 ML 等へご連絡頂ければと思います

2011年8月30日火曜日

MAMP 環境で SQLAlchemy を使用する方法

前回のつづきです
相変わらず、メモ程度なので短いです

MAMP 環境ではソケット接続先がデフォルトと異なるため、接続時にその場所を指定する必要があるというのが前回でしたが、 Python 製の有名な OR マッパの1つである、SQLAlchemy を指定する場合はどのように設定するかが今回のエントリーとなります

指定方法は、以下のようにデータベース URL に対して、ソケット接続先をクエリパラメータに追加することとなります

データベース種別://ユーザ名:パスワード@接続先アドレス:ポート番号/データベース名?unix_socket=接続先ソケットのパス

具体的には以下の通りとなります

In [1]: from sqlalchemy import create_engine
In [2]: engine = create_engine("mysql://root:root@localhost/mysql?unix_socket=/Applications/MAMP/tmp/mysql/mysql.sock")
In [3]: engine.execute("select 1").scalar()
Out [3]: 1L

以上で、 MAMP 環境下で SQLAlchemy が無事使えるようになるかと思います

2011年8月27日土曜日

MAMP 環境で mysql-python をインストールする方法

ちょこっとハマったのでメモとして…
元ネタはコチラ

以降は、 MAMPHomebrew がインストールされていることが前提となります
MAMP 、 Homebrew のインストール等の詳細に関しては下記過去記事も参照ください

Mac OS X での PHP 開発環境(MAMP編)
MacPorts から Homebrew へ移りました

なお、今回は MAMP 2.0 、 Homebrew 0.8 を使用しました

今回ハマった要因は、 mysql-python をビルドする際に必要なヘッダファイルが MAMP には含まれないということでした
( MAMP とは別に) MySQL 本体をダウンロードし、それを利用するなどの方法はあるのですが、さすがに面倒なので、 Homebrew にある、 "mysql-connector-c" という C 言語用接続 API のみのパッケージを利用します

$ brew install mysql-connector-c

Homebrew でのインストールが終了したら、
(下記では、mysql-python のインストールに pip を使用しています)

$ pip install mysql-python

以上で無事にインストールが完了するかとおもいます

次に実際に接続テストを行います
(テストには ipython を使用しました)

In [1]: import MySQLdb
In [2]: db = MySQLdb.connect(unix_socket="/Applications/MAMP/tmp/mysql/mysql.sock", user="root", passwd="root", db="mysql", charset="utf8")

上記コードの実行でエラーが発生しなければ、接続テスト完了です
この際に注意が必要なのは、 MAMP を利用する場合、接続ソケットのパスがデフォルトでは "/Applications/MAMP/tmp/mysql/mysql.sock" となるため、接続時にこれを設定しなければならないということです
(設定しない場合は、 "/tmp/mysql.sock" に接続しようとして、エラーとなります)

以上で、 mysql-python のインストールは無事完了となります

2011年8月3日水曜日

NetBeans IDE 7.0.1 リリース

NetBeans IDE 7.0.1 がリリースされました
ダウンロードはコチラからできるようになっております

恒例のスプラッシュです


今回は、先日リリースされた Java SE 7 の完全対応がメインとなっています
その他には、同梱されている Glassfish のバージョンがあがっていること、いくつかのバグフィックスがなされていることなどがあります

現在、7.0 をお使いの方は、自動アップデートにて 7.0.1 相当になりますので、再インストールすることなく、アップグレードできます

何かお気づきの点などありましたら、 ML 等へご連絡頂ければと思います

2011年4月21日木曜日

NetBeans IDE 7.0 リリース

当初の予定よりも遅くなりましたが、 NetBeans IDE 7.0 がリリースされました
ダウンロードはコチラからできるようになっております

恒例のスプラッシュです


7.0 によって追加、または改善された主なポイントは以下のようになっています

・シンタックス、ヒントなどのエディタ拡張を含んだ、JDK 7 サポート
・WebLogic Application Server 、 GlassFish 3.1 サポートの改修
・Oracle Database サポートの改善
・HTML5 編集サポート
・Maven 3 サポートと IDE への同梱
・CDI、REST サービス、Java Persistence 、Bean Validation のサポート改善
・PHPリネームリファクタリング対応
・外部での変更検出の改善
・C/C++ サポートの更新

その他の機能については、 コチラを参照頂ければと思います

また、以前にも書いていますが、 7.0 より JUnit が同梱配布されなくなりましたので、 NetBeans 本体インストール後別途プラグインとしてのインストールが必要となります
手順は簡単ですので、詳細は以前のエントリを参考にして頂ければと思います

次回のリリースは、4月21日時点でのロードマップ上ではバージョン番号が7.0.1、リリース予定日が2011年の7月になっています
また、主要な実装機能もコチラにて掲載が始まっています
(バージョン番号からもわかる通り、メインはバグフィックスと JDK7 の対応強化となり、新機能追加の予定はないようです)

何かお気づきの点などありましたら、 ML 等へご連絡頂ければと思います

2011年4月12日火曜日

オープンソース NoSQL データベース OrientDB を使ってみる #3

前回の投稿から半年以上過ぎましたが、OrientDB の紹介3回目です
前の2回は以下の通りです

オープンソース NoSQL データベース OrientDB を使ってみる #1
オープンソース NoSQL データベース OrientDB を使ってみる #2

データ間の関連(リレーション)について紹介します
データ間の関連とは2つの異なるレコードを関連付けることで、データの透過的な参照や複雑なデータ構造の表現が可能となります

OrientDB では参照型( Referenced relationships )と組込型( Embedded relationships )という2種類の関連付けをサポートしています
参照型は、フィールドに対象レコードのレコードID(全レコードにてユニークとなるID)を持つことでデータ間の関連付けを行います
そのため、関連付ける各レコードは独立したレコードとして各々参照できる必要があります
対して組込型は、フィールドに直接レコードをそのものを設定するもので、組み込まれたレコードを独立して参照することはできません

また、参照、組込型として関連付けられるデータは 1:1 だけでなく、各々 List 、 Set 、 Map という 1:N 、または N:M の関係を作ることができます
(今回はこの部分の説明の詳細は省略させて頂きます)

それでは実際にデータの登録を行い、どのような構造のレコードが生成されるかを説明したいと思います
今回使用した環境は下記の通りです

・Mac OS X 10.6.7
・Java(TM) SE Runtime Environment (build 1.6.0_24-b07-334-10M3326)
・OrientDB 0.9.25
・NetBeans 7.0 RC2

以降は上記環境にて、サーバの起動、専用クライアント(コンソール)の接続まで完了している前提で進めます
サーバやクライアントの起動方法、クライアントを使用したレコード操作などについては、前々回のエントリを参照ください
また、文中で使われるレコードIDは環境により異なりますので、お使いの環境にあわせて読み替えてください

まず、テストデータを登録するため、下記クエリを実行して Person クラスと Group クラスを作成します
( ">" はプロンプトとなりますので、コピーして実行する際にはご注意ください)
> create class Person
> create class Group
次に Group クラス のデータを登録します
> insert into Group (name) values ('Rebel Alliance')
> insert into Group (name) values ('Galactic Empire')
下記コマンドで Group クラスに2レコード登録されたことが確認できます
> browse class Group
---+--------+--------------------
  #| REC ID |NAME                
---+--------+--------------------
  0|    25:0|Rebel Alliance      
  1|    25:1|Galactic Empire     
---+--------+--------------------
"REC ID" は先の説明のレコードIDを指し、 "Rebel Alliance" は "25:0" 、 "Galactic Empire" は "25:1" のレコードIDを持つこととなります

次に参照型の関連フィールドを持つレコードを作成します
関連付けるレコードは先ほど登録した Group クラスのレコードです
下記クエリを実行して、 レコードを登録します
> insert into Person (name, surname, group) values ('Luke', 'Skywalker', 25:0)
> insert into Person (name, surname, group) values ('Han', 'Solo', 25:0)
> insert into Person (name, group) values ('Chewbacca', 25:0)
> insert into Person (name, surname, group) values ('Leia', 'Organa', 25:0)

> insert into Person (name, group) values ('Darth Sidious', 25:1)
> insert into Person (name, group) values ('Darth Vader', 25:1)
レコードに関連付けを設定する場合は、フィールドに対象のレコードIDを直接記述します
(そのため、事前に関連づけるレコードIDを知っておく必要があります)
上記の場合、 "group" というフィールドにレコードIDを設定しており、これで Person クラスと Group クラスの各レコードが関連付けられることとなります

下記コマンドで Person クラスに6レコード登録されたことが確認できます
> browse class Person
---+--------+--------------------+--------------------+--------------------
  #| REC ID |NAME                |SURNAME             |GROUP               
---+--------+--------------------+--------------------+--------------------
  0|    24:0|Luke                |Skywalker           |25:0                
  1|    24:1|Han                 |Solo                |25:0                
  2|    24:2|Chewbacca           |null                |25:0                
  3|    24:3|Leia                |Organa              |25:0                
  4|    24:4|Darth Sidious       |null                |25:1                
  5|    24:5|Darth Vader         |null                |25:1                
---+--------+--------------------+--------------------+--------------------
関連付けられたレコードに対しては、「フィールド名.対象レコードのフィールド名」の形式で指定することで値を参照することができます
以下は select 文にて group フィールドに関連付けられた、 Group クラスの name フィールドを参照しています
(where 句にある "@rid" はレコードIDを意味するレコード属性になります)
> select name, surname, group.name from Person where @rid = 24:0
---+--------+--------------------+--------------------+--------------------
  #| REC ID |NAME                |SURNAME             |GROUP               
---+--------+--------------------+--------------------+--------------------
  0|   -1:-1|Luke                |Skywalker           |Rebel Alliance      
---+--------+--------------------+--------------------+--------------------
また、他のフィールドと同様に where 句の検索条件としても使用できます
> select from Person where group.name = 'Rebel Alliance'
---+--------+--------------------+--------------------+--------------------
  #| REC ID |NAME                |SURNAME             |GROUP               
---+--------+--------------------+--------------------+--------------------
  0|    24:0|Luke                |Skywalker           |25:0                
  1|    24:1|Han                 |Solo                |25:0                
  2|    24:2|Chewbacca           |null                |25:0                
  3|    24:3|Leia                |Organa              |25:0                
---+--------+--------------------+--------------------+--------------------
Java API を利用する場合、参照型レコードの登録は以下のようになります
(import 文、パッケージ名は省略しますのでご注意下さい)
public class Main {

    public static void main(String[] args) {
        // admin ユーザでサーバーの demo データベースに接続します
        ODatabaseDocumentTx database = new ODatabaseDocumentTx("remote:localhost/demo").open("admin", "admin");

        // 新規レコード(Group)の作成
        ODocument jediOrder = new ODocument(database, "Group");
        jediOrder.field("name", "Jedi Order");
        jediOrder.save();

        // ユニークIDを取得
        ORID jediOrderORID = jediOrder.getIdentity();
        
        // 新規レコード(Rank)の作成
        ODocument master = new ODocument(database, "Rank");
        master.field("name", "Jedi Master");
        master.save();

        // ユニークIDを取得
        ORID masterOrderORID = master.getIdentity();

        ODocument knight = new ODocument(database, "Rank");
        knight.field("name", "Jedi Knight");
        knight.save();

        // ユニークIDを取得
        ORID knightOrderORID = knight.getIdentity();

        ODocument padawan = new ODocument(database, "Rank");
        padawan.field("name", "Padawan");
        padawan.save();

        // ユニークIDを取得
        ORID padawanOrderORID = padawan.getIdentity();

        // 新規レコード(Person)の作成
        ODocument yoda = new ODocument(database, "Person");
        yoda.field("name", "Yoda");
        yoda.field("group", jediOrderORID);
        yoda.field("rank", masterOrderORID);
        yoda.save();
        
        ODocument obiwan = new ODocument(database, "Person");
        obiwan.field("name", "Obi-Wan");
        obiwan.field("surname", "Kenobi");
        obiwan.field("group", jediOrderORID);
        obiwan.field("rank", knightOrderORID);
        obiwan.save();

        ODocument ahsoka = new ODocument(database, "Person");
        ahsoka.field("name", "Ahsoka");
        ahsoka.field("surname", "Tano");
        ahsoka.field("group", jediOrderORID);
        ahsoka.field("rank", padawanOrderORID);
        ahsoka.save();
        
        // 接続の解除
        database.close();
    }
}
上記では Group クラスに1レコード登録、Rank クラスの新規作成と3レコード登録、 Person クラスに3レコード登録しています
参照型の関連付けを行う方法はクエリを使用したケースと同様にフィールドにレコードIDを設定します
Java API にてレコードID( Java API では ORID クラスにて表現されています)を取得するには、ODocument クラスの getIdentity() メソッドを使用します
なお、新規レコードの場合、事前に save() メソッドを呼び出してデータベースに登録が完了していないとレコードIDは取得できませんので、ご注意ください

レコードを取得する場合は下記のようになります
public class Main {

    public static void main(String[] args) {
        // admin ユーザでサーバーの demo データベースに接続します
        ODatabaseDocumentTx database = new ODatabaseDocumentTx("remote:localhost/demo").open("admin", "admin");

        System.out.println("-----レコードIDを指定してレコードを取得-----");
        
        // RID=24:6(Yoda) を取得
        ODocument yoda = new ODocument(database, new ORecordId(24, 6));
        
        // group フィールドを取得
        ODocument yodaGroup = yoda.field("group");
        Object yodaGroupName = yodaGroup == null ? "" : yodaGroup.field("name");
        // rank 1フィールドを取得
        ODocument yodaRank = yoda.field("rank");
        Object yodaRankName = yodaRank == null ? "" : yodaRank.field("name");
        
        // 取得レコードの出力
        System.out.println("name   : " + yoda.field("name"));
        System.out.println("surname: " + yoda.field("surname"));
        System.out.println("group  : " + yodaGroupName);
        System.out.println("rank   : " + yodaRankName);
        System.out.println();

        System.out.println("-----クエリを実行してレコードを取得-----");
        
        // SELECT 文を作成する
        String selectQuery = "select from Person where group.name = 'Jedi Order' ";

        // クエリを実行する
        List<ODocument> people = database.query(new OSQLSynchQuery<ODocument>(selectQuery));

        for (ODocument person : people) {
            // group フィールドを取得
            ODocument group = person.field("group");
            Object groupName = group == null ? "" : group.field("name");
            // rank 1フィールドを取得
            ODocument rank = person.field("rank");
            Object rankName = rank == null ? "" : rank.field("name");

            // 取得レコードの出力
            System.out.println("name   : " + person.field("name"));
            System.out.println("surname: " + person.field("surname"));
            System.out.println("group  : " + groupName);
            System.out.println("rank   : " + rankName);
            System.out.println();
        }

        // 接続の解除
        database.close();
    }
}
上記を実行すると、以下のように値が取得できます
-----レコードIDを指定してレコードを取得-----
name   : Yoda
surname: null
group  : Jedi Order
rank   : Jedi Master

-----クエリを実行してレコードを取得-----
name   : Yoda
surname: null
group  : Jedi Order
rank   : Jedi Master

name   : Obi-Wan
surname: Kenobi
group  : Jedi Order
rank   : Jedi Knight

name   : Ahsoka
surname: Tano
group  : Jedi Order
rank   : Padawan

次に組込型の関連付けですが、現在(2011年4月12日時点)のバージョンではクエリによる組込型のレコードの登録、更新(参照は可能です)は対応しておらず、 Java API でのみとなります

Java API を利用する場合の登録は以下のようになります
public class Main {

    public static void main(String[] args) {
        // admin ユーザでサーバーの demo データベースに接続します
        ODatabaseDocumentTx database = new ODatabaseDocumentTx("remote:localhost/demo").open("admin", "admin");
        
        // 新規レコードを作成
        ODocument lightsaber = new ODocument(database, "Weapon");
        lightsaber.field("name", "Lightsaber");
        lightsaber.field("type", "sword"); 
        
        // RID=24:0(Luke) を取得
        ODocument luke = new ODocument(database, new ORecordId(24, 0));
        luke.field("weapon", lightsaber, OType.EMBEDDED);
        luke.save();
        
        database.close();
    }
}
上記では Weapon クラスのレコードを1件作成し、 Person クラスのレコードの "weapon" フィールドに設定しています
参照型と大きく異なる点は作成した Weapon クラスの save()メソッドを呼び出していない点、取得した Person クラスの "weapon" フィールドに設定する際、第3引数に "OType.EMBEDDED" を設定している点です

レコードの参照方法に関しては、組込型も参照型も差異はありません
>  select from Person where @rid = 24:0                          

---+--------+--------------------+--------------------+--------------------+--------------------
  #| REC ID |NAME                |WEAPON              |SURNAME             |GROUP               
---+--------+--------------------+--------------------+--------------------+--------------------
  0|    24:0|Luke                |-1:-1               |Skywalker           |25:0                
---+--------+--------------------+--------------------+--------------------+--------------------
参照型のフィールド "group" にはレコードIDの値("25:0")が設定されているのに対し、組込型は直接レコードが設定されているため、レコードIDは設定されていません
組込まれたレコードのフィールドも同様の形式で参照可能です
> select name, surname, weapon.name, weapon.type from Person where @rid = 24:0

---+--------+--------------------+--------------------+--------------------+--------------------
  #| REC ID |NAME                |WEAPON              |SURNAME             |WEAPON2             
---+--------+--------------------+--------------------+--------------------+--------------------
  0|   -1:-1|Luke                |Lightsaber          |Skywalker           |sword               
---+--------+--------------------+--------------------+--------------------+--------------------
以上が OrientDB の関連付けの機能の紹介と利用方法になります

次回は、 OrientDB のグラフデータベースとしての機能を紹介したいと思います
(次はあまり期間をあけないようしたいと思います…)

2011年4月9日土曜日

NetBeans IDE 7.0 RC 2 リリース

NetBeans IDE 7.0 RC2 がリリースされました
ダウンロードはコチラからできるようになっております

恒例のスプラッシュです


リリース予定が延びて、(4月9日現時点では)4月中予定というざっくりとした感じになったみたいです
何かお気づきの点などありましたら、 ML 等へご連絡頂ければと思います

2011年3月30日水曜日

NetBeans IDE 7.0 RC 1 リリース

NetBeans IDE 7.0 RC1 がリリースされました
ダウンロードはコチラからできるようになっております

恒例のスプラッシュです


既に3月も終わろうとしていますが、本日(2011年3月30日)時点では4月4日の正式リリース予定に変更はないようです
何かお気づきの点などありましたら、 ML 等へご連絡頂ければと思います

2011年3月21日月曜日

プログラミング言語 efene について

今回はプログラミング言語 efene についてです

efene は2010年1月にバージョン 0.1 をリリースし、開発がスタートした新しい言語で、 Erlang が提供する、 ErlangVM 上で動作し、Erlang とほぼ 100% の互換性を持つことを目標として実装されています

ErlangVM 上で動く言語としては、 Ruby に似た文法を持つ、 reiaElixir、 LISP 文法の LFE(Lisp Flavoured Erlang) などがありますが、これらは直接 ErlangVM 用のバイトコードを出力するのに対して、 efene は一度 Erlang のソースコードに変換し、 Erlang のソースコードとしてコンパイルして、バイトコードを出力しており、そのため Erlang との高い互換性を実現できています

文法は "{...}" でブロックを表す JavaScript 、またはインデントでブロックを表す Python に似た 2種類の構文で記述が可能で、 C / C++ 、 Java や LL 言語の開発者にはちょっとクセのある Erlang の文法よりもなじみやすいと思います
公式のドキュメントでは JavaScript 形式を efene 、 Python 形式を ifene (idented efene) とし、各拡張子を fn、ifnとするようにしていますが、コンパイラレベルでは区別はないようで、1つのファイルに efene 、ifene の文法が混在していても、コンパイル可能なようです(そんな実装をすることはないと思いますが…)

まずは、efene のコンパイル、実行環境をインストールします
インストールには agner を利用します
(もちろん、 agner を使用せず、ソースから直接ビルドして利用することも可能です)
agner については、コチラの記事を参照ください
ターミナル等で下記コマンドを実行します
$ agner install efene
インストールが正常に完了したら、環境変数 FNPATH を設定します
(今回 .bashrc ファイルに環境変数を記述しますが、お使いの環境に合わせて適宜読み替えてください)
$ vi ~/.bashrc
内容は以下の通りとなります
(例では agner を使用してインストールしたものですので、直接ソースコードよりビルド、インストールした場合は読み替えて設定してください)
export FNPATH=/usr/local/agner/packages/efene-\@master
以上で、 efene を実行する準備が完了です

定番の "Hello World!" は efene では以下のように書きます
@public
run = fn () {
    io.format("Hello World!~n")
}
上記の内容を、ファイル名を "hellofn.fn" として保存します

簡単な文法の説明は以下の通りです
(細かい用語の説明は行っていませんが、ご了承ください)
1行目の "@public" は以降に定義される関数へのアクセス権を表すもので、モジュール外からアクセス可能であることを表します
2行目の "run = fn () {" は "run" という引数を持たない関数を定義しています
関数の実態(処理内容)は以降の行("{...}"ブロック内)に定義しています
3行目の " io.format("Hello World!~n")" は "io" モジュールの "format()" 関数に 表示する "Hello World!~n" という文字列を渡しています
文字列内の "~n" は改行を表します
4行目の "}" は関数の処理部分(ブロック)の終端となります
また、4行目の "}" 記述後に必ず、改行を入れてください
(改行がない場合は、コンパイルエラーとなります)

下記 fnc コマンドを実行し、コンパイルします
$ fnc hellofn.fn
コンパイル後、下記のように実行します
$ fnc -r hellofn run
実行後、下記のように表示されます
(以下の表示は実行したコマンドも含めて記述しています)
$ fnc -r hellofn run
Hello World!

ifene では以下のように書きます
(ファイル名は "helloifn.ifn" として保存します)
@public
run = fn ()
    io.format("Hello World!~n")

efene 版と処理内容の違いは全くないのですが、ブロックを "{...}" ではなく、インデントで表すため、 "{" と "}" がなくなっています
コンパイル、実行も efene 版と同様です
(コンパイル、実行、実行結果をまとめて以下に記述します)
$ fnc helloifn.ifn
Compiling helloifn.ifn
$ fnc -r helloifn run
Hello World!
文法に関する詳細は公式ドキュメントを参照頂ければと思います

次に、 Erlang の関数型言語としての面を紹介する際によく出てくる、 クイックソートというアルゴリズムの実装を紹介します
Erlang 版のクイックソートは以下のように書かれます
(Wikipedia の "Erlang" の項目より引用しています)
%% quicksort:qsort(List)
%% Sort a list of items
 -module(quicksort).
 -export([qsort/1]).
 
 qsort([]) -> [];
 qsort([Pivot|Rest]) ->
     qsort([ X || X <- Rest, X < Pivot]) ++ [Pivot] ++ qsort([ Y || Y <- Rest, Y >= Pivot]).
efene では以下のように記述することができます
@public
qsort = fn([]) {
  []
}

fn([Pivot : Rest]) {
  qsort([X for X in Rest if X < Pivot]) ++ [Pivot] ++ qsort([Y for Y in Rest if Y >= Pivot])
}
ブロックを明示的に記述している分、若干コードの量は増えていますが、ほぼ同様に書くことができます
また、 efene コマンドの機能として、"-t erl" オプションを指定すると Erlang 形式にて出力することが可能です
上記クイックソートのコードを Erlang 形式に出力した場合は以下のようになります
$ fnc -t erl quicksort.fn
-module(quicksort).

-export([qsort/1]).

qsort([]) -> [];
qsort([Pivot | Rest]) ->
qsort([X || X <- Rest, X < Pivot]) ++ [Pivot] ++ qsort([Y || Y <- Rest, Y >= Pivot]).

Erlang のプロセス間通信(非同期メッセージ転送)も使用することができます
@public
ping = fn(0, Pong_PID) {
  Pong_PID ! finished
  io.format("Ping finished~n")
}

fn(N, Pong_PID) {
  Pong_PID ! (ping, self())
  
  receive (pong) {
    io.format("Ping received pong~n")
  }
  
  ping(N - 1, Pong_PID)
}

@public
pong = fn() {
  receive (finished) {
    io.format("Pong finished~n")
  } else receive (ping, Ping_PID) {
    io.format("Pong received ping~n")
    Ping_PID ! pong
    pong()
  } 
}

@public
run = fn() {
  Pong_PID = spawn(pingpong, pong, [])
  spawn(pingpong, ping, [3, Pong_PID])
}
コンパイルし、実行すると、下記のように表示されます
$ fnc -r pingpong run
Pong received ping
Ping received pong
Pong received ping
Ping received pong
Pong received ping
Ping received pong
Ping finished
Pong finished
Erlang で書かれたライブラリをそのまま利用することも可能です
下記例では Riak という NoSQL データベースの Erlang 用クライアントライブラリ riak-erlang-client を使用する例です
(なお、Riak 、riak-erlang-client に関する詳細やインストール、利用方法などの説明は省略しています)
@public
run = fn () {
  (ok, Pid) = riakc_pb_socket.start_link("127.0.0.1", 8087)
  riakc_pb_socket.ping(Pid)
  Object = riakc_obj.new(<["groceries"]>, <["mine"]>, <["eggs & bacon"]>)
  riakc_pb_socket.put(Pid, Object)
  (ok, O) = riakc_pb_socket.get(Pid, <["groceries"]>, <["mine"]>)
   io.format("~p~n", [O])
}
コンパイルし、実行すると、下記のように表示されます
$ fnc -a ./riakc/ebin -a ./riakc/deps/protobuffs/ebin -r riakc run
{riakc_obj,<<"groceries">>,<<"mine">>,
<<107,206,97,96,96,224,202,96,202,5,82,108,205,73,140,156,46,143,50, 152,18,25,243,88,25,30,73,188,61,198,7,145,96,97,10,11,92,135,41, 12,84,207,254,242,132,56,84,34,58,227,61,92,61,219,145,174,61,152, 194,64,245,108,246,60,90,80,137,110,100,245,58,114,2,152,194,64, 245,172,12,115,68,161,18,223,196,127,195,213,179,79,121,84,140,77, 216,38,175,19,42,204,32,241,27,201,24,134,199,6,26,200,18,89,0>>,
[{{dict,2,16,16,8,80,48,
{[],[],[],[],[],[],[],[],[],[],[],[],[],[],[],[]},
{{[],[],[],[],[],[],[],[],[],[],
[[<<"X-Riak-VTag">>,87,51,74,53,119,109,67,70,90,50,86,
70,53,115,51,75,82,102,85,106,76]],
[],[],
[[<<"X-Riak-Last-Modified">>|{1300,667392,457396}]],
[],[]}}},
<<"eggs & bacon">>}],
undefined,undefined}
fnc コマンドにて "-s" オプションを付加することでシェルを起動することができます
このシェルでは計算や簡単な入出力が行えます
$ fnc -s
>>> 1+1
2
>>> A = "efene"
[101, 102, 101, 110, 101]
>>> io.format("Hello, ~s.~n", [A])
Hello, efene.
ok
シェルは "Ctrl+C" を押し、さらに "a" を押すことで停止することができます
なお、 Erlang のシェルと比較して、履歴機能がない、束縛した変数の表示や解放などの機能が実装されていなかったりとやや貧弱な面があります
(履歴に関しては、 rlwrap コマンドと一緒に使うことで擬似的に実現することは可能です)
また、簡単な使用には支障はないかと思いますが、表示部分にバグがあるようです
(上記 Riak クライアント利用もシェルにて実行可能なのですが、最後のデータ取得後の表示にてエラーが発生します)

以上のように、 efene は JavaScript / Python ライクな文法で Erlang の強力な機能を使用できる環境を提供してくれます
Erlang の文法に抵抗を感じていた人でも入りやすいと思います
しかし、やはり障害が発生した場合には最終的に Erlang のコードを読むことも多く、 efene を使えば、 Erlang に関しての知識が不要というわけではないので、ご注意ください

Erlang については Voluntas さんのブログ"Erlang に興味を持った人へ" がお勧めです
(Erlang での開発に関する貴重な最新情報が記載されています)

時間があるときに、(今更ですが)基礎文法最速マスターも書いてみたいなと思います

2011年3月10日木曜日

Erlang パッケージ管理ツール Agner を試す

Erlang には様々なライブラリが存在しますが、依存関係やバージョン管理を個別に管理するのは大変です
このような問題に対して、 Perl には CPAN 、 Ruby には RubyGems といったパッケージリポジトリや管理ツールがあります
Erlang では CEANFaxien などが有名ですが、今回は Agner という新しいツールを紹介します

Agner は ClojarsHomebrew の影響を受けたパッケージ管理ツールです
そのため、これらのツールを利用するユーザには使いやすいと思われます
(ちなみにツール名の Agner は "A Giant Nebula of Erlang Repositories" の頭文字を取った略称であり、Erlang の名前の起源となった数学者 Agner Krarup Erlang への敬意を表したものでもあるとしていますが、そのため erlang という単語と組み合わせたときに検索しづらくなってもいます)
なお、管理しているパッケージ数は上記のような有名なツールには劣りますが、主要なライブラリは登録されているように思います

インストールは下記コマンドを実行して行います
$ curl https://github.com/agner/agner/raw/master/scripts/oneliner | sh

下記コマンドを実行して、バージョン情報が表示されれば、インストールは完了です
$ agner version
0.4.12

現在管理しているパッケージ情報の一覧は下記コマンドにて確認できます
$ agner list

パッケージのビルドには下記コマンドを使います
$ agner build [パッケージ名]

パッケージのインストールには下記コマンドを使います(インストールスクリプトが書かれていないパッケージはインストールできません)
$ agner install [パッケージ名]

パッケージのアンインストールには下記コマンドを使います
$ agner uninstall [パッケージ名]

上記以外にも複数のコマンドやオプション指定できますので、詳しくは公式 Wiki を確認頂ければと思います

2011年3月9日水曜日

Mac OS X に Erlang をインストールする

Mac OS X に Erlang をインストールする方法の紹介です

Windows 環境の場合では、公式ページにてバイナリが配布されていますが、Mac用はありません
そのため、ソースからビルドする必要がありますが、 Homebrew などのパッケージ管理ツールを入れていると簡単に導入することができます
Homebrew を使用した Erlang のインストール方法は以下の通りです
(インストール前にパッケージリストを最新にすることをおすすめします)

$ brew install erlang

上記コマンド実行後、github から最新のソースコードを取得し、ビルドします
(2011年03月09日時点での最新バージョンは R14B01 です)
ビルド完了後、下記コマンドを実行して、バージョン情報が表示されれば、インストールは完了です

$ erl -version
Erlang (SMP,ASYNC_THREADS,HIPE) (BEAM) emulator version 5.8.2

2011年2月20日日曜日

NetBeans IDE 7.0 Beta 2 リリース

NetBeans IDE 7.0 Beta2 がリリースされました
ダウンロードはコチラからできるようになっております

恒例のスプラッシュです

既にご存知の方も多いかと思いますが、ライセンスの関係で NetBeans と JUnit は(ライセンス問題が解決するまでは)同梱されて配布されなくなるようです
といっても、同梱されないだけで、ユーザ自身でライセンスに承認することで関連モジュールと一緒にダウンロード、インストールすることが可能となっており、インストール後は従来通りの機能が利用できます

まず、インストール直後の初回起動にて、下記のようなメッセージが表示されます
(現在は英語で表示されていますが、日本語化が進めば、日本語のメッセージが表示されると思います)

「了解」ボタンをクリックすることで、ダウンロードを開始します


ダウンロードが終了すると、インストール画面が表示されます

「次へ」ボタンをクリックすると、JUnit ライセンス承認となりますので、内容を確認後、承認する場合は「すべてのライセンス契約条件に同意する。」チェックボックスをチェックし、「インストール」ボタンをクリックします。

以降はウィザードの指示に従い、 NetBeans の再起動を行って終了です
Beta 2 では JUnit 4.8.2 を利用することができます

正式リリースまでにライセンス問題が解決するかは不明ですので、インストール後に上記のようなひと作業があることを念頭に入れておく必要がありそうです

また、Beta 2 では以前ご紹介させて頂いていた Git サポートがインストール可能となっています
アップデートセンターの登録など、特別な設定をしなくても「使用可能なプラグイン」として表示されます
※開発途中のプラグインですので、ご利用は自己責任でお願いします

Beta 2 以降は、3月にRCリリース、4月に正式リリース予定となっています
何かお気づきの点などありましたら、 ML へご連絡頂ければと思います

2011年1月14日金曜日

プロジェクトのアイコンを変えるプラグインを作ってみる

2011年1回目で早速一発ネタです

NetBans のプロジェクトウィンドウに表示されるアイコンをプラグインで変える方法についての紹介です
なお、7.0 以降に実装予定の API を使用していますので、お試しされる際には 7.0 Beta などをご使用下さい
また、実装予定の機能ですので、正式なリリースでは実装されない可能性があります
ご注意下さい

まず、事前に必要なものはプロジェクトのアイコンと差し替える画像です
16 x 16 のサイズの画像をご用意してください
今回は 以前作成したねこび〜んアイコンの画像を使用します
(オリジナルのねこび〜んはカネウチカズコさんによるものです)

次にモジュール用のプロジェクトを作成します

プロジェクト名などは適当な値を設定してください
プロジェクト作成後、事前に準備した画像ファイルを適当な場所にコピーします
(今回の例では、"resources" ディレクトリを作成し、その中にコピーしています)

次は今回のプラグイン(モジュール)に必要な API の設定を行います
プロジェクトのプロパティ画面の「ライブラリ」カテゴリを選択し、「ライブラリの依存関係」タブの「追加」ボタンをクリックし、"Lookup API"、"プロジェクト API"、"ユーティリティ API"の3つのAPIを追加します
追加後は下記のように表示されます

「了解」ボタンをクリックして、プロパティ画面を閉じます
最後にアイコンの差し替えに必要なクラスを作成します
(といっても、1クラスのみですが…)

クラスの中身は下記の通りです
(パッケージやクラス名は適当ですので、適宜読み替えてください)

package nekobean;

import java.awt.Image;
import javax.swing.event.ChangeListener;
import org.netbeans.api.project.Project;
import org.netbeans.spi.project.ProjectIconAnnotator;
import org.openide.util.ImageUtilities;
import org.openide.util.lookup.ServiceProvider;

@ServiceProvider(service = ProjectIconAnnotator.class)
public class NekoBeanProjectIcon implements ProjectIconAnnotator {

    // アイコンの読み込み
    private final Image nekoBeanIcon = ImageUtilities.loadImage("nekobean/resources/nekobean.png");

    @Override
    public Image annotateIcon(Project project, Image original, boolean bln) {
        // 読み込んだアイコンを返します
        return nekoBeanIcon;
    }

    @Override
    public void addChangeListener(ChangeListener cl) {
    }

    @Override
    public void removeChangeListener(ChangeListener cl) {
    }
}

今回使う API は ProjectIconAnnotator インターフェイスです
インターフェイス名からわかる通り、プロジェクトのアイコンに注釈(エラーマークなどのバッジ)を表示するための API ですので、今回のような使い方はいわば邪道だったりします
なお、 6.9.1 以前のバージョンではこの API が存在しないため、プロジェクトツリーが表示される前にアイコンを変更することは無理っぽいです
(詳しくは、 LogicalViewProvider を実装した各プロジェクトタイプのクラスなんかを見るとわかるかと思います)

最終的に、プロジェクトは以下のような構成になります

このプラグインを実行すると、以下のように表示されます

ということで、プロジェクトのアイコンを変えるプラグインについては以上です
今年は、昨年よりはもう少しエントリの数が増えるよう頑張りたいと思いますので、何卒よろしくお願いします