[JavaScript][ActionScript] ブロック({ … }) ではスコープの限定ができない

一時変数のスコープを絞るのに { … } をよく使うが、ECMAScript (ActionScript/JavaScript 共通) だと物理的には意味をなさなくなる。例えば、次の文はエラーにはならない:

{var t=”NG”;} alert(t);

ブロックがスコープを持つなら、t は alert() を呼ぶ時点では存在しないためエラーになるべきだが、実際は NG と表示されてしまう。(Firefox 1.0, IE6, Flash MX 2004 で確認)
 
これは制御構文でも同じで、例えば、

for(var i; i < 10; i++){ var n = i; }

は、for 文の終了後に

i = 10; n = 9;

が入ったままになる。スコープを切りたい場合は、その部分だけ関数を使う等するしかなさそう。個人的に、リファクタリングの準備のために頻繁にスコープを切るのでこれは不便だなぁ..
ECMAScript では関数スコープであることを宣言するときのみ var 宣言は意味を成しているよう。
 

簡易タイマー

例えば 1 分後にアラートを鳴らすには次のようにすればよい。
– Windows なら sleep というコマンドを使えるようにしてコマンドプロンプトで

sleep 60 && echo <Ctrl-G>

  • UNIX 系(bash, sh)なら

sleep 60 && printf “\a”

 
追記:
(2006-05-10) sleep が Windows 標準で存在しないことに気づき訂正.

static ファクトリメソッドの落とし穴

Effective Java より、static ファクトリメソッドで Foo.getInstance() みたくするのがいい、とあったが、何も考えずやってると継承周りで混乱を招く。

class Parent {
public static Parent getInstance(){ return new Parent(); }
}
class Child extends Parent {}

このとき、Child.getInstance(); は Child インスタンスではなく(スーパークラスで定義されている getInstance() を使うため) Parent インスタンスを生成してしまう。
 
Effective Java の例にきっちり書かれているとおり、

class Parent {
private Parent(){ }
public static Parent getInstance(){ return new Parent(); }
}

とか class final Parent とかして継承を禁止するのが妥当な解決方法(拡張にはコンポジションを使う)。
それが嫌なら static ファクトリメソッドの公開をやめて普通にコンストラクタを公開する。
 
あるいは、継承を行うクライアントが、確実に public static Child getInstance() を定義してくれることを信じるか。

DAO パターン

Core J2EE Patterns – Data Access Object
データソースや製品依存の処理を隠蔽して、例えばテーブル単位でアクセス用の API を作り、insert, delete, find, update など必要な処理はインターフェイスにして、それを実装する。複数の形式に対応するにはこの DAO インターフェイスを実装すればいいだけなのがメリット。
 
DAO だけでなく、シリアル化可能な値オブジェクトの、 Transfer Object も用意しておけば、DAO とクライアントの通信では Transfer Object がレコードの代用になるため抽象度が増す。
 
説明では、複数のソースと複数のテーブルが存在するため、利便性のために Abstract Factory Method Pattern でソースタイプ毎に階層を作り、メソッドでテーブルを作れるようにしている。
 
難点は、簡易的な実装だと条件をしぼりきれずオーバーヘッドがかかりそうなことや、どうしても JDBC とかを直接さわるより開発コストがかかること。単純な実装では select で全てとって Collection にしてしまえば楽だけど、たとえば数万行のテーブルが毎回格納されるとなると大変。単純な実装とは別にシステム特化のメソッドを実装すればいいかも。

リモートから任意のコマンドを実行する

$ ssh user@host command…
– CUI でどうやるんだっけなと思って ssh(1) を見たらそのままでした。コマンドは引数をとれるが、interactive な挙動も可能。って shell の代用で動かすのだからできて当然か。公開鍵認証とかでパスワードレスにすると遠隔バッチ処理に便利。

JDK1.5 の javadoc で package.html を指定すると複数のパッケージコメントのソースと言われて警告になる

– 正しく出力されるので害はないものの、毎回警告がでていたので調べてみた。警告内容は次の通り。

javadoc: 警告 – パッケージ “x.y.z” に複数のパッケージコメントのソースが検出されました。

英語だと以下。

Multiple sources of package comments found for package “x.y.z”

Java Forums <http://forum.java.sun.com/thread.jspa?threadID=599721&tstart=0> にずばり回答が。

Yep. The Doclet interface of the Doclet API specifies a method
 
void setRawCommentText(String text)
 
prior to 1.5 this method did exactly what its name implies. With 1.5 the implementation was changed to generate a warning and do nothing if it was attempted to set the comment text multiple times.
What happens is this:
Javadoc sees the package.html files in the sources, creates an appropriate Doc (PackageDoc) instance and sets the comment text. Then for some reason Javadoc encounters package.html files for already existing Doc instances and tries to set the comment text a second (third, fourth, …) time.
So, all you need to do is to ensure that Javadoc parses the package.html file for a given package only once, i.e. ensure that only sourcepath points to the package.html files but not classpath.

1.5 から package.html が複数見付かった時に上書きしつつ、警告を出すようになったとのこと。
ここで例にあるとおり、 javadoc のオプションで、 sourcepath でパッケージのある場所を示しつつ、なおかつ classpath でも示していたのが原因だった。Eclipse ではリリースディレクトリにも package.html をコピーしてくれていて、結局それが source のものと重複してしまった。
 
そもそも不要な、classpath からリリースディレクトリ(bin)の指定を外して解決。

javadoc でパッケージの説明をつける

– package.html というファイルを、指定したいパッケージのソースディレクトリに入れれば自動で読みとってくれる。<body> ~ </body> の最初の文を、概要のほうのパッケージの一行説明に使い、それ以外はパッケージの説明ページに使われる。
<http://java.sun.com/j2se/1.5.0/ja/docs/ja/tooldocs/windows/javadoc.html#packagecomment>
– javadoc – Java AAPI ドキュメントジェネレータ: パッケージコメントファイル
JDK1.2 から利用可能。

emacs で diff

<http://www.math.s.chiba-u.ac.jp/~matsu/emacs/emacs20/ediff.html>
– Emacs 活用法: Ediff の使い方
M-x ediff-merge として、二つのファイルを選択する事で可能。そのままマージができるので便利そう。
M-x ediff-files で主に片方のファイルにするとか。
終わったら q で閉じて ediff-merge バッファをファイルとして保存すればいい。やめたくなったら C-] 。
 
Info -> Emacs -> Emerge の項目にその他コマンド等の説明があるらしい。

FreeBSD で java/linux-sun-jdk14 を使っていると "Can’t detect initial thread stack location" が出る原因

– make で表示されるインフォメーション通りにやっていないと jar で出たりする。

FreeBSD JDK, in ports/java/jdk14.
 
This Java VM will attempt to obtain some system information by
accessing files in linux’s procfs. You must install the Linux
emulation procfs filesystem for this to work correctly. The JVM
will exhibit various problems otherwise. This can be accomplished
by adding the following line to your /etc/fstab file:
 
linprocfs /compat/linux/proc linprocfs rw 0 0
 
and then, as root, executing the commands:
 
kldload linprocfs
mount /compat/linux/proc

説明通り、 /etc/fstab に

linprocfs /compat/linux/proc linprocfs rw 0 0

を追加して
$ mount /compat/linux/proc
を実行すればよい。