2011年3月22日火曜日

はてなダイアリーに移行中

この間JavaやScala、Valaなど、サンプルコードをともなう投稿が増えてきたため、強調表示やWiki記法による軽量なマークアップなどいろいろ便利な感じのはてなダイアリーに移行することにしました。引きつづきValaその他について載せていきます。よろしく。

■m12i/d http://d.hatena.ne.jp/m12i/

2011年3月14日月曜日

WindowsでValaを動かす

きょうはちょっと小休止。「JavaプログラマーからみたVala」は置いておいて、公式サイトにあった別のメモの翻訳を載せます。

原典は、Vala on Windows(2011年3月14日取得)です。

******************************

WindowsでValaを動かす

Valaはいつもソースコードの形式でリリースされます。しかしValaコミュニティのメンバーが、Windows向けのバイナリを提供しています。.exeファイルとして提供されているインストーラにより、Windowsのための必要最低限のGNU環境(MinGW)──GlibやGTK+といったライブラリとともに、CコンパイラとValaコンパイラを提供します──をインストールできます。

インストールが終わると、次のようにしてValaプログラムをコンパイルできるようにります。
> valac hello.vala

GTK+ライブラリを使用したアプリを起動した際に、コンソールウィンドウが表示されてしまう問題を抑制するためには、次の手順をとってください。

  • MinGW API for MS-Windowsをダウンロードします。“w32api-x.xx-mingw32-dev.tar.gz”という形式の名前が付いたファイルです。(訳者:“dev”という接尾辞のあるものです。)
  • ダウンロードしたアーカイブファイルを、Vala(もしくはMinGW)がインストールされているディレクトリに展開します。(訳者:前述の.exeを使用してValaコンパイラ環境をインストールすると、Cディレクトリ直下に“vala-x.xx.x”というディレクトリが作成されます。このディレクトリには、libincludeといったディレクトリが配置されています。MinGW API for MS-Windowsのアーカイブファイルを展開するとlibincludeといったディレクトリがあらわれるので、これらをC:\vala-x.xx.x/libC:\vala-x.xx.x/includeに上書きします。)
  • Valaコンパイラを“-X –mwindows”というオプションとともに呼び出します(訳者: “-X –xxx”というのは“-xxx”の部分がCコンパイラに与えられるオプションであることをあらわしています)。
> valac -X -mwindows --pkg gtk+-2.0 hellogtk.vala

(最終更新: 2011年1月4日 13:04 /執筆: NicolasJoseph)

******************************

2011年3月13日日曜日

JavaプログラマーからみたVala (4) クラス②

最近なにかの拍子にVala言語に興味を持ってしまいました。Web上のドキュメントは限られているものの、Java言語との比較など平易なドキュメントもありましたので、学習をかねて稚拙な翻訳を載せていこうと思います。

原典は、“Vala for Java Programmers”(2011年3月13日取得)です。

******************************

JavaプログラマーからみたVala (4) クラス②

列挙型

Javaの場合: 列挙型はクラスをベースにしています。

Valaの場合: 列挙型は整数をベースにしています。メソッドは持てますが、コンストラクターやフィールドなどは持つことができません。
enum Season {
    SPRING,
    SUMMER,
    AUTUMN,
    WINTER;

    public bool is_hot () {
        return this == SUMMER;
    }
}

実行時の型判別

動的型チェック

Javaの場合: instanceof演算子を使用します。
Valaの場合: is演算子を使用します。

動的型キャスト

Javaの場合: Foo foo = (obj instanceof Foo) ? (Foo) obj : null

Valaの場合: Foo foo = obj as Foo

もちろん、 "(obj is Foo) ? (Foo) obj : null"も同様に有効な式です。

型情報を取得する

Javaの場合:
Class c = Foo.class;
System.out.println(c.getName());
Foo = (Foo) c.newInstance();

