一般化されたset!
CommonLispのsetfと同じようなことは、set!で出来ると教えてもらった。
これをobject-applyと組み合わせれば、Arcの=と同じようなことも出来る。
Special Form: set! (proc arg …) expression
2番目の形式はSRFI-17に定義されている「一般化されたset!」です。 これは構文的な装飾であり、実際は以下のように解釈されます。
((setter proc) arg … expression)Function: setter proc
http://practical-scheme.net/gauche/man/gauche-refj_25.html
[SRFI-17] 手続きprocのsetter手続きを返します。 procがsetter手続きを持たない場合の動作は未定義です。
ある関数fのsetter手続きgとは、もし(g a b … v)のように呼ばれた場合、次の(f a b …)がvを返すようになる手続きのことです。
準備
以下の3行を読み込ませる
(use gauche.sequence) (define-method object-apply (obj key) (ref obj key)) (define-method (setter object-apply) (obj key val) (set! (ref obj key) val))
リストの場合
gosh> (define ls '(a b c)) gosh> ls (a b c) gosh> (ls 2) c gosh> (set! (ls 2) 'x) gosh> ls (a b x)
文字列の場合
gosh> (define st (string #\a #\b #\c)) gosh> st "abc" gosh> (st 2) #\c gosh> (set! (st 2) #\x) gosh> st "abx"
ハッシュの場合
gosh> (define ht (hash-table 'eq? '(a . 1) '(b . 2))) gosh> ht #<hash-table eq? 0x8233c80> gosh> (use util.list) gosh> (hash-table->alist ht) ((b . 2) (a . 1)) gosh> (ht 'b) 2 gosh> (set! (ht 'b) 3) gosh> (hash-table->alist ht) ((b . 3) (a . 1))
おぼえがき
(define st "abc")としなかったのは、リテラル文字列は変更不可能だから。
リストでも文字列でもハッシュでも同じように出来る、というために文字列の例も出したが、文字列でこのやり方をするのは非推奨らしい。
なお、ダブルクォートで囲って作成した文字列は変更不可能です。その他の方法で作成した文字列はstring-set!で変更可能です。
2007/04/29 16:18:47 shiro
「ダブルクォートで囲って作成した文字列は変更不可能」なのはそれがリテラルだから。
「リテラル文字列は変更不可能」と言っておけばよい。
string-set!は *強く非推奨* です。書かなくても良いくらいだけど、いちおうR5RSに
入ってるから触れたいというのなら、「なお、リテラル以外の文字列はstring-set!で
変更できますが、そのようなスタイルはGaucheでは推奨されません。」の1行くらいに
とどめといてください。2007/04/29 16:21:00 shiro
http://karetta.jp/article/book/007376/007378/commentList#commentList
もう少し言うと、Gaucheでのstring-set!は、「その一文字分だけを置き換えた文字列を
新たに作成する」というふうに実装されています。したがってstring-set!を使って
性能的に特をすることはまったくありません。素直に文字列の断片を自分で集めて
最後にstring-appendするなりすべきです。