#ちなみにシンボル中の'\'の文字の解釈は今まで決めてなかったんですが、R7RSで決まったのでこれからそちらに合わせます。
#(define (wrap . arg)
(getter-with-setter
(^[] (apply values arg))
(^ x (set! arg x)) ) )
#このような関数をつくれば、複数のパラメータを複数わたしたいときに便利なのかしら?とか。
#シードが複数、リストが複数、のfoldとか。
#受け渡し以外に、単に値をまとめたいというだけのときとか。多値をファーストクラスなもので保持するための表現の一つになるのかしら?とか思いました。
#ん? そのコードだと(set! arg x)の意味が無いような?
#gosh> (define x (wrap 1 2 3))
x
gosh> (x)
1
2
3
gosh> ((setter x) 12 )
(12)
gosh> (x)
12
gosh> (set! (x) "hoge")
("hoge")
gosh> (x)
"hoge"
#なんというか、こう、値を変数みたいに扱うというか。変数以上、コレクション未満的な存在。
#これを手続きにわたして、結果を受け取るような。むう、あまり意味が無いかしらん。
#gosh> (define (test t) (set! (t) "foo"))
test
gosh> (test x)
("foo")
gosh> (x)
"foo"
#gosh> (define (test2 t) ((setter t) "foo" "bar" "hoge"))
test2
gosh> (test2 x)
("foo" "bar" "hoge")
gosh> (x)
"foo"
"bar"
"hoge"
#ああ、わかりました。そういうふうに使いたいわけですね。boxの多値版だな。
#(そこで、set!を多値にしたバージョンが(略)
#boxというのは、set-box!/unboxのことですか?(ググったのですが、これかなと)
#boxというのがいくつかのScheme実装にあって、R7RS-largeにも提案されています。http://srfi.schemers.org/srfi-111/srfi-111.html そのwrapはboxを多値に拡張したもの、と考えられます (参照用の関数が無いところは違いますが)。 #ありがとうございます。なるほど。やっぱり考えられていましたか。(FORTRANの変数渡しをちょっと思い出しました。)
#個人的にはset!のセマンティクスを変えるよりは、set-box!のような別のAPIでもって複数の値をパックしていることを示す方が良いと思います。
#これは純粋に手続きだから、inlineなどでコンパイラがよろしく最適化をしてくれるのかしら?と淡い期待をもっていたりするので、下手に構造をいれるとまずいかなあと迷っています。
#手続きになにか属性をもたせることができれば、あたかも何かの構造のように見せることはできるかなあとか。
#んー、(setter x)を最適化する予定はありますが、性能が重要であればset-box!を最適化することだって考えます。何を最適化するかは、それがボトルネックであることが確認されてから決めることなので、それがボトルネックになるかどうかわからない時点では何とも言えません (経験的に「これがボトルネックになりそう」と当たりをつけて実装を決めることはありますが)
#もうひとつは、このwrapは拡張set!の意味をそのままコードにしたような形になっていて、値の保持をリストにした途端に、「リスト」でいいんじゃないか?という気がしてしまいまして・・・・・
#どうも、うまく表現できないのですが。getter-with-setterをぎりぎりまで切り詰めたような表現になっているというか。
#多値set!は、setterで「セットされるもの」の意味がオーバーロードされてしまっているのでいまいち筋が悪いという感じがします。一般化set!では (set! x expr) の x のところに変数も式も使えるよ、だったわけですが、多値set!ではxのところに変数がきた時の意味づけが難しいです。(set! x a b c ...) の時のxは式のみ、としてしまうと、それならset!と呼ぶ意味があんまりないんじゃないか、って話になります。まあ、(setter x)と(x ...) に関して、n引数とn戻り値の対称性があるのは確かに綺麗なんですが。
#(実は一般化set!に対しても、変数の変更と構造の変更は意味が違うからオーバーロードするの反対、って意見がありました。一般化set!が無くて、setterを使う構造の変更がsetf! みたいな別名になってるなら、そのsetf!を多値/多引数へと拡張するのはより自然だったと思います。)
#あ、なるほど。(set! x 1 2 3)だとxがファーストクラスになるための器がないということですね。
#(ということは、ジェネレータを多値にすることも困難か・・・・)
#でも多値はもうちょい工夫の余地はあると思うんで、色々実験してみてください。
#(define (wrap . arg)
(getter-with-setter
(^[] (apply values arg))
(^ x (set! arg x)) ) )
(define-record-type <box> %make-box box? (%fn %fn) )
(define (box . arg) (%make-box (apply wrap arg) ) )
(define-method unbox ((x <box>)) ((%fn x)) )
(define-method set-box! ((x <box>) . arg ) (apply (setter (%fn x)) arg) )
#gosh> (define x (box 1 2 3))
x
gosh> (unbox x)
1
2
3
gosh> (set-box! x 1 2 "hoge")
(1 2 "hoge")
gosh> (unbox x)
1
2
"hoge"
#こんな感じです。
#複数の値を入れること前提ならリストなりベクタなりに入れておけばいい話で、わざわざ box を導入する甲斐がないような気がしますね。
#良い名前があればなんか納得できそうな気もするんですが…
#それを突かれると痛い。そうなんですよねえ。リストでもいいんです。
#ただ、多値に拡張できるから拡張したというだけという・・・・
#(define (gwrap g)
(getter-with-setter
(lambda [] (g))
(lambda [h] (set! g h)) ) )
#使うかどうかは謎ですが、wrapをつかうとgeneratorを途中で変更できるようになります。
#遅延シーケンスの元になるgeneratorを途中で変更するなんていうことはしないだろうし、アイデアだおれかしらん。
#複数のファイルを読むときに使えるか? perlのダイヤモンド演算子的な処理をするときとか。
#動的スコープとか言うんでしたっけ?
#https://plus.google.com/108364314136680772678/posts/HB37TjS1j8a 多値のboxについては、G+のグループのほうにも流しました。つたない英語なので、通じるかどうか。+1の数で反応を見てみようかと。(でも、どれほどのひとが見ているであろうかとは思うのですが。) #あと、多値のboxのauto boxingとか考えると変な感じです。複数パラメータを受け取るための受け皿的な。
#wilikiで議論されていた多値の話をちょっと思い出します。