Valaの場合: typeof()を使用します。
Type t = typeof (Foo);
stdout.printf ("%s\n", t.name ());
Foo o = (Foo) Object.new (t);

オブジェクトの破棄

Javaの場合: 終了化子(finalizers)は、非決定論的です。
public class Foo {
    @Override
    protected void finalize() {
    }
}

Valaの場合: デストラクタ(destructors)は、決定的です。
public class Foo : Object {
    ~Foo () {
    }
}

アノテーション

Javaの場合: アノテーションは自己定義的です。

Valaの場合: アノテーションの代わりに属性(attributes)を用います。属性はコンパイラに組み込まれています。書式は、“[AttributeName (param1 = value, param2 = value)]”というかたちです。バインディング(bindings)やD-Busインターフェースのためにしばしば使用さてます。バインディングのために使用されるいちばんよく見る属性は、“[CCode (...)]”です。

プロパティ

Javaの場合: Bean規約が用いられます。getX()setX()という形式のメソッドです。
public class Person {
    private int age = 32;

    public int getAge() {
        return this.age;
    }

    public void setAge(int age) {
        this.age = age;
    }

    public static void main(String[] args) {
        Person p = new Person();
        p.setAge(p.getAge() + 1);
    }
}

Valaの場合: プロパティ──get {} ・ set {}ブロック──がサポートされており、フィールドのようにアクセスできます。
public class Person : Object {
    private int _age = 32;

    public int age {
        get { return _age; }
        set { _age = value; }
    }
}

void main () {
    var p = new Person ();
    p.age++;
}

標準的な実装であれば、さらに短くできます。
public class Person : Object {
    public int age { get; set; default = 32 }
}

デリゲート、クロージャ

Javaの場合: デリゲート・パターンの実装は、匿名内部クラスを使用することになります。
public interface MyDelegateType {
    public void invoke(int a, double b);
}

public class Demo {
    private static void foo(MyDelegateType deleg) {
        deleg.invoke(32, 0.25);
    }

    public static void main(String[] args) {
        MyDelegateType deleg = new MyDelegateType () {
            public void invoke(int a, double b) {
                System.out.println("a = " + a + "; b = " + b);
            }
        };
        deleg.invoke(42, 0.75);
        foo(deleg);
    }
}

Valaの場合: Vala言語は、デリゲートとクロージャをサポートしています。
delegate void MyDelegateType (int a, double b);

void foo (MyDelegateType deleg) {
    deleg (32, 0.25);     // invoke delegate
}

void main () {
    MyDelegateType deleg = (a, b) => {
        stdout.printf ("a = %d; b = %g\n", a, b);
    };
    deleg (42, 0.75);     // invoke delegate
    foo (deleg);          // pass delegate to a method
}

クロージャは外部スコープ(それ自身が定義されたスコープ)のローカル変数を束縛する無名のメソッドです(訳者:JavaScriptの関数がまさにそれです。Java6ではfinal宣言された変数でないと外部スコープの変数にはアクセスできませんが、JavaScriptも含め他の言語の中にはこうした変数の読み書きを行えるものがあります。JavaScriptではこの方法で他のコードがアクセスできない文字通り匿名の名前空間を展開・保持するテクニックが頻繁に使用されます)。クロージャはデリゲート型の変数に代入したり、デリゲート型の引数として他のメソッドに渡すことができます。

Java言語においては、匿名内部クラスにより、クロージャのまねごとができます。しかし匿名内部クラスが束縛できる外部スコープ・ローカル変数は、final宣言されたものだけです。一方、Vala言語ではクロージャはいかなる変数でも束縛できます。Java7ではクロージャのサポートが計画されています。メソッドは直接デリゲート変数に代入できます。
delegate int MyDelegateType (int a, double b);

int add (int a, int b) {
    return a + b;
}

int sub (int a, int b) {
    return a - b;
}

void main () {
    MyDelegateType deleg = add;
    int sum = deleg (2, 3);
    deleg = sub;
    int diff = deleg (8, 4);
}

