jQueryでclickできない

jQueryで困ったのでメモ。
一応、バージョンは1.8.2。ブラウザはFirefox 20.0.1。

jQueryのclick()でa要素のクリックイベントを発行して、自動的にリンク先に飛ぼうと思ったのですが、うまくいきませんでした。
つまり、

$('#linkToSomewhere').click();

とかやってみたわけですが、リンク先に飛べないのです。

こういう場合、素直にDOM要素のclick()を呼ぶしかないようで、

$('#linkToSomewhere')[0].click();

とやれば万事解決しました。

jQueryのイベント系の関数は、イベント発行だけして、DOMの本来の動作は起こさないのかなと思いましたが、それも違う様子。
というのも、a要素に対して、addEventListener('click', function)で追加されたイベントも発行されないみたいです。

じゃあ、jQueryを使って追加されたイベントしか呼ばないのか、というとそれも違うみたい。
div要素に対して、addEventListener('click', function)で追加されたイベントは、jQueryのclick()できちんと実行されました。
a要素とdiv要素でなにが違うんでしょうね…?

それから、a要素でも、onclick属性に指定されたイベントはきちんと実行されました。(もちろんdiv要素でも。)
もはや、わけがわからない…。

jQueryのclick()で呼ばれるイベントをまとめるとこんな感じ。

要素jQueryのclick(fn)addEventListeneronclick
a要素×
div要素

理解するには、jQueryのソースを読んでみるしかないのかなぁ…。
それともブラウザ側の問題とか?

eclipseで総称型の警告を無視する方法

eclipseJavaのコードを書いていると、特に他人のコードやライブラリを使ってるとたまにあらわれる警告。

型の安全性: メソッド add(Object) は raw 型 List に属しています。総称型 List への参照はパラメーター化される必要があります

例えば、

hoge.getValueList().add(someValue);

なんてコードを書くと出てきたりします。
原因は、hoge.getValueList()の戻り値がList型などのraw型の総称型になっていること。
raw型というのは、総称型として定義されている型(例えば、ListMap)に対して型引数を指定しなかった時の型。
総称型が導入されて以降は、List<String>などと使うべきなのに、Listと型引数を指定しないで使うとこんな警告が出るわけです。

キャストで回避する方法は存在しないようで、

((List<String>) hoge.getValueList()).add(someValue);

などとしてみても、

型の安全性: List から List への未検査キャスト

と言われてしまいます。

結局、警告を消すには「無視する」しかないようで、SuppressWarningsアノテーションを使います。
値をuncheckedとして、このアノテーションを指定すると、その指定された範囲では総称型に関するキャストが警告として現れません。(無視されるのはそういうキャストだけかな? 調べてないが…。)
ところが、アノテーションは文にはつけられないので、

@SuppressWarnings("unchecked")
hoge.getValueList().add(someValue);

などという書き方はできません

仕方がないので、メソッドやクラスにつけることになりますが、無駄に広範囲で無視するようにしてしまうと必要な警告まで見えなくなってしまいます。バグまで見過ごしかねないという、よくある(?)問題です。
そこで、SuppressWarningsアノテーションがローカル変数宣言にもつけられることを利用します。

@SuppressWarnings("unchecked")
List<String> list = hoge.getValueList();
list.add(someValue);

とすることで、警告回避の影響をここだけにとどめることができるので、個人的にお薦めです。

P.S.

どうしてアノテーションが文につけられないかを考えると、構文解析が難解になるからでしょうか。
文のアノテーションを許すと、例えば、

@interface Test {
    String value() default "";
}
…
    @Test("hoge") length();  //【A】
    @Test("hoge").length();  //【B】

