Dvorakを始めてみるテスト
QWERTYに不満があるわけではないが、気分で。
Macなら、ことえりの環境設定の“英字入力時のキーボード配列”を“Dvorak - Qwerty ⌘”にする。これだけ。
しかし、なぜかFirefoxでキーボードショートカットが効かなくなる。TextEditやFinderでは効くのに。
[追記] Firefoxだけじゃなかった。Mailやターミナルもだ、
JavaScriptでブロックスコープを実現する最速の方法
GreaseMonkeyのスクリプトを書いていたら、入れ子にしたfor文の内側と外側で同じ変数名を使ってしまい、無限ループになってFirefoxが固まった。JavaScriptにブロックスコープがあればこんなことは起こらなかったので、この仕様を決めた奴は氏ぬ全世界に謝罪するべきだと思う。
JavaScriptにはブロックスコープが無いのはよく知られた話だ。 以下のコードはコンソールに「0」を書き出す。
var x = 123;
{
var x = 0;
}
console.log(x); // 0を出力
この問題に対する対処法もよく知られている。
var x = 123;
(function(){
var x = 0;
})();
console.log(x); // 123を出力
さて、今日何となく「JavaScript ブロックスコープ」でググると、別の対処法を知った。
- JavaScript でブロックスコープを実現する: Days on the Moon
with文を使うというもの - [ThinkIT] 第5回:グローバル変数の制御と更新履歴ファイル (1/2)
(via プログラマのためのJavaScript (12):不思議な宣言と奇妙なスコープ - 檜山正幸のキマイラ飼育記のコメント)
(function(){})()の代わりにnew function(){}とするもの
いくつかの対処法があるのは分かったが、実際、この中のどれが一番速いのだろうか。
new function(){}はfunction(){}.call(new Object)とほぼ同じこと(返すものが違う)なのでnew Objectの分遅そうだ。
コードを書いて検証してみた。 まとめ:
- Safariすげー
- letがあればそれが一番速い
- letがなければ (function(){})() が一番速い
- new function(){} はやっぱり遅い
- with(){} はその中間
みんな (function(){})() を使おう←もう使ってるよね- だれかletを(function(){})()に直すトランスレータを書いてくれ
以下、検証に使ったコードとその実行結果。
Objective-CのProtocolについて
Objective-Cのプロトコルはどう実装されているのか。
#include <stdio.h>
#include <objc/runtime.h>
#include <objc/Protocol.h>
@protocol SomeProtocol
- someMethod;
@end
int main() {
Protocol *p = @protocol(SomeProtocol);
printf("SomeProtocol: %p %s\n", p, protocol_getName(p));
}
@protocol(protocol_name)で、プロトコルの実体(Protocol *)を取得することができる。このコードをコンパイル、実行すると以下のようになる。
$ gcc test1.m -lobjc $ ./a.out SomeProtocol: 0x300c SomeProtocol
次に、@protocol(protocol_name)の代わりに、ランタイム関数であるobjc_getProtocol()を使ってみる。
#include <stdio.h>
#include <objc/runtime.h>
#include <objc/Protocol.h>
@protocol SomeProtocol
- someMethod;
@end
int main() {
Protocol *p = objc_getProtocol("SomeProtocol");
printf("SomeProtocol: %p %s\n", p, protocol_getName(p));
}
同じようにコンパイル、実行する。
$ gcc test2.m -lobjc $ ./a.out SomeProtocol: 0x0 nil
今度はnilが返ってきたようだ。このプロトコル(SomeProtocol)はどこでも使用されておらず、このプロトコルの実体が作られなかったようだ。
今度は、SomeProtocolに適合したクラスを宣言してみる。
#include <objc/Protocol.h>
#include <objc/runtime.h>
#include <stdio.h>
@protocol SomeProtocol
- someMethod;
@end
@interface SomeClass <SomeProtocol>
- someMethod;
@end
int main() {
Protocol *p = objc_getProtocol("SomeProtocol");
printf("SomeProtocol: %p %s\n", p, protocol_getName(p));
}
$ gcc test3.m -lobjc $ ./a.out SomeProtocol: 0x0 nil
今度もnilが返ってきた。宣言するだけでは不足なようだ。次はクラスの実装も書く。
#include <stdio.h>
#include <objc/runtime.h>
#include <objc/Protocol.h>
@protocol SomeProtocol
- someMethod;
@end
@interface SomeClass <SomeProtocol>
- someMethod;
@end
@implementation SomeClass
- someMethod { return nil; }
@end
int main() {
Protocol *p = objc_getProtocol("SomeProtocol");
printf("SomeProtocol: %p %s\n", p, protocol_getName(p));
}
$ gcc test4.m -lobjc $ ./a.out SomeProtocol: 0x30a4 SomeProtocol
取得できた。Class型のオブジェクトは、そのクラスが適合するプロトコルのリストを持つ(class_copyProtocolListで実行時に取得できる)ので、SomeProtocolの実体が作られたのだろう。
まとめ。Protocolの実体が作られる条件:
- そのプロトコルに適合するクラス(カテゴリも?)の@implementationが書かれた
- @protocol()で参照された
従って、どこからも参照されていないプロトコルを実行時にobjc_getProtocolで取得することはできない。
ちなみに、Protocolの実体はファイルごとに作られる。同じSomeProtocolであっても、あっちのファイル由来のものとこっちのファイル由来のものではアドレスが違う。protocol_isEqualで比較しよう。
lobjcをx86_64で動かす
libffiのビルド:
$ CC="gcc -arch x86_64" CXX="g++ -arch x86_64" ./configure $ make
luaのビルド:
$ make CC="gcc -arch x86_64" -j2 macosx $ sudo install -p -m 0755 lua /usr/local/bin/lua-x86_64
あとはx86_64用のlibffiをうまくリンクしてやればいい。
一見、何事も無く動くようだが、終了時にクラッシュする。
Program received signal EXC_BAD_ACCESS, Could not access memory. Reason: KERN_INVALID_ADDRESS at address: 0x0000000000000030 0x00007fff82ffd99a in _unload_image () (gdb) bt #0 0x00007fff82ffd99a in _unload_image () #1 0x00007fff82ff4af8 in unmap_image () #2 0x00007fff5fc02b67 in __dyld__ZN4dyld11removeImageEP11ImageLoader () #3 0x00007fff5fc02d6f in __dyld__ZN4dyld20garbageCollectImagesEv () #4 0x00007fff5fc0ac56 in __dyld_dlclose () #5 0x00007fff813e2755 in dlclose () #6 0x000000010001d05a in gctm (L=<value temporarily unavailable, due to optimizations>) at loadlib.c:64 #7 0x0000000100007e09 in luaD_precall (L=0x1000cd0e0, func=0x1000c8c8f, nresults=1885445184) at ldo.c:319 #8 0x00000001000081ae in luaD_call (L=0x1000c8c8f, func=0x0, nResults=839904) at ldo.c:376 #9 0x0000000100009d9b in GCTM (L=0x7fff70619c40) at lgc.c:467 #10 0x0000000100009df8 in luaC_callGCTM (L=0x1000c8c8f) at lgc.c:479 #11 0x00000001000076f7 in luaD_rawrunprotected (L=0x100803c00, f=0x10000f720 <callallgcTM>, ud=0x0) at ldo.c:116 #12 0x000000010000f7a0 in lua_close (L=<value temporarily unavailable, due to optimizations>) at lstate.c:209 #13 0x0000000100001ad4 in main (argc=<value temporarily unavailable, due to optimizations>, argv=0x0) at lua.c:389
_unload_imageでググると、VLCのMLが引っかかった。同様の症状のようだ。Leopardでの64ビットビルドでの既知の問題で、将来のリリースで修正されるだろうということらしい。Snow Leopardにすれば解決なのだろうか。ちなみにArch Linux x86_64+GNUstepでは落ちない。
PPCもRosetta上で試してみたが、何事も無く動作する。Rosettaだからかな。実機は持ってないので分からん。libffiのビルドは↓
CC="gcc -arch ppc" CXX="g++ -arch ppc" ./configure --host=powerpc-apple-darwin9 make
VirtualBoxにArch Linux (x86_64)を入れる
Official Arch Linux Install Guideが必見。
まずダウンロード。archlinux-2009.08-core-x86_64.isoをダウンロードした。sha1sumもチェック。FTPのやつだと最初から最新版が入るのでそっちの方がいいかもしれない。
VirtualBoxで新規VMを作る。Linux / Arch Linux (64 bit)にした。設定のNetworkで、Adapter 2のHost-only Adapterにする。ダウンロードしたばかりのCDイメージをマウント。
起動。Boot Arch Linux Live CDを選択。rootとしてログオン。
# km
でキーボードを指定。i386/qwerty/jp106.map.gzが良さそうだ。Console Fontはよくわからんのでスキップ。
# /arch/setup
インストール開始。Alt+←→とかAlt+F*でコンソールを切り替えられる。
