Gauche の拡張ライブラリでクラスを定義する
Gauche の拡張ライブラリで、自分でクラスを定義する方法、というよりメモとしてのテンプレート。正しい手順か不明だけど、とりあえず動く。
安直だけど、"clos" という名前の拡張ライブラリを書くとして、Scheme で書くと次のような定義になるようにする。
(define-class <person> () ((name :init-value "Anonymous") (age :init-value 20)))
拡張ライブラリのヘッダファイル clos.h の宣言。
typedef struct ScmPersonRec { SCM_HEADER; ScmObj name; int age; } ScmPerson; SCM_CLASS_DECL(Scm_PersonClass); #define SCM_CLASS_PERSON (&Scm_PersonClass) #define SCM_PERSON(obj) ((ScmPerson*)obj) #define SCM_PERSON_P(obj) SCM_XTYPEP(obj, &Scm_PersonClass) // ScmObj Scm_MakePerson(void);
構造体を使ってクラスのスロットを用意。さらに、マクロ。命名規則は gauche.h で使われているものを参考にした。最後のコメントアウトされている Scm_MakePerson は、gosh 側で
次に clos.c。
static ScmObj person_allocate(ScmClass *klass, ScmObj initargs); SCM_DEFINE_BUILTIN_CLASS(Scm_PersonClass, NULL, NULL, NULL, person_allocate, NULL); static ScmObj person_allocate(ScmClass *klass, ScmObj initargs) { ScmPerson *p = SCM_NEW(ScmPerson); SCM_SET_CLASS(p, SCM_CLASS_PERSON); p->name = SCM_MAKE_STR("Anonymous"); p->age = 20; return SCM_OBJ(p); } static ScmObj person_name(ScmPerson *p) { return p->name; } static ScmObj person_age(ScmPerson *p) { return SCM_MAKE_INT(p->age); } static void set_person_name(ScmPerson *p, ScmObj val) { if (SCM_STRINGP(val)) { p->name = val; } else { Scm_Error("slot name must be a string.?n"); } } static ScmClassStaticSlotSpec person_slots[] = { SCM_CLASS_SLOT_SPEC("name", person_name, set_person_name), SCM_CLASS_SLOT_SPEC("age", person_age, NULL), { NULL } };
クラスのアロケーションに使われる関数が person_allocate。スロットの初期値もここでセットしておく。 クラスのスロットを slot-ref を使ってアクセスしたい場合は、getter / setter 用の関数も用意する必要がある。
ScmObj Scm_Init_clos(void) { ScmModule *mod; /* Register this DSO to Gauche */ SCM_INIT_EXTENSION(clos); /* Create the module if it doesn't exist yet. */ mod = SCM_MODULE(SCM_FIND_MODULE("clos", TRUE)); Scm_InitStaticClass(SCM_CLASS_PERSON, "<person>", mod, person_slots, 0); /* Register stub-generated procedures */ Scm_Init_closlib(mod); }
今回 closlib.stub はノータッチ。clos.scm で
gosh からテスト。
gosh> (use clos) #<undef> gosh> (d <person>) #<class <person>> is an instance of class <class> slots: name : <person> cpl : (#<class <person>> #<class <top>>) direct-supers: (#<class <top>>) accessors : ((age . #<slot-accessor <person>.age native :age>) (name . # slots : ((name :allocation :builtin :slot-accessor #<slot-accessor < direct-slots: ((name :allocation :builtin :slot-accessor #<slot-accessor < num-instance-slots: 0 direct-subclasses: () direct-methods: () initargs : () defined-modules: () redefined : #f category : builtin gosh> (define *p* (make <person>)) *p* gosh> (slot-ref *p* 'name) "Anonymous" gosh> (set! (slot-ref *p* 'name) "tomapd") #<undef> gosh> (slot-ref *p* 'name) "tomapd" gosh> (set! (slot-ref *p* 'age) 0) *** ERROR: slot age of class #<class <person>> is read-only Stack Trace: _______________________________________ 0 (set! (slot-ref *p* 'age) 0) At line 7 of "(stdin)" 1 (set! (slot-ref *p* 'age) 0) At line 7 of "(stdin)"
動いた。
gosh> (d (make <person> :name "tomapd" :age 24)) #<<person> 0x696ec0> is an instance of class <person> slots: name : "tomapd" age : 20
setter を定義したスロットについては、:init-keyword としても使えるみたい。
SLIME + utf-8 の件
今まで Common Lisp では計算ばっかりしていたので、扱うのは ASCII 文字ばかだったため気付かずに幸せに暮らしていたのだが、昨日ちょっと気が向いてテキストファイルを読み込んで集計するプログラムを作ってみようと思った。UTF-8 エンコーディングは SBCL が対応しており、Emacs (CarbonEmacs) も UTF-8 を使っていた。問題は起こらないと思っていた。
ところが、SBCL w/ SLIME で UTF-8 エンコードされた日本語ファイルを読み込んだところ、無限ループに陥るような挙動を示した。コンソールで SLIME を経由せずに SBCL から読み込む場合は問題ない。これは SLIME のバグだ、と思い込み、メーリングリストに訴えた。
[slime-devel] Slime w/ SBCL 0.9.11 (MacOSX/PPC): no response after reading utf-8/euc-jp files
軽率だった。返事をもらった。
[slime-devel] Slime w/ SBCL 0.9.11 (MacOSX/PPC): no response after reading utf-8/euc-jp files
ちゃんと SLIME の設定で UTF-8 を指定したのか、と。
(setq slime-lisp-implementations '((sbcl ("sbcl") :coding-system utf-8-unix) (cmucl ("cmucl") :coding-system iso-latin-1-unix)))
してませんでした。検索したらマニュアルにも書いてあった。Google 先生に聞いてからリストにメール出すべきだと改めて思った。
SBCL threads on Intel Mac
CL 処理系 SBCL の Mac OS X / Intel におけるスレッドサポートに関する議論メモ(@sbcl-devl)。
2006-03-21 Threads and Lutexes on Mac OS X for Intel Status Update より:
Nathan Froyd and I have been working on getting threads up and running on Mac OS X for Intel. Back in November or so, Nathan originally proposed the concept of a lutex, or a lisp mutex lock, that would be API compatible with the current linux futex-based locking code.
Nothan Froyd と Cyrus Harmon の二人が Darwin/x86 上の SBCL でスレッドを動作させようと試みている。Cyrus Harmon は、www.cyrusharmon.org Coming Soon! の人。メールの技術的な中身はついていけないのだが、最後のまとめとしては、
Back to good news, we can rebuild #+(and sb-thread sb-lutex) with itself and we pass all 14 contrib tests. So things are looking good, but there is still more work to do.
うまくいきそうだと。さらに、たぶん今回あらたに開発した lutex (lisp mutex lock) による互換性の向上からだと思うが、
If this is successful it also suggests that threads on PPC/darwin might be feasible as well.
PPC 上でもスレッドがいけるかもしれないと。期待して待ちたい。
SLIME 2.0 Released
Objective-C <= GC
下記の「Objective-C Mac OS Xプログラミング」をパラパラと斜め読みしていたら興味深い記述があった。もしかすると Mac OS X 10.5 (Leopard) にはガーベッジコレクションが載るかも知れないとのこと。Mac OS X 10.4 上で man cc の上 -fobjc-gc 参照。
Objective-C MacOS X プログラミング
- 作者: 荻原剛志
- 出版社/メーカー: ソフトバンククリエイティブ
- 発売日: 2006/04/07
- メディア: 大型本
- クリック: 94回
- この商品を含むブログ (24件) を見る
c-wrapper for Darwinports
最近話題の c-wrapper の Dawrinports 用 Portfile をサブミット。
http://bugzilla.opendarwin.org/show_bug.cgi?id=7792
3/17 追記:コミットされた。