と書けることになりますね。
【A】は、length();に対して@Test("hoge")がついています。【B】は、("hoge").length();に対して@Testがついていることになります。
)”の次の“.”まで読んで初めて("hoge")アノテーションの一部なのか、文の一部なのかわかるというのは少々複雑ですね。
というわけで、アノテーションは、次に“(”が現れうる場所にはつけられないのでしょう。
そうすることで、@何々のあとに“(”が現れたとき、その“(”から対応する“)”までをアノテーションの一部だと決めて構わなくなりますから。

と、考えると納得がいくのですがいかがでしょう?
どっかに開発者のコメントとかありそうですけど。

Perlでファイル名変更

# .iniファイル以外で最近24時間以内に変更されたファイルの名前を変更する
my $dirname = 'C:/data';
my $dir;

chdir $dirname;
opendir $dir, '.' or die;
my @file = grep {!/(^\.|.+\.ini$)/} readdir $dir;
closedir $dir;

for (@file) {
    if ((stat)[9] > time-60*60*24) {
        rename $_, "del$_";
    }
}

MiniSat on Windows

Windows上でネイティブな(w/o Cygwin)MiniSatを構築しようとして、いろいろ困ったのでメモ。
MinGWを使えばいけると思ったのですが…。

1. makeできない

とりあえず、CとC++コンパイルできる状態にすればいいかなと思って、CとC++コンパイラだけインストールしたら、無理でした…。
MSYSというシェル環境(?)にそのあたりのユーティリティがいろいろ入っているようなので、mingw-getでいれました。

mingw-get install msys-base

私の場合は、makeだけいれれば大丈夫かと思って、msys-makeパッケージだけインストールしようとしましたが、sedがないだの、pwdがないだの言われて、無理でした…。
なので、msys-baseパッケージをすべていれてしまいましたが、今調べてみたらmsys-tinyという、最小限のユーティリティだけいれるパッケージがあるようですね。

mingw-get install msys-tiny msys-sed msys-make

とかで、いけるかもしれません。(未確認)

2. MinGWgccで、zlib.hを使ったプログラムがコンパイルできない

とりあえず、msys-zlibパッケージをいれればいけるかと思ったが、無理…。

MinGWディレクトリ以下をzlibで検索してみると、mingw32-zlib.xmlとmsys-zlib.xmlが見つかりました。
このxmlの構造はよくわかりませんが、とりあえずmingw32-zlib.xmlを読んでみると、mingw32-libzパッケージ配下にdevクラスというものを発見。
libzというエイリアスがついているので、これでインストールできました。

mingw-get install libz

しかし、なんでヘッダファイルのパッケージはlibzなんだ。紛らわしい。

3. メモリの使用制限とかができない

core/Main.ccの中で、getrlimit関数によってCPU使用時間の制限とかメモリ使用量の制限とかしているみたいですけど、そのせいでコンパイルが通りません。
とりあえず、オプションのようですし、コメントアウトして対処。

具体的には、

  • 85行目〜86行目あたりのcpu_limとmem_limの宣言
  • 99行目あたりの、SIGXCPUシグナルの受信設定
  • 101行目〜120行目あたりの、CPUとメモリに関する制限の設定 (if文×2)
  • 149行目あたりの、SIGXCPUシグナルの受信設定

コメントアウトしたらOKでした。

MinGWでもこの辺、別名で対応してたりしないのかな。

simp/Main.ccも同様。
具体的には、

  • 25行目あたりの、#include
  • 87行目〜88行目あたりのcpu_limとmem_limの宣言
  • 103行目あたりの、SIGXCPUシグナルの受信設定
  • 105行目〜124行目あたりの、CPUとメモリに関する制限の設定 (if文×2)
  • 152行目あたりの、SIGXCPUシグナルの受信設定

コメントアウト

4. Minisat::memUsedPeak()が定義されていないといわれる

utils/System.ccの中で、linux環境以外でmemUsedPeakが正しく定義されていないのが原因。
MinGWとか関係なく、defined(__linux__)な環境以外はコンパイル通らないんじゃないか、ってくらいソースがおかしいです。MinisatMiniSatって書いてあったり。
とりあえず、#elseのところに以下を追加定義して対応。95行目くらいかな。

double Minisat::memUsedPeak(void) { return memUsed(); }

utils/System.hにはMinisat::memUsedPeak()関数に関して、「非対応なら0を返す」って書いてあるので、仕様的にもこれでOKでしょう。

取得できたほうが嬉しいですけど。

5. makeがエラーを吐く

「致命的なエラー」とか「コンパイルを停止しました」とか出てくるのでビビりますが、(実際、直そうといろいろ画策しましたが…)makeが依存関係を完全には認識できないだけのようなので、特に問題はなさそうです。
というか、MSYSのmakeなんだからMSYS上で動かせ、って話なんでしょうね。

ここまでやってREADMEどおりに(但し、コマンドプロンプト用にちょっと変えてますが)

setenv MROOT=C:\Minisat
cd core
make rs
copy minisat_static.exe C:\MinGW\bin\minisat.exe

とかやればOK!

もちろん、MinGWの、.\bin.\msys\1.0\binにパスを通すことを忘れずに。

ここまで5時間……。余計なことをしてしまったぜ。(笑)
まぁ素直にCygwinを入れるか、Linux環境にしろってことですよね。

SPINのatomicの使い方

http://spinroot.com/spin/Man/atomic.htmlの和訳です。

名前

atomic - 不可分に実行されるべきコード片を定義する。

文法

atomic { sequence }

効果

意味論的モデル(semantics model)において、atomicシーケンス内では、その最後以外の文が実行されたときの副作用として、グローバルのシステム変数(global system variable)を実行中のプロセスの実体化番号に限定する。これにより、実行の排他的特権を保護する。

説明

もし、文の並びが括弧で囲われていてatomicキーワードが前置されていれば、この文の並びが他のプロセスとインターリーブされない1つの不可分な単位として実行されるべきことを表す。プロセスをインターリーブして実行しようとするとき、atomicシーケンスの最初の文が実行された瞬間から最後の文が完了するまで、他のどのプロセスも文を実行できない。シーケンスは任意のPromela文を含むことができるし、非決定的で構わない。

もしatomicシーケンス内の文がブロック状態になる場合には、アトミック性は失われ、他のプロセスは文を実行し始めることが許される。そのブロックした文が再び実行可能になったとき、そのatomicシーケンスはいつでも実行再開でき、即座に再開される必要はない。プロセスがそのatomicシーケンスの残りを実行再開する前に、まずそのプロセスはシステムの他のすべてのアクティブプロセスと競合してコントロールを得ねばならない。すなわち、まずそのプロセスは実行できるようにスケジューリングしてもらわなければならない。

もしatomicシーケンスが同期(rendezvous)送信の文を含んでいる場合、同期通信(rendezvous)のハンドシェイクが成功したときに送信者から受信者にコントロールが移る。非決定的プロセスインターリーブの通常のルールの下では、コントロールはしばらくしてから送信者に戻り、そしてatomicシーケンスの残りの実行を続けることが許可される。ただし、同期通信(rendezvous)のハンドシェイクがatomicシーケンスの内側で受信されるという特別な場合には、アトミック性も同期通信(rendezvous)のハンドシェイクを通じて渡されることになり、割り込まれない (他のプロセスがそのとき実行の排他的特権を持っている場合を除く)。

atomicシーケンスはPromela文が使えるところならどこでも使うことができる。atomicシーケンスの最初の文は、そのシーケンスの「ガード」と呼ばれ、シーケンスがいつ開始されるかを決定する。よい方法ではないが、goto文を使ってatomicシーケンスの中にジャンプすることもできるし、シーケンスの外にジャンプすることもできる。シーケンスの中にジャンプした後、そのプロセスがコントロールを得たとき、ジャンプした先の文が実行可能な場合には、アトミックな実行が始まる。シーケンスの外にジャンプした後、ジャンプ先もatomicシーケンスの中になければ、アトミック性は失われる。

例示

atomic {	/* swap the values of a and b */
	tmp = b;
	b = a;
	a = tmp
}

この例では、割り込まれずに文の並びが実行され、2つの変数a, bの値が入れ替わる。内部のすべての文が常に無条件に実行可能な文なので、この実行はブロックされない。

次の例は、非決定的なatomicシーケンスである。

atomic {
	if
	:: a = 1
	:: a = 2
	fi;
	if
	:: b = 1
	:: b = 2
	fi
}

この例では、他のプロセスから邪魔され得ない文によって、変数a, bにある単一の値が代入される。このatomicシーケンスの実行のされ方は4通りあり得る。

同期通信(rendezvous)演算を使ってコントロールを渡しあうことによって、2つ以上のプロセスを交互に実行できるので、グローバルでアトミックな実行の連鎖を作ることが可能である。

chan q = [0] of { bool };
active proctype X() { atomic { A; q!0; B } }
active proctype Y() { atomic { q?0 -> C } }

この例では、例えば、プロセスXの、Aというプログラムブロックから実行を始めることができる。同期通信(rendezvous)のハンドシェイクが実行されるとき、アトミック性はプロセスYに移り、Cというブロックが実行開始する。それが終わると、コントロールはXに戻り、そしてBというブロックがアトミックに実行される。

一連のプロセスを開始する際、それらすべてが初期化されるまでどのプロセスでも文が実行され始めないようにしたいとき、atomicシーケンスを使うとうまくいくことが多い。

atomic {
	run A(1,2);
	run B(2,3);
	run C(3,1)
}

注記

atomicシーケンスは検証の複雑さを軽減するために使うことができる。

もし無限ループが誤ってatomicシーケンスに含まれてしまった場合でも、検証器はそのサイクルを常に認識できるとは限らない。デフォルトの深さ優先探索モードでは、そのような無限サイクルがあると最終的には深さの上限を突破してしまい、ループを中断してしまう。だが、幅優先探索モードでは、この種の無限サイクルが検出できる。当然、無限サイクルがatomicシーケンスに現れると、そのatomicシーケンスは現実の実装ではどうやってもアトミックに実行できないので、それはエラーである。

Promelaのd_stepシーケンスは、atomicシーケンスより遥かに効率的に検証器によって実行されうるが、非決定性を許さない。

ログイン情報の削除

sambaサーバに、Windowsから複数のアカウントを使い分けてログインする方法のメモ。

sambaサーバに一度接続すると、「パスワードを記録する」チェックをつけなくても勝手にユーザ名とパスワードが記録されて、次回からは勝手にログインされてしまいます。
パスワードを訊かれないどころか、ユーザ名も訊かれないため、別アカウントに切り替えることができません。
再起動しても治らないのです。
うちは個人のPCなんですが、共有PCなんかでこうなると困りますね。セキュリティ的にも危ないですし。

で、Googleさんに訊いてみても、

  • smbクライアント(サービス)を再起動してみる
  • netコマンドでログイン資格を削除してみる
    具体的には
    net use \\ServerName /delete
    というコマンドを実行する

というのが出てきたのですが、どちらも自分の場合には当てはまりませんでした。

そんな中、見つけた対処法がこれ。
Windowsでキャッシュされたログオンを無効にする(暗号化ファイルシステムの運用に注意):Tech TIPS - @IT

どうやらWindowsドメインネットワークが落ちていても(オフラインでも)ログオンできるように資格情報をキャッシュしているようで、それが今回の問題の原因のようですね。
それを全くキャッシュしないようにするのが今回の対処方法。
上のサイトの記述の通り、「管理ツール」から設定を変更して対処できました。
自分はドメインネットワークなんて高度なものを使っていませんが、会社なんかで使っている人は、この方法で対処するのはよくないのでしょうね。記事の最後で注意書きしてありますね。

それから、もう1つ対処法を見つけました。
上の「資格情報」と同じかどうかわかりませんが、コントロールパネルのユーザアカウントのところにもそんな感じの設定項目があります。
XPだと、ユーザアカウントからどれかアカウントを選ぶと、左側の「関連した作業」のところに「ネットワークパスワードを管理する」っていうのがあって、そこから資格情報を操作できるみたいです。
Win7だと、コントロールパネルで「資格情報マネージャー」で検索すれば出てくるようです。
リストから選んで、特定の資格情報だけを削除できるようになっています。
ログインするたび毎回記録されるので、そのたびに消さなきゃならないですが。
あと、sambaにログインした直後ではここのリストにその資格情報が表示されませんでした。よくわかりませんけど、一度ログアウトした後じゃなきゃダメなのかな?
1つめの方法が使えない人はこちらで対処するしかないですね。

フィルタなんかでキャッシュするもの、しないものを設定できたら一番楽なのですけどね…。