2011年3月13日日曜日

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)につづく──

2011年1月9日日曜日

ブクログで探しちゃうブックマークレット

ブクログで配布されていた「ブクログに追加」ブックマークレットが、岩波書店のページとかその他でぜんぜん役に立たないことにイラっときてつくりました。

「ISBN : ~」とか「IEBN-10 : ~」とか「IEBN-13 : ~」とかの記述をページ内で探して、その情報をもとにブクログで書籍検索を実施します。そんだけです。

以下のリンクをブックマークバーなどにドラッグすれば、使えるようになるはずです。

ISBNをもとにブクログで探す

ISBNをもとにブクログで探す(ASIN・EAN対応)

※テスト用ISBN-13: 978-4791762460

AppWidgetの作り方

AppWidget(以下、ウィジェット)は、Androidアプリに組み込まれる形で配布され、ユーザーが自身の端末のホームスクリーン上に自由に配置できる小さなアプリです。

ウィジェットの定義ファイルのなかで、更新間隔を指定しておくことで、一定の時間間隔で表示をアップデートしていくことが可能です。表示の更新のタイミングが限られているため、「常駐アプリ」とはかならずしも分類できませんが、画面=Activityを持つAndroidアプリ本体の、高機能なランチャー程度には活用できます。

※より正確に言えば、ウィジェットとは、ユーザーがウィジェットを作成したときや、あらかじめ定められた時間間隔が経過したときに、Androidプラットフォームのシステム側からメッセージを受け取るブロードキャスト・レシーバー(AppWidgetプロバイダー)により初期化・更新されるView、です。

Androidアプリにウィジェットを組み込むには、以下のファイルが必要になります。

①AppWidgetProviderInfo (XML)
ウィジェットのメタデータを記述するもので、ウィジェットの表示を構成するためのレイアウト・リソース、表示更新の頻度、AppWidgetプロバイダー(後述)のクラス名を、XMLで記述します。

②AppWidgetProvider (Class)
ウィジェットの初期化などで呼び出される処理を実装するAppWidgetプロバイダー(ブロードキャスト・レシーバーの一種)の実装クラスです。

③レイアウト (XML)
ウィジェットの表示に使用されるレイアウト・リソースです。サイズの指定方法が独特?です。

④AndroidManifest(XML)
言わずと知れたAndroidアプリのメタデータやコンポーネントについての記述をするためのXMLです。AppWidgetProviderがブロードキャスト・レシーバーの一種であることから、記述の追加が必要になります。

以下では、Android Developpersのリファレンスのコードを参考に説明を行います。

1. AndroidManifestへの登録

Intentフィルターの部分と、AppWidgetプロバイダーのメタデータについて記述したXMLの在所を示す部分が重要です。
<receiver android:name="ExampleAppWidgetProvider">
    <intent-filter>
        <action android:name="android.appwidget.action.APPWIDGET_UPDATE" />
    </intent-filter>
    <meta-data android:name="android.appwidget.provider"
               android:resource="@xml/example_appwidget_info" />
</receiver>

2. AppWidgetプロバイダーのメタデータの記述

AndroidManifestで示した場所に、プロバイダーのメタデータを記述したXMLを配置します。

ウィジェットのサイズ指定の単位となるのは、Android端末のホームスクリーンをタテヨコ4分割した「セル」の幅/高さであり、Android Developpersでは、「(セル数 * 74) - 2」という数式が紹介されています。
この数値を、dp(画面密度非依存ピクセル)でminWidthとminHeight属性に指定することで、ウィジェットのサイズを指定します。ウィジェットは、ユーザーによりサイズ変更可能です。

updatePeriodMillis属性では、ウィジェット の更新間隔を指定します。単位はミリ秒となります。
更新は最短で30分以上の間隔を置いて実行されます。この属性に0を指定すると、更新は行われなくなり、後述のAppWidgetプロバイダーのonUpdateメソッドは、ウィジェット作成時にしか呼ばれなくなります。

