Gauche:Bugs:log15
Gauche 0.9.2以前のバグ
- rfc.uriのuri-mergeで結果の正しくない?結合パターンがある(52712ab)
- (use srfi-1 :only (find)) がエラーになる (0.9.2_pre2)
- format の ~* で最後の引き数を飛ばせない(9379ba5)
- named letでコンパイルエラー(9ac2d87)
- port-buffering が :modest :none で read-block が停止する場合
- construct-json に空リストを渡すとエラーになる
- リファレンスの sys-getaddrinfo の説明
- assert-curr-charのエラーメッセージ(89202df)
- メタクラスを指定したクラスをchange-classするとSEGV(43634d4)
- create-directory-treeのspecに文字列・シンボルを指定するとエラー
- vmの命令と対応する関数をdefineで上書きしても、vmの命令としてコンパイルされる
- HTTPレスポンスヘッダにContent-Lengthが無い場合、バイナリデータを受け取れない(0.9.1)
- マニュアル typo Adler32
- parameterizeを抜ける際にconvert procedureが呼ばれてしまう
- binary.pack の unpack で #<eof> が入ったり入らなかったりする
- Windows7上でMinGW版gauche-install.exeが実行できない
- gauche.partcontのマニュアルの日本語訳が中途半端 (0.9.1)
rfc.uriのuri-mergeで結果の正しくない?結合パターンがある(52712ab)
(2011/08/02 05:54:22 PDT)
gosh> (uri-merge "http://aaa.bbb" "xxx.yyy") "http://aaa.bbbxxx.yyy"
これは
"http://aaa.bbb/xxx.yyy"
となるのが正しいのではないでしょうか。
- Shiro(2011/08/02 23:46:31 PDT): 修正しました。
(use srfi-1 :only (find)) がエラーになる (0.9.2_pre2)
teppey(2011/08/01 08:03:54 PDT): srfi-1モジュールからコアに移ったいくつかの手続きをインポートオプションに指定するとエラーになります。これらの手続きをsrfi-1でもエクスポートするのはどうでしょうか。
diff --git a/libsrc/srfi-1.scm b/libsrc/srfi-1.scm index f436d82..f0f958a 100644 --- a/libsrc/srfi-1.scm +++ b/libsrc/srfi-1.scm @@ -17,19 +17,19 @@ (define-module srfi-1 (export xcons cons* list-tabulate circular-list iota - not-pair? + not-pair? null-list? list= first second third fourth fifth sixth seventh eighth ninth tenth car+cdr take drop take-right drop-right - take! drop-right! split-at! last + take! drop-right! split-at split-at! last concatenate concatenate! append-reverse append-reverse! zip unzip1 unzip2 unzip3 unzip4 unzip5 - count unfold pair-fold reduce unfold-right + count fold unfold pair-fold reduce fold-right unfold-right pair-fold-right reduce-right append-map append-map! map! pair-for-each filter-map map-in-order filter partition remove filter! partition! remove! - member find-tail list-index + member find find-tail any every list-index take-while drop-while take-while! span break span! break! delete delete-duplicates delete! delete-duplicates! assoc alist-cons alist-copy alist-delete alist-delete! @@ -44,6 +44,12 @@ (define-inline (not-pair? x) (not (pair? x))) +(define-macro (from-core . xs) + `(begin + ,@(map (^x `(define ,x (global-variable-ref (find-module 'gauche) ',x))) + xs))) +(from-core null-list? any every fold fold-right find split-at) + ;;; ;;; List generators of SRFI-1 diff --git a/test/dict.scm b/test/dict.scm index 08dd21d..285de7a 100644 --- a/test/dict.scm +++ b/test/dict.scm @@ -37,7 +37,6 @@ (test-basics (make-bimap (make-hash-table 'eq?) (make-hash-table 'eqv?))) (use gauche.collection) -(use srfi-1) (let1 bm (make-bimap (make-hash-table 'eq?) (make-hash-table 'eqv?)) (bimap-put! bm 'a 1)
- Shiro(2011/08/01 11:19:25 PDT): なるほどこれは盲点でした。
これ、根本原因はgaucheモジュールがfind等をexportしてないことです。
すべてのモジュールがgaucheをデフォルトで継承してるので今まで気づきませんでした。
(with-module gauche (export-all))
すればokです。 正しくやるにはちゃんとpublicな関数だけ列挙した方がいいですが。 - Shiro(2011/08/03 00:24:38 PDT): しまった。だめだ。gaucheモジュールがexport-all
してしまうと、
「gaucheをextendしているモジュール(ほぼ全てのモジュールが該当)」をuse
するとぞろっとgauche内で定義されてる束縛もimportすることになる。
そうすると、「gaucheで定義されている束縛をシャドウするようなモジュール (gauche.collectionとか)」をuseした後に無関係なモジュールをuseしたら、
それについてきたgauche由来の束縛でもってせっかくimportした前者のモジュールの
束縛がまたシャドウされちゃう。
(use gauche.collection) (use rfc.http) ;; 一見無関係なモジュール fold ;; これがgauche.collectionのfoldではなくgaucheのfoldになっちゃう。
てなわけでteppeyさんのfixのように再定義&エクスポートするしかないな。 ちなみによそのモジュールの束縛を引っ張ってくるのは、わざわざglobal-variable-refを 使わないでも、こんな感じでok:(define-module fold (with-module gauche fold))
format の ~* で最後の引き数を飛ばせない(9379ba5)
leque(2011/07/16 20:41:13 PDT):
gosh> (format "~*" 1) *** ERROR: '~*' format directive refers outside of argument list in "~*"
SLIB や CL の動作を見るとエラーになってほしくない気がします。
gosh> (use slib) gosh> (require 'format) gosh> (format "~*" 1) ""
% sbcl ... * (format nil "~*" 1) ""
こんな感じでしょうか。
diff --git a/src/write.c b/src/write.c index 8e443cc..0f1b25b 100644 --- a/src/write.c +++ b/src/write.c @@ -875,7 +875,7 @@ static void format_proc(ScmPort *out, ScmString *fmt, ScmObj args, int sharedp) } else { backtracked = TRUE; } - if (argindex < 0 || argindex >= arglen) { + if (argindex < 0 || argindex > arglen) { Scm_Error("'~*' format directive refers outside of argument list in %S", fmt); } argcnt = argindex;
- Shiro(2011/07/25 05:29:43 PDT): それで問題なさそうです。fixed (a4338ab)
named letでコンパイルエラー(9ac2d87)
teppey(2011/07/01 20:04:54 PDT): 以下のコードがコンパイルエラーになります(-fno-inline-localsか-fno-lambda-lifting-passオプションを与えると発生しません)。
$ cat /tmp/x.scm (let loop () (values (lambda () #f)) (loop)) $ ./gosh -ftest /tmp/x.scm gosh: "error": Compile Error: vector-ref index out of range: 6 "/tmp/x.scm":1:(let loop () (values (lambda () #f)) ...
compile.scmのpass4/scanでトップレベルのlambda nodeにマークが付けられますが、$lambda-flagがdissolvedだった場合このノードは
- pass4/liftに渡されないのでマークされたまま($lambda-lifted-varが#t)
- pass4/substの$LAMBDAの節で($gref #t)が返される
となるように思いました。場当たり的ですが、パッチです。
diff --git a/src/compile.scm b/src/compile.scm index a9bf482..ed3b0b3 100644 --- a/src/compile.scm +++ b/src/compile.scm @@ -4031,7 +4031,8 @@ ;; We just mark it by setting lifted-var to #t so that ;; pass4/lift phase can treat it specially. (if t? - ($lambda-lifted-var-set! iform #t) ;mark this is toplevel + (unless (eq? ($lambda-flag iform) 'dissolved) + ($lambda-lifted-var-set! iform #t)) ;mark this is toplevel (begin ($lambda-free-lvars-set! iform inner-fs) (let loop ([inner-fs inner-fs] [fs fs])
- Shiro(2011/07/13 14:37:48 PDT): ども。修正入れました (c71ff5a)
port-buffering が :modest :none で read-block が停止する場合
ryoakg(2011/06/27 01:43:00 PDT): 例えば
(receive (in out) (sys-pipe) ;; :modest かどうか一応確認 (display #`"buffering in : ,(port-buffering in)\n" (standard-error-port)) (display #`"buffering out: ,(port-buffering out)\n" (standard-error-port)) (display "a" out) (flush out) ;; (set! (port-buffering in) :none) ; こっちでも同じ ;; a が読める (let1 d (read-block 64 in) (format (standard-error-port) "~s~%" d)) ;; ココで止まる (let1 d (read-block 64 in) (format (standard-error-port) "~s~%" d)) )
とすると、2回目の read-block で止まります。読む側に何もない状態だと起る様です。(read-block! も同様でした。socket も同様の様です。元々 socket でやっていましたが、それをココに書くのは面倒なので pipe にしています)
read-block の説明 http://practical-scheme.net/gauche/man/gauche-refj_58.html#index-read_002dblock を見ると、特にその様な事は書いていないので必ずすぐ return する様に思えますが、read-block! の http://practical-scheme.net/gauche/man/gauche-refj_101.html#index-read_002dblock_0021 では「vecを埋める前に戻ることがあります」と、「そういう場合もある」という表現になっています。英語だと「read-block! may return before ...」でした。
C言語で同じ様な事(だと私が勝手に思っている事)
#include <sys/wait.h> #include <fcntl.h> #include <errno.h> #include <stdio.h> #include <stdlib.h> #include <unistd.h> #include <string.h> int main(void) { int pipefd[2]; char i,o; int s; if (pipe(pipefd) == -1) { perror("pipe"); return 1; } fcntl(pipefd[0], F_SETFL, O_NONBLOCK | fcntl(pipefd[0], F_GETFL, 0)); i = 'a'; write(pipefd[1], &i, 1); s = read(pipefd[0], &o, 1); printf("s:%d, o:%c\n", s, o); s = read(pipefd[0], &o, 1); /* fcntl やらないとココで止まる */ if (s <= 0) { int err = errno; puts(strerror(err)); printf("EWOULDBLOCK?:%d, EAGAIN?:%d\n", err == EWOULDBLOCK, err == EAGAIN); } printf("s:%d, o:%c\n", s, o); return 0; }
をすると、読む側に何も届いていなくてもとりあえず read は戻ります。
これと考えを揃えるなら
- read-block なら "" が戻る
- read-block! だと 0 が戻る。uvector は変化なし。 が妥当に思えます。
現状停止したくなければ、byte-ready? などを使えば良い様子でしたが、複数スレッドがある期間同じ port を読む様なプログラムがうまく動く事を望む場合は、うまくいかない場合が出る気もしました。
- Shiro(2011/06/27 02:20:13 PDT): バッファリングとblocking/non-blockingはレイヤが違います。
- バッファリングはシステムコールの上(アプリケーションや言語ランタイム側)にバッファを持つことで、 Schemeレベルでの入出力コールをシステムコールのI/Oからdecouplingするという ことです。C言語でのFILE*を使ったライブラリに相当するものです。
- full bufferingであれば、Schemeの入出力コールは必ずしもシステムコールを 起動しないし、あるいはSchemeの単一の入出力コールが複数のシステムコールを起動する こともありえるということです。
- 一方、buffering :noneというのはバッファリングが無いということですから、 Schemeの入出力関数が直接システムコールの起動と対応します。システムコールが ブロックするかどうかは関係ありません---システムコールがブロックすれば、 Schemeレベルでもブロックします。
- buffering :modestはfull bufferingのうち、「Schemeレベルでの単一コールが 複数のシステムコールに対応する」というものだけを避けたものです。
- SchemeレベルでソケットI/Oでブロックしたくなければsys-select等を使う ことを想定しています。これは標準的なCプログラミングと同じです。 (sys-selectでreadable/writeableになった後で複数のシステムコールを 発行すると2番目以降でブロックする可能性があるので、そのためにmodestモードがあります。)
- sys-selectかけてから読みに行く前に他のスレッドが割り込まないようにする、 というのはアプリの責任と考えています。
- システムコールをnon-blockingにするのは、単にfcntlでフラグをセットするだけでは 済まなくて、あちこち変える必要があるんで、現在のGaucheそのままでは うまくいかないかも。(使い方を限定すればできるかもしれませんが)。 それと、O_NONBLOCKはforkしたりdupしたりすると 面倒な話があったような… プログラマが使い方を自分で限定してればいいんですが、 Gaucheのランタイムのように「どう使われるかわからない」というレイヤで 暗黙のうちにいじるのは難しかったと思います。
construct-json に空リストを渡すとエラーになる
leque(2011/06/26 21:19:18 PDT): 空のオブジェクトを読み込んで書き出そうとした場合にエラーになります。
> (parse-json-string "{}") () > (construct-json (parse-json-string "{}")) *** JSON-CONSTRUCT-ERROR: construct-json expects a list or a vector, but got () > (construct-json (parse-json-string "{\"a\": {}}")) *** JSON-CONSTRUCT-ERROR: construct-json expects list or vector, but got: () Stack Trace: _______________________________________ 0 (print-value (cdr attr)) At line 176 of "/usr/local/share/gauche-0.9/0.9.1/lib/rfc/json.scm" 1 (fold (lambda (attr comma) (unless (and (pair? attr) (string? (car ... At line 167 of "/usr/local/share/gauche-0.9/0.9.1/lib/rfc/json.scm"
diff --git a/lib/rfc/json.scm b/lib/rfc/json.scm index 7909a18..f05434e 100644 --- a/lib/rfc/json.scm +++ b/lib/rfc/json.scm @@ -155,7 +155,7 @@ (cond [(eq? obj 'false) (display "false")] [(eq? obj 'null) (display "null")] [(eq? obj 'true) (display "true")] - [(pair? obj) (print-object obj)] + [(list? obj) (print-object obj)] [(vector? obj) (print-array obj)] [(number? obj) (print-number obj)] [(string? obj) (print-string obj)] @@ -206,7 +206,7 @@ (define (construct-json x :optional (oport (current-output-port))) (with-output-to-port oport (^() - (cond [(pair? x) (print-object x)] + (cond [(list? x) (print-object x)] [(vector? x) (print-array x)] [else (error <json-construct-error> :object x "construct-json expects a list or a vector, ¥
- Shiro(2011/06/30 23:36:14 PDT): fixed (9ac2d87)
リファレンスの sys-getaddrinfo の説明
ryoakg(2011/06/26 01:49:33 PDT): 英語は自信ないですが以下じゃないかと思います
http://practical-scheme.net/gauche/man/gauche-refj_87.html#index-sys_002dgetaddrinfo 誤: ... <sys-addrinfo> のインスタンスを返します。 正: ... <sys-addrinfo> のインスタンスのリストを返します。
http://practical-scheme.net/gauche/man/gauche-refe_87.html#index-sys_002dgetaddrinfo
誤: Returns <sys-addrinfo> instance ... 正: Returns a list of <sys-addrinfo> instance ...
- Shiro(2011/06/26 17:16:39 PDT): ありがとうございます。fixしました (a60cf58)
assert-curr-charのエラーメッセージ(89202df)
teppey(2011/06/16 07:45:50 PDT): 読み込んだ文字がエラーメッセージに含まれていませんでした。
diff --git a/lib/text/parse.scm b/lib/text/parse.scm index ee1a08e..f611276 100644 --- a/lib/text/parse.scm +++ b/lib/text/parse.scm @@ -169,8 +169,8 @@ (define pred (char-list-predicate char-list)) (rlet1 c (read-char port) (unless (pred char-list c) - (errorf "~awrong character c ~a. ~s expected." - (ppp port) string char-list)))) + (errorf "~awrong character ~s ~a. ~s expected." + (ppp port) c string char-list)))) (define-compiler-macro assert-curr-char (er-transformer prefold-macro-1))
- Shiro(2011/06/26 17:16:39 PDT): ありがとうございます。fixしました (74c5645)
メタクラスを指定したクラスをchange-classするとSEGV(43634d4)
teppey(2011/05/29 17:56:03 PDT): メタクラスがどういうものかよく分かっていないのですが、以下のスクリプトがsegmentation faultになりました。
$ uname -srm Linux 2.6.32-5-amd64 x86_64 $ ./gosh -V Gauche scheme shell, version 0.9.1 [utf-8,pthreads], x86_64-unknown-linux-gnu $ cat /tmp/x.scm (define-class <c-meta> (<class>) ()) (define-class <c> () () :metaclass <c-meta>) (define c (make <c>)) (change-class <c> <c-meta>) (write c) $ ./gosh -ftest /tmp/x.scm zsh: segmentation fault ./gosh -ftest /tmp/x.scm
gdbのバックトレースです。
$ gdb --quiet --args ./gosh -ftest /tmp/x.scm Reading symbols from /home/teppey/src/Gauche-trunk/src/gosh...done. (gdb) run Starting program: /home/teppey/src/Gauche-trunk/src/gosh -ftest /tmp/x.scm [Thread debugging using libthread_db enabled] Program received signal SIGSEGV, Segmentation fault. Scm_SubtypeP (sub=0x71ac00, type=0x7ffff7c5a860) at class.c:850 850 while (*p) { (gdb) bt #0 Scm_SubtypeP (sub=0x71ac00, type=0x7ffff7c5a860) at class.c:850 #1 0x00007ffff795bba3 in Scm_ComputeApplicableMethods (gf=<value optimized out>, argv=<value optimized out>, argc=2, applyargs=0) at class.c:2076 #2 0x00007ffff793cfcf in run_loop () at ./vmcall.c:250 #3 0x00007ffff7951e85 in user_eval_inner (program=<value optimized out>, codevec=<value optimized out>) at vm.c:1288 #4 0x00007ffff7952c3e in apply_rec (vm=<value optimized out>, proc=<value optimized out>, nargs=<value optimized out>) at vm.c:1384 #5 0x00007ffff7974172 in write_ss_rec (obj=0x7ff3c0, port=0x720e40, ctx=0x7fffffffe0b0) at write.c:554 #6 0x00007ffff7974ae6 in Scm_Write (obj=<value optimized out>, p=<value optimized out>, mode=<value optimized out>) at write.c:153 #7 0x00007ffff79a60d8 in stdlib_write (SCM_FP=<value optimized out>, SCM_ARGCNT=<value optimized out>, data_=<value optimized out>) at stdlib.stub:595 #8 0x00007ffff794a6cb in run_loop () at ./vmcall.c:186 #9 0x00007ffff7951e85 in user_eval_inner (program=<value optimized out>, codevec=<value optimized out>) at vm.c:1288 #10 0x00007ffff7952c3e in apply_rec (vm=<value optimized out>, proc=<value optimized out>, nargs=<value optimized out>) at vm.c:1384 #11 0x00007ffff795362f in safe_eval_wrap (kind=2, arg0=0x7ffff7c61d60, args=0x7edf00, cstr=0x0, env=<value optimized out>, result=0x7fffffffe430) at vm.c:1531 #12 0x00007ffff799892a in Scm_Load (cpath=<value optimized out>, flags=0, packet=0x7fffffffe760) at load.c:481 #13 0x0000000000402ac3 in main (argc=3, argv=<value optimized out>) at main.c:508 (gdb)
- Shiro(2011/05/29 18:48:32 PDT): クラスオブジェクトのchange-classは、 そのクラスのインスタンスへ影響を伝えるのが困難なため、禁止ということに してたような覚えがあります。なのでここではどこかでエラーを投げるのが あるべき動作ですね。
- Shiro(2011/06/08 18:23:20 PDT): 思ったよりややこしい: Gauche:MOP:クラスオブジェクトのchange-class
create-directory-treeのspecに文字列・シンボルを指定するとエラー
teppey (2011/04/04 08:34:44 PDT): GaucheRefj:create-directory-treeによると、spec引数には文字列やシンボルを指定できますが、エラーになります。
gosh> (use file.util) #<undef> gosh> (create-directory-tree "/tmp" "foo") *** ERROR: wrong number of arguments for #<closure ensure-file> (required 2, got 1)
do-fileへの引数が足りないようでした。
diff --git a/libsrc/file/util.scm b/libsrc/file/util.scm index 516433e..10e0188 100644 --- a/libsrc/file/util.scm +++ b/libsrc/file/util.scm @@ -313,7 +313,7 @@ [else sys-chown])) (define (walk dir node do-file do-dir) (match node - [[? name?] (do-file (mkpath dir node))] + [[? name?] (do-file (mkpath dir node) #f)] [([? name? n] . args) (receive (opts content) (collect-options args) (if (list? content)
- Shiro(2011/06/01 01:57:03 PDT): Fixed (5607882)
vmの命令と対応する関数をdefineで上書きしても、vmの命令としてコンパイルされる
ryoakg2011/01/14 06:38:52 PST
(define-module mod (export foo) (define (+ a b) 4) (define (foo a b) (+ a b)) ) (import mod) (disasm foo)
を、ファイルに書いて実行すると
% gosh d.scm CLOSURE #<closure foo> main_code (name=foo, code=0x83edbe0, size=3, const=0, stack=0): args: #f 0 LREF1 ; a 1 LREF-VAL0-NUMADD2(0,0) ; (+ a b) 2 RET
となって、自分で定義した + でなくて vm の命令の方にコンパイルされてしまいます。(実のところ試したのは、+ と * だけで、ハッキリと vmの... とハッキリ言えないのですが、多分そうじゃないかなぁと思います)
また
(define (+ a b) 4) (define (foo a b) (+ a b)) (disasm foo)
や
(define-module mod (export foo) ) (select-module mod) (define (* a b) 4) (define (foo a b) (* a b)) (select-module user) (import mod) (disasm foo)
の様に、define-module の外に書いた場合は、問題ない様子でした。
- Shiro(2011/01/14 15:09:08 PST): VMの命令に対応するものだけでなく、インライン展開
されるものは全てそうなります。また、define-moduleの中に書いた場合だけでなく、
beginで囲んだ場合も同様に元の定義がインライン展開されます。
これは今のところトップレベルフォームごとにコンパイルして 実行するというGaucheの性質から来る「仕様」なのですが (トップレベルでの再定義が コンパイルに及ぼす影響はr5rsでは未定義。r6rsでは再定義自体禁止)、 beginの有無で結果が変わるのも気持ち悪いってば気持ち悪いですね。
これで具体的な問題が生じていたら教えてください。対応の参考にします。
今はマクロ展開とインライン展開をひとつのパスで行ってるんですが、対応するとしたら それを2パスに分けて、マクロ展開後にトップレベルの定義をスキャンして、見つかった ものについてはインライン展開を抑制する、ということになるかなあ。
- Shiro(2011/01/14 15:55:35 PST): あ、今気づいたんだけどこの「仕様」、 define-record-typeの更なる最適化の邪魔になるかも。もしそうだとしたら 近いうちに直すかもしれません。
- ryoakg(2011/01/14 17:58:43 PST): 遊びで書いていただけなので、具体的にといわれると、困り度は低いのですが。以下の様な感じです(長いので不要な部分は削りました)
(define-module deriv (use util.match) (export deriv) (define variable? symbol?) (define (+ a b) (cond [(and (number? a) (number? b)) ((with-module scheme +) a b)] [(eqv? 0 a) b] [(eqv? 0 b) a] [else `(+ ,a ,b)])) (define (* a b) (cond [(and (number? a) (number? b)) ((with-module scheme *) a b)] [(or (eqv? 0 a) (eqv? 0 b)) 0] [(eqv? 1 a) b] [(eqv? 1 b) a] [else `(* ,a ,b)])) (define (deriv var exp) (define (core exp) (match exp [(? number? _) 0] [(? variable? _) (if (eq? exp var) 1 0)] [(x) (core x)] [('+ a b) (+ (core a) (core b))] [('* a b) (+ (* a (core b)) (* (core a) b))] [else (format #t "err. ~s" exp)])) (core exp)) ) (import deriv) (deriv 'x 'x) ; いいらしい (deriv 'x '(x)) ; いいらしい (deriv 'x '(+ x 3)) ; いいらしい (deriv 'x '(* x y)) ; #<module scheme> の * になっているっぽい
やりたかった事としては、http://mitpress.mit.edu/sicp/full-text/book/book-Z-H-16.html#%_sec_2.3.2 で、make-sum, make-product などありますが、僕の脳の処理能力が低いので、こんなの書いていたらとても頭がついていけないので、+, * に置き換えようとしていました。
でも、インタプリタでこれをやると、元々の +, * とゴチャゴチャになりそうなので、モジュールを作って、deriv だけ export しようと思ったのです。
一般的に考えると、電卓かそれ以上のものを作ろうとした場合に、僕と同じ様な思考回路の人は困るのかもしれません。
- Shiro(2011/01/14 18:49:11 PST): なるほど。確かにこういうふうに書けるとうれしいですね。 考えてみます。
HTTPレスポンスヘッダにContent-Lengthが無い場合、バイナリデータを受け取れない(0.9.1)
2011/01/11 22:35:52 PST
rfc.httpモジュールのhttp-getでバイナリファイルを取りよせたときに レスポンスヘッダにContent-Length行が含まれていなかった場合、 sinkオプションを使ってもレスポンスボディの内容を得ることができません。
receive-body関数内でport->stringを呼んでいるのが原因のようで、 ソースのコメントを読むと過渡的にこのような処理になっているのかもしれないですが 報告しておきます。
- Shiro(2011/01/11 23:11:59 PST): むむ。port->stringは入力がバイナリでも
不完全文字列を返すだけなので差は出ないはずなんですが、
具体的にどういう症状になりますか?
- http-getから帰ってこない
- 内容が空になる、あるいは途中で切れる
- エラーが投げられる
- 2011/01/12 02:37:28 PST: 内容が途中で切れています。バイナリファイルをオープンしてport->stringを呼んでも、同じ位置で途切れていました。
- Shiro(2011/01/12 21:29:05 PST): port->stringは不完全文字列も読めると思い込んで いましたがそうではなかったようです。rev7352で修正しました。
マニュアル typo Adler32
ryoakg2011/01/07 05:35:09 PST http://practical-scheme.net/gauche/man/gauche-refj_153.html http://practical-scheme.net/gauche/man/gauche-refe_153.html
Function: alder32 string :optional checksum
alder32 になっている
- Shiro(2011/01/12 23:48:15 PST): 直しました。
parameterizeを抜ける際にconvert procedureが呼ばれてしまう
Shiro (2011/01/06 04:28:10 PST): Joo ChurlSooによりレポートされたもの。
gosh> (define a (make-parameter 1)) a gosh> (define b (make-parameter 2 number->string)) b gosh> (list (a) (b)) (1 "2") gosh> (parameterize ((a 10) (b 20)) (list (a) (b)) ) *** ERROR: number required: "2" Stack Trace: _______________________________________ 0 after gosh> (list (a) (b)) (1 "20")
現在のGaucheのparameterizeの実装はdynamic-windのbefore/after thunkで パラメータの値を書き換える、つまりこんな感じで展開されてるんだが:
(let ([a_prev #f] [b_prev #f]) (dynamic-wind (lambda () (set! a_prev (a 10)) (set! b_prev (b 20))) (lambda () (list (a) (b))) (lambda () (a a_prev) (b b_prev))))
after thunkの(b b_prev)のところでconverterが起動されちゃうのがまずい。 parameterizeの動作は動的環境の変更だから、抜けるところで完全に元に戻らないと ならないはず。
- Shiro(2011/01/06 14:38:51 PST): 修正済。
binary.pack の unpack で #<eof> が入ったり入らなかったりする
ryoakg2011/01/06 02:29:05 PST: 以下実行例です
(use srfi-1) (use binary.pack) (map (.$ (cute unpack "V*" :from-string <>) (cute string <> #\x00 #\x00 #\x00) integer->char) (iota 16 0 16)) => ((0) (16) (32) (48) (64) (80) (96) (112) (32962 #<eof>) (37058 #<eof>) (41154 #<eof>) (45250 #<eof>) (32963 #<eof>) (37059 #<eof>) (41155 #<eof>) (45251 #<eof>))
途中から #<eof> が入ります。結果が不安定なので多分バグだと思うのですが
元々は
(use gauche.uvector) (use gauche.experimental.app) ($ unpack "V*" :from-string $ u8vector->string $ list->u8vector '(#x01 #x01 #x01 #x01 ; 不完全文字列 #x01 #x01 #x01 #x01 #xd0 #x00 #x00 #x00 #x01 #x01 #x01 #x01 #x01 #x01 #x01 #x01)) => (16843009 16843009)
の様にもう少し長い string を unpack させようとしていたのですが、これだとなぜか "V" 2つ分しか unpack してくれなく、もうすこし自分で調べると、#<eof> が途中で入る場合にこの現象が起っている様に見えました。 "V!*" にしても同じでした。
% gosh -V Gauche scheme shell, version 0.9.1 [utf-8,pthreads], i686-pc-linux-gnu
です。
- Shiro(2011/01/06 14:38:51 PST): 直しました (rev7343)。
いくつかの要因が絡んで動作がわかりづらくなっていました。
- バグ: V*, N*などのunpackルーチンで、終端に達したかどうかを調べるのにpeek-charを
使っていた
- Gaucheでは、次の入力が現在のエンコーディングで無効な文字だと peek-charの動作は不定としているが、現在はたまたま#<eof>が返っていた。 それをunpackルーチンが入力終端と考えた。peek-charを使わないように修正。
- 本来この場合にpeek-charはどう振る舞うべきか、というのは別の問題。まだ手つかず。
- #<eof>問題を解決したとしても、上の実行例で112の続きが128, 144,...とならないのは
なぜか
- これは正しい動作。(string #\x80 #\x00 #\x00 #\x00) はutf-8エンコーディング されるので [#xc2 #x80 0 0 0] というバイト列になる。
- バグ: V*, N*などのunpackルーチンで、終端に達したかどうかを調べるのにpeek-charを
使っていた
Windows7上でMinGW版gauche-install.exeが実行できない
koguro(2010/12/31 20:59:44 PST): Windows7上で、MinGWのshellからgauche-install.exeを実行すると以下のエラーが発生します。
$ /c/Program\ Files/Gauche/bin/gauche-install.exe sh: /c/Program Files/Gauche/bin/gauche-install.exe: Bad file number
http://msdn.microsoft.com/ja-jp/windows/dd883236 で書かれているように、ファイル名にinstallという名前が付いていることから実行時に権限昇格が必要となるようで、正しく動作させるには以下のgauche-install.exe.manifestをgauche-install.exeと同じフォルダに置く必要があります。(MinGWのpatch.exeやinstall.exeも同じようなmanifestファイルを持っています)
<?xml version="1.0" encoding="UTF-8" standalone="yes"?> <assembly xmlns="urn:schemas-microsoft-com:asm.v1" manifestVersion="1.0"> <v3:trustInfo xmlns:v3="urn:schemas-microsoft-com:asm.v3"> <v3:security> <v3:requestedPrivileges> <v3:requestedExecutionLevel level="asInvoker" /> </v3:requestedPrivileges> </v3:security> </v3:trustInfo> </assembly>
なお、上記URLにも書いてありますが、一度実行すると内部でキャッシュされてしまうみたいで、私の環境ではエラー発生後manifestファイルを置いてもエラーは解消されませんでした。ただ、他のフォルダにgauche-install.exeとgauche-install.exe.manifestをコピーしてみたところ、正常に実行できました。
- Shiro(2011/07/25 05:20:45 PDT): 対応しました (498a675)
gauche.partcontのマニュアルの日本語訳が中途半端 (0.9.1)
Shiro(2010/12/13 09:31:30 PST): パラグラフの途中まで訳したところで うっかりコミットしてそのまま忘れていたようです。完全なパラグラフは次のとおりです。
註: 部分継続はふたつのオペレータ、@code{reset}と@code{shift}を使います。 これらは元の論文で導入された名前ですが、既に用語として定着した感があります。 ライブラリ関数名としては一般的に過ぎる名前なので、よりわかりやすい名前を つけようかとも考えたのですが、部分継続を話題にする際にはこれらの用語が 使われるのが普通なので、最終的にこの名前をキープすることにしました。 プログラム中で他の識別子とぶつかったり紛らわしい場合は、モジュールのimport 時に@code{:prefix}インポート指示子(@ref{Using modules}参照)を 次のように使うと良いでしょう。