Gauche:WishList
- <sockaddr> を equal? できる様にして欲しい
- unpack で template に叶う入力でない場合の戻り値の変更
- 別スレッドで report-error を呼んだ場合でもエラーを表示できるようにしてほしい
- define-in-moduleの手続き版が欲しい
- 正規表現の最適化を制御したい
- 文字列の \x, \u, \U 記法
- letrec*
- useしているのに使っていないモジュールを指摘する機能
- tree->string and string interpolation
- getaddrinfo
- cgi-headerでの改行(Windows環境)
- define-cclassにcomparatorを
- long doubleとScmBignumの変換
- http-getの認証対応
- srfi-*を全部読み込むモジュール
- Nonblocking Connect
- 剰余付き累乗
- Nonblocking Write
- any, every for gauche.collection
- after-gc-hook
- weak-hash-table
- export-all*
- add-load-path
- 対応済み: Gauche:WishList:done
- 保留・代案 : Gauche:WishList:pending
<sockaddr> を equal? できる様にして欲しい
ryoakg(2011/06/26 03:38:35 PDT) 元々やりたかった事は、
アドレスやポートの情報 → socket
の hash-table を作って、まだ socket が入ってなかったら(主に初めて通信する相手)、socket を作って hash-table に入れる。
一定期間通信していなかったりしたら、hash-table-delete!。socket-close もする。
という様な事です。hask-table のキーとしてこれを使うのが妥当かどうかは、よく分かりませんが、元から入っているものなので、自分で同じ様なものを作るよりも良いかと思っただけです。
でも一方で、これは Unix から来たもので、元々 Unix でもそういう使い方をしているか? といえばそうでもない気がするので、なるべくC言語のAPIをそのままラップしてそれ以上の事は、もっと外側でやるというポリシーに反するのかもしれません。
でも、その辺りを律儀にやって新たなレイアを作るのも、煩わしい気もします。
私としては、取れない情報があるわけではないので困り度は低いです。
SCM_DEFINE_BUILTIN_CLASS を使っているところだけ、ある程度見ましたが compare が入っていないものは多い様だったので、ひとつひとつ見ていくとアレもコレもとなってしまう気もしました。
また、ScmClassCompareProc の 3つ目の引数の equalp の意味が分かりませんでした。(sort などするときの全順序な場合とそうでない場合?)
- Shiro(2011/06/26 17:41:56 PDT):
object-equal?メソッドでできないかな、 とやってみたらできませんね。compareが入ってないとobject-equal?も呼ばれないのか。 object-equal? を呼ぶようにしてしまうという手がひとつありますが、 この問題に関してはハッシュテーブルで比較関数とハッシュ関数をカスタマイズできるように する、という方が根本的な解決になりそうだと思います。 (object-equal? のカスタマイズはグローバルな効果を持つので、 本来はクラスを提供する人が同時に提供すべきで、ユーザが後付けで定義するものではない。) - Shiro(2011/07/26 01:35:42 PDT): equal? が動くに越したことはないので、socket address についてはequal?で比較できるようにしときました。
unpack で template に叶う入力でない場合の戻り値の変更
ryoakg2011/01/09 20:40:46 PST 言いたい事が2点ありますが、分けて書いても、混ぜて書いても、うまく書けそうにないですが、とりあえず混ぜて書きます。
case1 入力を読んでも #<eof> になっている場合
現状(rev7345)
gosh> (unpack "VVV" :input (open-input-string "")) (#<eof> #<eof> #<eof>)
の様に入力が半端な部分だけに #<eof> が入る様になっている。これを #<eof> だけを返す様にして欲しい(リストに入れない)。
case2 入力が半端な場合
gosh> (unpack "VVV" :from-string "aaaabbbbcc") (1633771873 1650614882 #<eof>)
の様に入力が半端な部分だけに #<eof> が入る様になっている。私見では、これはエラー処理が面倒に思える(理由は下の「問題点(case1,2共通)」に譲る)。
こうすれば良いという方法は思いつかないが、案としては
- #f を返す
- (values #f (unpack-skip "VVV" :from-string "aaaabbbbcc")) を返す
- 例外 などが思いついたが、特に根拠はない(後者は無駄に文字列コピーしてしまうのかも)。
問題点(case1,2共通)
例えば "VVV" だと、多くの場合全ての可能性に対応しようとすれば、以下の様に書く必要が出てくると思う
(match-let1 (a b c) (unpack "VVV" :from-string source)
(cond [(eof-object? a) ...]
[(eof-object? b) ...]
[(eof-object? c) ...]
[else ...]))
なぜなら、仮に
(match-let1 (a b c) (unpack "VVV" :from-string source) (fun a b c))
の様に使える関数 fun があったと仮定する。 (この例では (fun a b c) の様に使っているが、引数の組合せや数は何でもいい)
- #<eof> を引数として期待している、標準のライブラリ関数はほとんどない(と思う)
- 従って、fun はユーザが書いた関数で、結局その中で eof-object? を使った分岐があるハズ
- これは結局、2つ上のコード辺の condなどの分岐が、どこにあるか? という問題に過ぎなく、特に何も解決していない(と思う)。
2つ上のプログラム辺の様に、エラーの箇所毎に分岐するなら (unpack "V") を3回やった方が良い気がする。
case1 についてのメリット
(port-for-each (match-lambda
[(a b c)
....
])
(cute unpack "VVV" :input port))
の様に reader として使える様になる。 (このケースに限らず port-for-each などのループと #<eof> を組合せるのが一番無駄がないと思う(#<eof> が陽には見えないが)、逆にこれら以外のケースで #<eof> が意味のある記号として働くケースを知らない)
でもこれだと、port から読む場合は便利だが :from-string など1回しかやらない場合は #f の方がいいかもしれない。and, and-let* などと組合せられるので
case2 については、何も考えつかない
問題設定について
- 結局、正規表現に過度な期待をしてしまうのと同じ問題ではないかとも思える。根本的には、この template 文字列が言語としての機能が低すぎるから仕方ない?
- もしそうであるなら、どこまで期待をすべき?
Shiro(2011/01/09 23:53:00 PST): とりあえず、データとして#<eof>が返るのは 意図したものというよりは実装上の見過ごしと考えてください。#<eof>は 入力における異常値であって、途中で#<eof>に出会ったら処理全体が#<eof>を返す、 もしくは失敗とすべきです。 (これを簡潔に書くにはmonadが使えるといいんですが、それはまた長くなるので置いときます)。 で、予定よりも入力が短いことを許容するなら、それはtemplate側で「こっから先はオプショナル」 という指定を入れられるべきで、足りない分についてはデフォルト値を指定するなど。 ただ、現在のtemplate文法を拡張してゆくのは無理があるので、 binary.packの位置づけとしては「Perl的コードの手軽なporting」 「使い捨てスクリプト」用とするつもりです。
真面目にバイナリI/Oを行う方法としては、 binary.ioを拡張して構造データを扱えるようにすることを考えています。 既にtrunkには実験的なコードが入ってるのですが、
(define-fstruct header ((version ftype:ulong) (xsize ftype:ulong) (ysize ftype:ulong)) )
というふうに構造体を定義しとけば、
(define h (read-fobject header)) h => #<fstruct header>
というようにバイナリとして読み込んで、
(header-version h) (header-xsize h) (header-ysize h)
などのアクセサでフィールドにアクセスできます。 あるいはu8vectorに格納されたバイナリデータの指定のオフセット位置からを header構造体とみなして各フィールドにアクセスする、など。
これが出来たら、binary.packはその上の層として再実装することになるかなと。 pack指定文字列をfstruct定義へと「コンパイル」する感じ。 今のtrunkの実装はまだ変わると思うのであてにしないで欲しいのですが 方針としてはこんなとこです。
別スレッドで report-error を呼んだ場合でもエラーを表示できるようにしてほしい
koguro(2008/10/04 03:03:14 PDT): report-error が undocumented なのでそもそも使っていいのか分からないのですが、別スレッドで REPL を実行しているときに report-error でエラーを表示したいときがあります。ところが、スレッド内では VM の defaultEscapeHandler が何もしない処理(thread_error_handler) になってしまっているため、現在の report-error の実装だとエラーが何も表示されないで終わってしまいます。できれば、フラグ指定でもいいのでエラー表示を行うようにしてほしいです。
- Shiro(2008/10/04 04:15:21 PDT): むむむ。defaultEscapeHandlerとreport-errorの使い方を
自分で書いてて混乱してるようです。defaultEscapeHandlerが設定されている
場合にreport-errorがそっちに制御を渡してるのは、多分defaultEscapeHandlerが
最終的なエラーハンドリングの振る舞いを決定できるようにするっていう意図だった
んだと思うんですが、一方でthread.cでsrfi-18のセマンティクスを満たすために
defaultEscapeHandlerを上書きした時はreport-errorとの干渉を
考えていなかったような気がします。
thread.cはdefaultEscapeHandlerを使うんではなく、thread_entryの部分で デフォルトのguardを噛ませるようにすればいいんじゃないかな。ちょっと考えてみます。
define-in-moduleの手続き版が欲しい
nekoie(2008/02/08 07:28:47 PST): define-in-moduleは、モジュール名シンボルだけではなくモジュール実体を渡す事も可能で、ドキュメントにもそう書いてあるのですが、special formなので、define-in-module自身の方が引数よりも先に実行されてしまう為、
(define m (make-module #f)) (define-in-module m hoge 123) => *** ERROR: Compile Error: define-in-module: no such module: m
となってしまいます。
(eval `(define-in-module ,m hoge 123) (current-module))
を実行すれば望む結果を得られるのですが、ちょっと分かりにくいので、
(define (bind-in-module env symbol expr) ; 名前は適当 (eval `(define-in-module ,env ,symbol ,expr) (current-module)))
みたいな手続き版も提供してあった方が便利な場合もあると思います。 (とは言え、一行なので、使用頻度を考えると、毎回書いてもいいレベルだとも思いますが)
Shiro(2008/02/08 14:31:26 PST): eval使うなら、
(eval `(define hoge 123) m)
で良いのでは。実行時にグローバルな束縛を追加してゆくのは プログラムの一貫性という観点からはあまり好ましくないので、 わざと不便にしてあります。
nekoie(2008/02/08 16:12:49 PST): 諸事情により、
(define m (make-module #f)) (eval '(extend) m)
のような、defineが存在しない環境に、モジュール外から束縛を与えたかったので、 define-in-moduleを使う必要がありました。 ただ、この状況(define束縛無し)は滅多に無さそうなので、 もし対応するなら、リファレンスのdefine-in-moduleのところに 「evalを使えば可能」という事を追記してもらうぐらいで良さそうです。 (最初に前述のエラーに出会った時に、evalを使う事になかな気付かず、 結構回り道をしてしまったので)
Shiro(2008/02/08 16:39:05 PST): ああ、そういうケースがあるんですね。 extendする前に必要な束縛が決められるなら先に(eval `(define ...)) してから (eval '(extend) m) すればいいわけですが、後から束縛が増えるとなると そうもいきませんか。
evalを使うのは最終手段なので、evalを使うことが自力で思いつける人にしか 使ってほしくないなあ、という思いはあります。
むー、こういう用途を考えるとむしろdefine-in-moduleを拡張すべきかなあ。 設計的に安全なのは、無名モジュールを作った時にフラグによって 「モジュールに束縛を注入する手続き」も同時に得られるようにしといて、 その手続きを使って束縛を入れて行く、ってのはありそうです。 その手続きを手にしていない人には束縛がいじれないと。 でもevalがあったらすり抜けられちゃうから無駄か…
nekoie(2008/02/10 19:49:45 PST): うーん、なるほどです……。 evalがあっても、無名モジュール空間内にdefineがなければ、 (現仕様の)define-in-moduleを使わない限り束縛は追加できないので、 (define-in-moduleを廃止か仕様変更して)無名モジュール作成時に 束縛注入手続きを得られるようにするのでよさそうなんですが、 もし↑の「eval内で、macroやspecial formの実体を、macroやspecial formとして扱ってほしい」パッチを 適用した場合、結局、eval越しにdefineを実行できてしまうので、 ややっこしい事になりそうです。
正規表現の最適化を制御したい
leque(2007/10/29 17:04:13 PDT): 現在リテラルの正規表現はデフォルトで最適化されますが、これをある程度制御できようになるとうれしいです。というのは、SRE をいじっているときに困ったのを思い出したのですが、正規表現の埋め込みや合成をする場合に、rep → rep-while のように文脈に依存した最適化がされてしまうとそういった操作が難しくなるからです。少し用途は違いますが、Ruby では正規表現内の式展開が一度しか行われないようにする最適化する記法として、/.../o というのがあります(これに倣うと最適化なしは #/.../o0 ?)。
- Shiro(2007/10/29 17:43:11 PDT): ふーむ。埋め込みや合成をするのは最適化ステージの 前に全部済ませるってのを想定していたんですが、#/.../をリーダーが読みこんでから その中身をいじりたいというような話でしょうか?
- leque(2007/10/29 19:06:54 PDT): そういう感じです。例えば SRE だと (rx (or ,#/ab+c/ "abd")) のようにしてリーダーの読んだ正規表現を埋め込むことができるので、(#/(ab+c|abd)/ "abd") はマッチするのに対して、((rx (or ,#/ab+c/ "abd")) "abd") は #f になるということが起こってしまいます。
- Shiro(2007/10/29 19:15:05 PDT): それならむしろ、最適化前の表現を取り出せるようにして 使ってもらう方がいいかな? ユーザからするとそこでなぜ最適化を 抑制しなくちゃならないかってわかりずらいと思うし、埋め込んだ後で最適化を かけるならコンパイルされた最終状態じゃなくて途中のASTが得られる方が嬉しいですよね。
- leque(2007/11/05 19:36:55 PST): (すばやいレスに気がつかなかった :-)言われて見るとそうですね。ユーザにそこまで判断させるのは逆に煩雑な気がしてきました。
文字列の \x, \u, \U 記法
文字列の \u 記法等を R6RS と同様に ; をつけて \u3000; のようにもできると嬉しいです(SXML を書いていたら普通の文字列に紛れてしまったので)。
- Shiro(2007/10/07 23:40:41 PDT): 仕様的にはデリミタがはっきりしているR6RSの方が良いと思うので いずれ移行するつもりですが、既存の文法と両立できないので、なんらかのフラグを設ける ことになると思います。
- なるほど、互換性の問題がありましたね。了解しました。(2007/10/21 14:28:08 PDT)
letrec*
Rui(2006/11/15 01:23:04 PST): letrec*を提供してほしいです。現状のGaucheのletrecがletrec*の動作になっているので、名前を定義するだけでよいかと。
- Shiro(2007/10/06 01:15:22 PDT): R6RSも決まったんでそろそろなんとかしたいですが、 現在のletrecは最適化がかかったときにletrec*の動作にならない場合があったような 感じが頭の隅に引っかかってるんです。本当にそうなのかどうなのかはcompile.scmを 読み直さないとならないんで保留になってます。
useしているのに使っていないモジュールを指摘する機能
Rui(2006/10/13 04:56:33 PDT): モジュールをuseしているのに、エクスポートしている束縛を使っていないとき、それを指摘してくれる機能があるとよいです。gauche.testのtest-moduleが警告を出力してくれるとうれしいかも。
- Shiro(2006/10/13 06:43:20 PDT): いいですね。確かにプログラムをいじってると(use ...)がたくさん たまって来て、それをリファクタリングした時なんかに整理しやすい何かが欲しいと 思っていました。ランタイムのチェックはオーバヘッドがあるので、テスト時の チェックが良さそうです。
tree->string and string interpolation
2006/10/12 03:17:18 PDT: string interpolation で例えば ,@a 辺りを (tree->string a) に 展開してくれると、短く書けてよいかも。
- Shiro(2006/10/12 03:25:59 PDT): お、それは面白いかも。
- enami(2006/11/17 16:51:35 PST): 一応 with-module 版を貼っておきます。
c.f. http://www.lingr.com/room/gbq0WCLQEF2/archives/2006/11/16
=================================================================== RCS file: lib/gauche/interpolate.scm,v retrieving revision 1.1 diff -u -r1.1 lib/gauche/interpolate.scm --- lib/gauche/interpolate.scm 2006/11/17 03:40:54 1.1 +++ lib/gauche/interpolate.scm 2006/11/18 00:44:11 @@ -40,6 +40,7 @@ (export string-interpolate) ) (select-module gauche.interpolate) +(autoload text.tree tree->string) (define (string-interpolate str) (if (string? str) @@ -56,13 +57,18 @@ (cond ((eof-object? c2) (write-char c acc) (accum c2 acc)) ((char=? c2 #\,) (write-char (read-char) acc) (accum (read-char) acc)) - ((char-set-contains? #[\x00-\x20\),\;\[\\\]\{\}\x7f] c2) + ((char-set-contains? #[\x00-\x20\)\;\[\\\]\{\}\x7f] c2) (write-char c acc) (accum (read-char) acc)) + ((char=? c2 #\@) + (read-char) + (cons (get-output-string acc) + (insert '(with-module gauche.interpolate + tree->string)))) (else - (cons (get-output-string acc) (insert)))))) + (cons (get-output-string acc) (insert 'x->string)))))) (else (write-char c acc) (accum (read-char) acc)))) - (define (insert) + (define (insert to-string) (let* ((item (with-error-handler (lambda (e) @@ -70,7 +76,7 @@ (lambda () (read)))) (rest (accum (read-char) (open-output-string)))) - (cons `(x->string ,item) rest))) + (cons `(,to-string ,item) rest))) (cons 'string-append (with-input-from-string str (lambda () (accum (read-char) (open-output-string)))))
getaddrinfo
jingu(2006/04/28 07:37:02 PDT): getaddrinfoに渡すhintsを<sys-addrinfo>を作らずに、 キーワード引数で渡すことができるものがあると便利だと思うのですが、 いかがでしょうか。
(define (getaddrinfo node service . hints)
(let-keywords* hints ((flags 0)
(family PF_UNSPEC)
(socktype 0)
(protocol 0))
(sys-getaddrinfo node service
(make-sys-addrinfo :flags flags
:family family
:socktype socktype
:protocol protocol))))
cgi-headerでの改行(Windows環境)
Windows環境でwww.cgiを利用してcgiを使おうとすると、cgi-headerの出力が適正でなくて、正常なレスポンスが返ってきません。\nの部分が0d 0aの2バイトを出力してしまっており、結果的に\r\nが0d 0d 0aとして扱われるためのようです。
\r\nを\x0d\x0aと書き換えても結果は同じだったので、出力の段階で何らかの変換をしてるのかと想像してます。\nを出力すると0d 0aになるのは自然だと思いますのでwww.cgi側で何か対策を取れないでしょうか?とりあえずは\r\nを\nだけに書き換えて対処してますが、もし明示的に改行コードを変えれる方法があるのなら適用してもらえれば助かります。
2006/04/28 05:52:21 PDT
- Shiro(2006/04/28 06:23:44 PDT): 手元で試したところ、cygwinだと正常ですが mingwだとstdoutに対する出力で \n -> \r\n の変換がかかってしまうようです。 (cygwinでは選べたような気もしますが)。 stdoutがO_TEXTでopenされてるってことだと思うので、初期化時点で _setmode(fileno(stdout), O_BINARY) とかしてやれば良さげですが、 全部binary modeにしちゃうと困る場合も出てきそうな気もします。どうしよ。
define-cclassにcomparatorを
genstubのdefine-cclassでオブジェクトを比較する関数を指定できるようになるとうれしいです。
long doubleとScmBignumの変換
koguro(2006/04/08 18:11:41 PDT): stub用のAPIでlong doubleとScmBignumとを変換するScm_MakeBignumFromLongDoubleとかScm_BignumToLongDoubleがあるとうれしいです(これがあるとc-wrapperでlong double対応ができるので)。
http-getの認証対応
rfc.httpのhttp-get, http-put, http-postが認証に対応してくれるといいですね。401を受けたら、自分で特にハンドルしなくてもAuthorizationヘッダつきのリクエストを再送信してほしいです。
srfi-*を全部読み込むモジュール
いつもlet-valuesとかを使うときに「あれっ、SRFIの何番だったけ?」と悩んでしまうので、(use srfi)とかするとsrfi-*のモジュールを全部読み込んでくれるとうれしいです。--koguro(2005/11/23 02:43:28 PST)
- Shiro(2006/01/27 20:09:34 PST): 少々大きなアプリになると(use ...) がずらりと 並ぶので、このへんは何とかしたいところではあります。 ただ、srfiにはGaucheの組み込み関数を置き換えるものもあるので、 srfi-*で全部読んでしまうと危なくありませんかね。
- koguro(2006/02/04 16:55:12 PST): おっしゃるとおりformatなんかの挙動が勝手に変わってしまうと混乱の元になりかねないですね。私自身要望が整理できていないのでもともと思っていたことを書かせていただくと、ある機能を使いたいときに明示的にモジュールを読み込む必要があるのか、それとも組み込みで持っている機能なのかをマニュアルを読まずに判断するための基準がちょっと分かりにくいということを感じていました。例えばsrfiで定義されているものはすべて(use srfi-*)と書かなくてはならないというのであればかえって分かりやすい(覚えなくてはならないのが明確であるため)のですが、現状ではsrfiの中でも一部の機能はコアに含まれていたりするので、ちょっと覚えにくいなと思っていました。特にリストや文字列といった基本的なオブジェクトを操作する関数については迷うことが多いです(removeとか)。その上でsrfiは文字でなく番号でつけられているため、とても覚えにくいなという印象が強くなります(これ自体はGaucheのせいではないんですけど)。
Nonblocking Connect
Nonblockingなconnect(2)をする方法があるとうれしいです。いまはソケットのfdをfcntlでノンブロックにすることはできて、socket-connectを呼ぶことまでできますが、nonblockingな場合はsocket-connectの呼び出しが失敗に終わるので、socket-statusが返すソケットの内部状態が、fdの状態を示したものになりません。(たぶんnonblocking I/Oはひととおり対応予定リストに入っていると思いますけど、一応要望です。)
剰余付き累乗
いくつかの数論的なアルゴリズムを実装するときに、剰余付き累乗が組込みで入っていると割と実用的な速度にできそうなのですが、標準で入らないでしょうか。今すぐ必要というわけでもないので気長に待つ感じで。
アルゴリズムをSchemeで書くとこんな感じ:
; pを法としたaのx乗
(define (pow-mod a x p)
(let ((a (modulo a p))
(n (integer-length x)))
(let loop ((result 1)
(i 0)
(a a))
(if (= i n) result
(if (logbit? i x)
(loop (modulo (* a result) p) (+ i 1)
(modulo (* a a) p))
(loop result (+ i 1)
(modulo (* a a) p)))))))
- Shiro(2005/10/26 20:57:53 PDT): 私はそっち方面に明るくないので コアにこれを持たせる必要性がよくわからないのですが、 math.なんとか、みたいな拡張モジュールで持たせるぶんには構いません。 その場合、これだけじゃなくて使いまわしのきく数論アルゴリズムパッケージ、 みたいになってるといいですね。もし何かデザインして頂ければ本体に バンドルできるんじゃないかと思います。
- ひらっち: 拡張モジュールでもいいと思いますが、
できれば剰余付き累乗だけでも最初に乗っけてほしいです。
DH法やRSAのような公開鍵暗号は、この関数一つあれば
Schemeで実装できてしまいますから、
もし高速な実装ができれば実用上で意味があるのではないかと思います。
私も勉強中ですので、undocumented で pow-mod を math. 以下に入れて
そこから積上げてくってのがやりやすいかも。
例えばDH法自体は、以下のように pow-mod があれば簡潔に書けます。
(パラメータの生成はもうちょっと複雑)
ただ、pow-mod まで Scheme で書くと非常に遅くなるんです。
(define (make-dh g p) (let ((pri-key (random-integer p))) (list g p pri-key (pow-mod g pri-key p)))) (define dh-g car) (define dh-p cadr) (define dh-pri-key caddr) (define dh-pub-key cadddr) (define (dh-make-share-key dh pub-key) (let ((pri-key (dh-pri-key dh)) (p (dh-p dh))) (pow-mod pub-key pri-key p))) - Shiro(2005/10/27 02:25:41 PDT):ふむ。こっそりmath.pow-modを作ってそっから色々 試してもらうのも手ですが、将来的にモジュールがあまり増え過ぎると目的の関数を 探すのが大変になるので、覚えやすい単位でグループ化できるものはしときたい、 という意図があります。例えばmath.modularとしてmodular arithmeticを実装する、 というのはどうでしょう。今すぐでなくても将来色々とそのモジュールに 追加してゆけそうな括りならば、とりあえず最初はpow-modだけを実装しておいて 徐々に便利そうな関数を増やしてゆく、というのでいいです。 私自身はあまり触ったことのない分野なのでそのへんの予想がつかないんで、 助言頂ければありがたいです。
- ひらっち:勉強中で助言というのもアレですが、整数論ではプリミティブは 少なめで、応用がいっぱいという印象です。 pow-mod を入れるのも、単純に計算コストがこの関数に 集中しているという理由からですし、 現状で不足している関数といえば pow-mod くらいかと思います。 将来の拡張を考えるのなら、数論/算術全体に対して math.arithmetic とかにした 方が良くないでしょうか。
Nonblocking Write
ソケットにwrite-blockしたとき、書き込めるだけのバイトを書き込んでブロックしない方法を提供してほしいです。selectとread-block、write-blockを使って、シングルスレッドのサーバで複数のクライアントを同時にサポートしようとしているのですが、ソケットを読まないクライアントがいるとサーバが書き込みでブロックしてしまいそうです。
Shiro(2005/09/05 14:00:18 PDT): 確かに。これは何とかしないとだめですね。 ソケットをnonblockにするのはgauche.fcntlでできると思いますが、 Gauche内部でwrite(2)がEAGAINを返した時の処理が難しい。Schemeレベルでの portへの書き込みからwrite(2)までにいくらでも任意のCレベルの処理が 入る可能性があるので、EAGAINをSchemeレベルで捕捉したとしても write(2)から再開する手段がありません。
Cレベルのport APIを全部トランポリンで書ければcall/ccで復帰できて 綺麗なんですが、Cコードの方がえらく複雑になるので避けたいです。 となると、(1)write-block限定、(2)procedural portやconversion portが 噛んでない、生のfile port限定、という特定の条件下でのみ、EAGAINを port API内で捕まえてwrite-blockが特定の戻り値を返す、みたいな 方法が現実的な線かもしれません。条件がかかるのが醜いですが…
- なるほど。write-blockにPutzからコードをコピペして、生のfile port(バッファリングなし)という条件のときだけ、書き込んだバイト数を返すようにしてみました。EAGAINのときは0を返します。うまく動くようです。私にはこういう程度でいまのところ十分のようです。
Shiro: Port回りは0.9までに直さなくちゃならない項目の筆頭なので、 たぶん0.8.6後に本格的に取り組むことになると思います (srfi-68の進行も 横目で見てないとならないんですが)。そこで対応を考えたいと思います。
- ありがとうございます。期待しています。
any, every for gauche.collection
- (2004/12/20 04:25:50 PST) ねるWiki:ねる: gauche.collectionにany, everyもほしいです。
- leque(2006/09/13 22:26:58 PDT): filter-map や count も generic に扱えると嬉しいと思いました。こんな感じで collection.scm sequence.scm
after-gc-hook
- (2004/09/15 23:56:20 PDT) ねるWiki:ねる Scm_RegisterFinalizerをschemeからも使いたいです.
Shiro: これはそう簡単ではないんですよ。=> 議論はGauche:Schemeコードのファイナライザ
weak-hash-table
- (2004/09/15 23:56:20 PDT) ねるWiki:ねる weak-vectorだけだとちょっと不便なのであるとうれしいです.
- Shiro: 欲しいですね。単に開発の手間の問題で後回しになっています。
- ねるWiki:ねる: ああ、では、書いてみます。
export-all*
export-allする際に、頭が%のものはexportしないようなexport-all*が欲しいです。prefixが設定できればなおいいのですが、%固定で充分だと思います。今作っているモジュールのpublic/private数が62/3なので大変なことになってまして・・・。--hira(2004/03/17 02:35:42 PST)
- 参考 Scheme:!と? nakamuraさんとこ
- そのmoduleの先頭で以下のようなマクロを定義して、exportするものを明示的にこれでdefineすればいいんじゃないでしょうか。
(define-syntax define-public (syntax-rules () ((_ (f . args) . body) (begin (define (f . args) . body) (export f))) ((_ i v) (begin (define i v) (export i))))) - Shiro: exportに関しては実装も含めてきれいな解決を探したいので、
当面はアドホックに対応して頂けますか。
- regexpを使う場合、exportが評価された後でそのモジュールにシンボルが 追加されると問題になります (モジュールは「閉じて」いないため、いつでも 新たなシンボルが追加され得ます)
- define-public方式はだいたいうまく動くんですが、define-class等別のマクロと 両立しないんですね。そういうのだけ明示的にexportを書くってので運用上は なんとかならなくはないんですが、システム標準にするのにはまだ抵抗があるって 感じです。
add-load-path
- skimu: 文字列を持っている変数を渡せたらうれしいです。
gosh> (define my-path "fobar")
my-path
gosh> (add-load-path my-path)
*** ERROR: string required, but got my-path
Stack Trace:
_______________________________________
0 (%add-load-path path)
At line 30 of "/usr/local/share/gauche/0.6.3/lib/gauche-init.scm"
Shiro: ロードパスはコンパイル時に決定していて欲しいので、add-load-pathはマクロにしてリテラル文字列しか受け付けないようにしています。 add-load-path内で変数を評価するようにしてしまうと、例えば次のフォームはうまく動きません。
(begin (define my-path "foobar")
(add-load-path my-path))
beginフォーム全体がまずコンパイルされ、その後評価時に"foobar"が評価されmy-pathへと束縛されますが、add-load-pathそのものはコンパイル時に処理されなければならないためです。
ただ、コンパイル時に値が確定出来る式をadd-load-pathが取ることを許す、という変更は可能ですね。例えばマクロの束縛はコンパイル時に確定しているので(でないとマクロ展開が出来ない)、こんなふうに書けるようにはできるかもしれません。
(define-macro (my-path) "foobar") (add-load-path (my-path))
ちょっと考えてみます。
現在の仕様でロードパスを実行時に変更するのは、変数*load-path*を直接変更することで可能です。
(push! *load-path* "foobar")
マニュアルでは*load-path*を直接いじるのは非推奨としていますが、それは上記のような評価のタイミングによる混乱を避けるためで、分かって使うぶんには問題ありません。 (2002/09/28 18:10:11 PDT)
skimu: ご丁寧な解説ありがとうございます。 コンパイル時に決まってなきゃいけないのは autoload をきちんと処理するためですよね? 一応確認。こういうブートストラップ的な問題は考えるとすぐ頭痛くなっちゃいます ^^; しかし add-load-path を使わない方向で検討したら却ってしっくりくるものに仕上がりました。ちなみに何をやっていたかというと todoさんのページにあった Gauche-gl のかっこいいデモを MacOSX のアプリケーションバンドルにして遊んでいたのでした。2002/09/28 21:36:32 PDT