configure属性は、ウィジェットにセッティング用画面がある場合のものです。ウィジェットが作成された際にここで指定したActivityが実行され、ウィジェットのプロパティを初期化すること出来るようです。(詳しくはこちらを参照。
<appwidget-provider xmlns:android="http://schemas.android.com/apk/res/android"
    android:minWidth="294dp"
    android:minHeight="72dp"
    android:updatePeriodMillis="86400000"
    android:initialLayout="@layout/example_appwidget"
    android:configure="com.example.android.ExampleAppWidgetConfigure">
</appwidget-provider>

3. ウィジェットのレイアウトを作成

ウィジェットのレイアウトで使用できるViewGroupとViewには制限があるようです。
ViewGroupについては、FrameLayout、LinearLayout、RelativeLayout。
Viewについては、AnalogClock、Button、Chronometer、ImageButton、ImageView、ProgressBar、TextViewです。
ButtonやImageViewなどのほかに、AnalogClockなどが挙げられているのがおもしろいところです。

4. AppWidgetプロバイダーを実装

AppWidgetProviderクラスの中で、一番重要なのは、onUpdateメソッドでしょう。
このメソッドは、プロバイダーのメタデータの記述(XML)の中で指定した更新タイミングに呼び出されます。

また、より重要なこととして、 ユーザーによりウィジェットが画面に追加された際にも、このメソッドが呼び出されます。したがって、このメソッドの中でウィジェットの表示の初期化や、必要なサービスの起動などを実行することになります。

しかもです。このメソッドの第3引数は、AppWidgetインスタンスのID配列です。この点について、Android Developpersの説明では、大意以下のように述べています。
ユーザーは同じAppWidgetのインスタンスをいくつも作成することができる。例えば、あるAppWidgetが、2時間ごとに更新されるよう指定されていたとする。まず1つめのAppWidgetインスタンスがホームスクリーン上に作成され、その1時間後、もう1つのAppWidgetインスタンスが作成される。1つめのAppWidgetがスクリーン上に追加されてから2時間後、onUpdateメソッドが呼ばれる。しかしその1時間後(2つ目のインスタンスが作成されてから2時間後)にonUpdateが呼ばれることはない。更新のスケジューリングは、あくまでも1つめのAppWidgetインスタンスの生成を基準に行われる。
つまり、ここでupdatePeriodMillis属性があくまでもプロバイダーの属性であり、ウィジェットの属性ではなかったことがここで思い出されるわけですが、いずれにしてもこのメソッドはホームスクリーン上のすべてのウィジェットについて、その更新/初期化を一時に実施するものであるということです。

したがって、ウィジェットのボタンをクリックしたときに、アプリケーション本体となるActivityを起動する、といったことをする場合、以下のようなコードを記述すればよいことになります。
public class ExampleAppWidgetProvider extends AppWidgetProvider {

    public void onUpdate(Context context,
        AppWidgetManager appWidgetManager, int[] appWidgetIds) {
       
        final int N = appWidgetIds.length;

        // このプロバイダーに所属するAppWidgetのそれぞれについて処理を行う
        for (int i=0; i
            int appWidgetId = appWidgetIds[i];

            // ExampleActivityを起動するIntentを生成
            Intent intent = new Intent(context, ExampleActivity.class);
           
            // それをPendingIntentに変換する
            PendingIntent pendingIntent = PendingIntent.getActivity(context, 0, intent, 0);

            // AppWidgetのレイアウト・リソースを取得
            RemoteViews views = new RemoteViews(context.getPackageName(),
                R.layout.appwidget_provider_layout);
           
            // 第1引数にClickリスナーを設定したいViewのID、
            // 第2引数にClickされた際に発行されるPendingIntentを指定
            views.setOnClickPendingIntent(R.id.button, pendingIntent);

            // IDで指定したAppWidgetの表示を、先ほど取得し、リスナーをセットした
            // RemoteViewsで更新する/初期化するようAppWidgetManagerに指示
            appWidgetManager.updateAppWidget(appWidgetId, views);
        }
    }
}
onUpdateメソッドに対応するものとしては、onDeletedがあります。
onDeleted(Context context, int[] appWidgetIds)

その他のメソッドとしては、onEnabled、onDisabled、onReceiveがあります。これらがonUpdateメソッド同様、あくまでもプロバイダーの生成~破棄までのライフサイクルに関わってくるものであり、AppWidgetの個別のインスタンスに関連するものではない、ということに注意してください。

これらのメソッドの解説は、Android DeveloppersのAPIリファレンスにあります。

2010年11月30日火曜日

Zen Codingを導入してみた

Amazonで、『HTML+CSSコーディングが10倍速くなるZen Coding』なる書物を見かけたので、ちっとばかり調べてみた。
ばりばり使うことがあるかというとかなり疑問だったけど、便利そうなので手もとのEmEditorやAptanaに導入してみた。


1. EmEditor


EmEditor向けにはマクロとして提供されている。
http://www.emeditor.com/modules/mydownloads/singlefile.php?cid=18&lid=281


上記ページで、FDマークの右の「Zen Coding macros and snippets」という部分をクリックすると、マクロのファイルがダウンロード可能。


同ページの手順書によると、

  1. 「マイドキュメント」フォルダに「My Macros」(MyとMacrosの間は半角スペース)というフォルダを探す。
  2. ない場合は、EmEditorでマクロを一度も使用したことがないことが原因と思われる。ない場合は、自分で作成してしまうこと(EmEditorで何でもいいのでマクロを記録、名前をつけて保存しようとすると自動で作成される)。
  3. My Macrosフォルダに、zen_emeditor.jseeをコピーする。
  4. もしスニペット・カスタムバーが表示されていなければ、メニューから<ツール→プラグイン→スニペット>をクリックし、表示する。
  5. スニペット・カスタムバーの上で右クリック<インポート/エクスポート→ルートにインポート>をクリック。
  6. zen-coding-en.eesnip(もしくは~ja.eesnip)を選択。
  7. もしスニペット・カスタムバーが表示されていない状態でもZen Codingマクロを使用したい場合は、<メニューからツール→プラグイン→プラグインの設定>をクリック。
  8. プラグイン一覧からスニペットを選択し、プロパティをクリック。
  9. 「バックグラウンドでも実行する」にチェックを入れ、OK。


(以上、意訳・補足あり)

これでZen Codingマクロが有効化し、「div#name」とか何とか入力してF12を押すと、コードの展開が可能になる。編集設定がCSSの場合はCSS向けのZen Codingも可能。
また、ほかにもコマンドがあるらしいけど、そこら辺は上記ページを確認のこと。



2. Aptana(Eclipse)


Aptana(Eclipse)向けには、プラグインの形式でリリースが行われはじめている。
以前、Zen Codingについて調べたときにはまだなかったように思うので、隔世の感?


プラグインは、以下のページで配布されている。
https://github.com/sergeche/eclipse-zencoding


インストール手順にしたがうと、

  1. メニューから<Help→Install New Software...>と進む。
  2. アップデートサイトのロケーションとして、http://zen-coding.ru/eclipse/updates/を追加する。
  3. 利用可能なプラグインのリスト中、「Zen Coding for Eclipse」(Uncategorized...→Zen Coding for Eclipse)にチェックを入れ、Nextボタンをクリック。インストール手続きを進める。
  4. インストール後、(Aptana/Eclipseに促されるまま)再起動する。

(以上、意訳・補足あり)


これだけで、Aptanaのテキストエディター中でZen Codingが使用可能になる。
例によって「div#name」とか何とか入力してTabキーを押すと直前のコードが展開されて、HTMLになる。
コマンドのショートカットのカスタマイズもできるっぽい。詳細は上記ページを確認のこと。