このことが示すのは、メソッドは(訳者:クロージャに限らずこれまで登場してきたあらゆる種類のメソッドは)オブジェクト同様に変数に格納したり引数として渡したりできるということです。

******************************

JavaプログラマーからみたVala (5)につづく──

JavaプログラマーからみたVala (3) クラス

最近なにかの拍子にVala言語に興味を持ってしまいました。Web上のドキュメントは限られているものの、Java言語との比較など平易なドキュメントもありましたので、学習をかねて稚拙な翻訳を載せていこうと思います。

原典は、“Vala for Java Programmers”(2011年3月13日取得)です。

******************************

JavaプログラマーからみたVala (3) クラス

継承

Javaの場合: extendsimplementsを使用します。
public class Demo extends Foo implements Bar {
    public Demo() {
        super();
    }
}

Valaの場合: コロンとそれに続くカンマ区切りリストであらわします。このリストには親クラスもインターフェースもともに含まれます。
public class Demo : Foo, Bar {
    public Demo () {
        base ();
    }
}

Vala言語では親クラス(super)を基本クラス(base)と呼びます。

オブジェクトベースクラス

Javaの場合: すべてのクラスはObject(java.lang.Object)から暗黙的に継承します。
public class Foo {
    // ...
}

Valaの場合: Object(Glib.Object)からの暗黙的な継承は行われません。
public class Foo : Object {
    // ...
}

Glib.Objectからの継承を行わないとどうなるのでしょうか? このような場合、そのクラスは若干軽量になる一方、プロパティ変更通知(property change notifications)などのいくつかの機能を欠いたものになります。そしてこのクラスは共通基本クラスを持たないことになります。たいていの場合、Glib.Objectからの継承は必要となるでしょう。

メソッド多重定義

Javaの場合: 以下の例のようにメソッドの多重定義(overloading)が行えます。
public class Demo {

    public void draw(String text) { }

    public void draw(Shape shape) { }


    /* メソッドのオーバーロード、
      そしてより引数の数の少ないメソッドによる、
        引数の数の多いそれの利用*/

    void f(int x, String s, double z) { }

    void f(int x, String s) {
        f(x, s, 0.5);
    }

    void f(int x) {
        f(x, "hello");
    }
}

Valaの場合: メソッドの多重定義はできません。別名を付けるか、引数にデフォルト値を指定することで代わりとします。
public class Demo : Object {

    public void draw_text (string text) {
    }

    public void draw_shape (Shape shape) {
    }

    /* 引数にデフォルト値が指定されたメソッド */
    void f (int x, string s = "hello", double z = 0.5) {
    }
}

Vala言語がメソッド多重定義の機能をサポートしないのは、Valaのライブラリが、C言語コードからアクセス可能であるよう意図して記述されているからです(意訳)。

コンストラクタ多重定義

Javaの場合: コンストラクタの多重定義ができます。
public class Foo {
    public Foo() { }
    public Foo(int foo) { }
    public Foo(String bar) { }
}
new Foo();
new Foo(42);
new Foo("hello");

Valaの場合: 多重定義ではなく、名前付きコンストラクタ(named constructors)を使用します。
public class Foo : Object {
    public Foo () { }
    public Foo.with_foo (int foo) { }
    public Foo.from_bar (string bar) { }
}
new Foo ();
new Foo.with_foo (42);
new Foo.from_bar ("hello");

コンストラクタ連鎖

Javaの場合: “this()”記法で実現します。
class Foo {
    public Foo() {
        this("bar");
    }

    public Foo(string bar) {
    }
}

Valaの場合: “this()”記法もしくは“this.コンストラクタ名 ()”記法で実現します。
class Foo : Object {
    public Foo () {
        this.with_bar ("bar");
    }

    public Foo.with_bar (string bar) {
    }
}

オーバーライド

Javaの場合: すべてのメソッドはデフォルトで仮想メソッド(C#で導入された概念。オーバーライド可能なメソッド)です。オーバーライドを阻止するにはfinal修飾子を使用します。
public class Super {
    public int myMethod(int x, int y) { }
    public final void anotherMethod() { }
}

public class Sub extends Super {
    @Override
    public int myMethod(int x, int y) {
        super.myMethod(x, y);
        // ...
    }
}

Valaの場合: すべてのメソッドは、デフォルトで非仮想メソッド(オーバーライド不可能なメソッド)です。オーバーライドを可能にするには明示的にvirtual修飾子を使用する必要があります。 他方、Vala言語には@Overrideアノテーションの代わりにoverride修飾子があり、この修飾子の使用は任意ではありません(強制です)。
public class Super : Object {
    public virtual int my_method (int x, int y) { }
    public void another_method () { }
}

public class Sub : Super {
    public override int my_method (int x, int y) {
        base.my_method (x, y);
        // ...
    }
}

アクセス修飾子


Java
Vala
public
public
protected
protected
package-private (デフォルト)
internal
private
private (デフォルト)

クラスメンバーのアクセスはデフォルトでprivateですが、publicアクセスのメンバーと対称的にさせるために、明示的にprivate修飾子を使用することもできます。

インターフェース

Javaの場合: インターフェースのメソッドは暗黙のうちに抽象メソッドです。
public interface Foo {
    public void foo(int i);
    public int bar(String s, double d);
}

Valaの場合: abstract修飾子は明示的に使用する必要があります。
public interface Foo {
    public abstract void foo (int i);
    public abstract int bar (string s, double d);
}

なぜでしょう? それはVala言語におけるインターフェースが非抽象メソッド(実装をともなうメソッド)をメンバーとすることができるからです。つまりVala言語のインターフェースは、いわゆるミックスイン(mixins。限定的な多重継承)を実現するために利用できるのです。
Vala言語におけるインターフェースは、──例えばファクトリーメソッドのような──staticメソッドを持つこともできます。

Javaの場合: インターフェースは継承可能です。
public interface IfaceA {
    public void methodA();
}

public interface IfaceB extends IfaceA {
    public void methodB();
}

public class Demo implements IfaceB {
    public void methodA() { }
    public void methodB() { }
}

Valaの場合: インターフェースは必要条件として働きます。
interface IfaceA : Object {
    public abstract void method_a ();
}

interface IfaceB : Object, IfaceA {
    public abstract void method_b ();
}

class Demo : Object, IfaceA, IfaceB {
    public void method_a () { }
    public void method_b () { }
}

Valaでは、インターフェースは他のインターフェースから継承できません。しかし他のインターフェースを必要条件として宣言できます。これによりおおよそ同じことを実現できます。インターフェースは、インターフェースだけでなくクラスも前提条件として宣言することができます。これにより、あるインターフェース(を継承したあるクラス)のインスタンスが、Glib.Objectのサブクラスでもあることを保証することができます。この事実──インターフェースは他のインターフェースのメンバーを継承できない──は、ほとんど技術的なちがいでしかありません。実際のところVala言語のインターフェースのシステムは、Javaにおけるそれと同じように働きます。ただ、Valaにおいてはクラス継承を必要条件とするという機能もある、ということです。

******************************

JavaプログラマーからみたVala (4)につづく── 

JavaプログラマーからみたVala (2) 型

最近なにかの拍子にVala言語に興味を持ってしまいました。Web上のドキュメントは限られているものの、Java言語との比較など平易なドキュメントもありましたので、学習をかねて稚拙な翻訳を載せていこうと思います。

原典は、“Vala for Java Programmers”(2011年3月13日取得)です。

******************************

JavaプログラマーからみたVava(2)

基本型
  • 標準的な型(intやlongなど)のサイズはアーキテクチャに依存します。こうした型のサイズを求めるには、sizeof()を使用します。例えば、sizeof(int)といった具合です。
  • Valaで追加された型──int8、int16、int32、int64(すべて符号あり)、uint8、uint16、uint32、uint64(すべて符号なし)は、アーキテクチャ非依存であることが保証されています。
  • byte型はありません。(代わりにuint8を使用しましょう。)
  • Javaにおけるboolean型は、Valaではbool型です。 
  • Valaで追加された基本型には、unichar型があります。これはユニコード文字をあらわします。
定数修飾子は、finalではなくconstです。

Vala言語では基本型もメソッドを持ちます。例えば以下のように──
int a = -4.abs ();
string s = a.to_string ();
int b = int.max (5, 7); // int型の静的メソッドが呼ばれています。


文字列型

Javaの場合:

型名は、Stringです。
意味的等価性をチェックするにはequals(String)メソッドを使用します。

Valaの場合:

型名はstringです。(小文字です。)
意味的等価性をチェックするには==演算子を使用します。

Valaでは文字列の(==演算子による)比較は、内容ベースで行われます。参照ベースではありません。<、>、<=、>=などの比較演算子は、文字列の辞書的比較に使用できます。文字列はswitch文で使用できます。

Vala文字列はUTF-8で保持されます。

Vala言語における文字列のその他の特徴

Vala言語は逐語的文字列リテラル(verbatim strings)をサポートしています。逐語的文字列リテラルは、3連ダブルクオテーションで囲います("""...""")。
string verbatim = """Verbatim strings don't evaluate escape sequences
like \n, \t, ... and may span multiple lines. The line breaks are part
of the string. You can use quotation marks (") and backslashes (\)
inside a verbatim string without escaping them."""

Vala言語は文字列テンプレートをサポートしています。@"..."で囲われた文字列は、$記号を接頭辞にした式をその内容に含むことができます。
string name = "John";
stdout.printf (@"Welcome, $name!");
stdout.printf (@"3 + 2 = $(3 + 2)");

配列

動的な成長

Vala言語では、配列に対して+=演算子を用いて、動的に要素を追加していくことができます。配列は2のべき乗のサイズで(動的に)メモリー上に再配置されます。
int[] squares = {};
for (int i = 0; i < 100; i++) {
    squares += i * i;
}

境界はチェックしない

Vala言語では、いかなる場合にも、実行環境により配列の境界がチェックされることはありません。
int[] a = new int[10];
a[20] = 1;  // 危険なコード!
(Valaの将来のバージョンでは、任意の境界チェック機能を実装することが検討されています。)

多次元の配列

Javaの場合: ジャグ配列を使用できます。([][]。配列の配列です。)
int[][] matrix = new int[3][];
for (int[] row : matrix) {
    row = new int[4];
}

Valaの場合: 長方形配列を使用できます。(rectangular multi-dimensional arrays。 [,]、 [,,]。Javaにおける多次元配列は配列オブジェクトに対する参照を要素とする配列ですが、Valaにおけるそれは多次元配列そのものが1つの連続したメモリーブロックに配置されます。)Valaでも、ジャグ配列のサポートが予定されています。
int[,] matrix = new int[3,4];

型推論

Vala言語では、ローカル変数に関して、型推論(暗黙型決定)と呼ばれるメカニズムが適用されます。このメカニズムの下では、──変数の初期化の際の式からコンパイラが型を推論できる場合──ローカル変数は型名ではなくvarキーワードによって宣言できます。これにより、不要な冗長性(意訳:ソースコードの可読性に対してメリットにならない冗長性)が取り除かれ、ジェネリック型の使用が簡単になります。例えば以下のように──
var obj = new Object ();
var map = new HashMap<string, int> ();
var str = "hello, world";
var arr = new int[10];

これに対して型推論メカニズムがないと以下のようになります──
Object obj = new Object ();
HashMap<string, int> map = new HashMap<string, int> ();
string str = "hello, world";
int[] arr = new int[10];

もちろん、すべての変数は静的型システムの管理下にあります(Still, everything is statically typed。意訳:動的型システムとはちがいます)。

foreach文

Javaの場合: for (int i : numbers) { }

Valaの場合: foreach (int i in numbers) { }

******************************

JavaプログラマーからみたVala (3)につづく──

JavaプログラマーからみたVala (1) ソースコード

最近なにかの拍子にVala言語に興味を持ってしまいました。Web上のドキュメントは限られているものの、Java言語との比較など平易なドキュメントもありましたので、学習をかねて稚拙な翻訳を載せていこうと思います。

原典は、“Vala for Java Programmers”(2011年3月13日取得)です。

******************************

JavaプログラマーからみたVala (1)

ソースファイル

Javaの場合: *.java

Valaの場合: *.vala

コンパイル

Javaの場合: JVMバイトコード(.classファイル)にコンパイルされます。
$ javac SourceFile1.java SourceFile2.java 
Valaの場合: C言語ソースコードに翻訳されたのち、ネイティブコードにコンパイルされます。
$ valac source1.vala source2.vala -o program 
Vala言語における標準オブジェクトシステムはGOjectであり、コンパイルされたValaライブラリは、有効なC言語ライブラリとなります。

ライブラリの使用

Javaの場合: .jarファイルを指定します。
$ javac -classpath foo-1.0.jar;bar-3.0.jar SourceFile.java 
Valaの場合: パッケージを指定します(.vapiファイルを介してCライブラリにアクセスします)
$ valac --pkg foo-1.0 --pkg bar-3.0 source.vala

Javaの場合:
  • クラス、インターフェース、列挙型: キャメルケース(パスカルケース)。
  • メソッド、ローカル変数、フィールド: ローワーキャメルケース。
  • 定数、列挙型インスタンス(enum values): アッパーケース(アンダーバーで結合)。
Valaの場合:
  • クラス、インターフェース、構造体、列挙型、デリゲート型、名前空間: キャメルケース(パスカルケース)。
  • メソッド、ローカル変数、フィールド、プロパティ、シグナル: ローワーケース(アンダーバーで結合)。
  • 定数、列挙型インスタンス: アッパーケース(アンダーバーで結合)。
名前にASCII文字以外の文字を使用することはできません。@を接頭辞として添えることで、名前にVala言語キーワード(予約語)を使用できます。この場合、@文字はそれを添えられた名前の一部としては認識されません。

ソースコードの組織化

ソースコード・ファイルについて

Javaの場合: 1つのファイルにつき、トップレベルのクラス(toplevel class。内部クラスでなく、パブリックなもの)は1つだけです。ファイル名はクラス名と一致します。

Valaの場合: 1つのファイルには複数のクラスを記述できます。ファイル名はクラス名と一致している必要はありません。

ヒエラルキーについて

Javaの場合: パッケージ概念があります。パッケージはディレクトリ構造によりあらわされます。またドメイン名を反転させた書式で構造化されます。
import javax.swing.*;

package org.foo.bar;

// ...
Valaの場合: 名前空間(namespaces)があります。ディレクトリ構造とは関係ありません。反転ドメイン名書式もとりません。
using Gtk;

namespace Foo.Bar {
    // ...
}
Valaの名前空間内には、所属クラスのないメソッドも存在します。これらは暗黙の静的メンバー(implicitly static)です。

デフォルトで読み込まれる名前空間について

Javaの場合: java.langパッケージ配下のクラスがデフォルトで読み込まれています。

Valaの場合: Glib名前空間がデフォルトで読み込まれています。

エントリーポイント

Javaの場合: public static void main(String[] args)

Valaの場合:  static int main (string[] args)

mainメソッドは、クラス外部で定義されても、privateアクセス修飾子が添えられていても、あるいは終了コード(exit code)としてintを返してもよいのです。その上argsはオプションです。

******************************

JavaプログラマーからみたVala (2)につづく──