COMPILE_R7RS は処理系に関わらず「そういうもの」なのでセキュリティ的な穴とはあまり感じられないんですが、(1)うっかり試験的に設定していたのを忘れて、Gaucheのcompile-r7rsを起動してるつもりがそうなってなくてトラブルシューティングに悩む、というのと(2)suidプログラムで実行してたら確かに穴になる、という点はあると思います。前者については「違うプログラムを実行するよ」というメッセージがあると親切ですし、後者についてはsuid実行時に禁止するのはありと思います。
compile-r7rsはユーザがconfigureでオプション指定しないとインストールされないですし。PATHによりマネージするなりした方が何をやってるか明確ではある。
gauche-compile-r7rsを機動するんですから、わかっててやる人ですよね。今考慮すべきは一般のR7RSユーザでは。
結構複雑な問題なので、 https://github.com/shirok/Gauche/issues/1043 でトラックします。とりあえず、「一時的にCOMPILE_R7RSを設定したのを忘れててハマる」というパターン防止のためにwarningは出すようにしました。
srfi 241 がPortableなPattern matchingのようですが実装される可能性ありますでしょうか。 初心者なんですが、できるだけPortableなコードを心がけていて、srfi 241を知りました。
はじめて書き込みします。よろしくお願いします。 現在はパターン内に同じ変数を書くとエラーとなりますが、 これを同じ変数のところは同じ値の場合にマッチするようにしてほしいです。
動作イメージ
gosh> (match '(1 1 1) ((x x x) "same") (_ "different")) "same" gosh> (match '(1 1 2) ((x x x) "same") (_ "different")) "different"
対応している他言語の例
In contrast to Haskell, patterns may contain repeated variables (other than the anonymous variable), i.e., they may be non-linear.
https://agraef.github.io/pure-docs/pure.html#non-linear-patterns-and-syntactic-equality
Egison では1つのパターン内で同じ変数が複数現れるパターンを記述することができます。
MatchComp is Christian Queinnec's pattern-match compiler code for compiling non-linear, second-order patterns on S-Expressions.
https://www.cs.cmu.edu/afs/cs/project/ai-repository/ai/lang/scheme/code/match/matchcmp/0.html
そこで0.9.10_pre1のutil.matchでの変更案の最低限のたたき台を書いてみました。
--- old/libsrc/util/match.scm 2020-07-30 20:16:34.911257510 +0900
+++ new/libsrc/util/match.scm 2020-07-31 23:32:13.146314742 +0900
@@ -20,6 +20,7 @@
match:every
match:error))
(select-module util.match)
+(define non-linear #t)
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; Pattern Matching Syntactic Extensions for Scheme
@@ -455,9 +456,10 @@
(define (bound p a k)
(cond
((eq? '_ p) (k p a))
+ ((and (identifier? p) (memq p a))
+ (if non-linear (k p a)
+ (match:syntax-err pattern "duplicate variable in pattern")))
((identifier? p)
- (when (memq p a)
- (match:syntax-err pattern "duplicate variable in pattern"))
(k p (cons p a)))
((and (pair? p) (equal? 'quote (car p)))
(k p a))
@@ -645,6 +647,8 @@
See the ``Keyword and symbol integration'' section \
of the manual for the details.\n" p x)
(emit `(equal? ,e ,p) sf kf ks))
+ ((and non-linear (identifier? p) (assq p v))
+ (emit `(equal? ,e ,(cdr (assq p v))) sf kf ks))
((identifier? p) (set! v (cons (cons p e) v))
(ks sf))
((null? p) (emit `(null? ,e) sf kf ks))
マクロの展開結果で、(equal? (cadr e) (car e))と(equal? (caddr e) (car e))の処理が入っていることが確認できます。
gosh> (macroexpand '(match e ((x x x) x))) (let ((#:G94 (lambda.0 (x) x))) (if (and (pair? e) (pair? (cdr e)) (equal? (cadr e) (car e)) (pair? (cddr e)) (equal? (caddr e) (car e)) (null? (cdddr e))) (#:G94 (car e)) (match:error e)))
エラーとしていた場合の挙動を変更するものであり、これまで動いていたコードに対する影響はないと思います。 が、念のため、変数non-linearを#fにすると従来のエラーとする挙動に戻るようにしてあります。 ご検討よろしくお願いします。
match (Gaucheがベースにしているもの)をAlex Shinnがsyntax-rulesで書き直したものが議論されています。
そちらでは同一変数への束縛がサポートされているので、
このsrfiがfinalizeされたら合わせてサポートします。
実装はsrfi-204の参照実装を持ってくるか、er-macroで書き直すかも。
Wrightの元ソースは自分自身で展開されたコードを含んでいて手がつけにくいので。
kobapan?2017/12/24 19:44:21 UTC
(http-get "localhost:8012" "/" :Authorization #f)
としたときに送信されるヘッダが、
host: localhost:8012 user-agent: gauche.http/0.9.5 authorization: #f
となるのにとまどいます。
host: localhost:8012 user-agent: gauche.http/0.9.5
となって欲しい。
Kei(2015/01/19 20:26:09 UTC): Chibiが.sldをR7RSのライブラリに採用したので、それがデファクトになりつつあるのですが、Gaucheには簡単に拡張子を追加するオプションがなくて毎回不便です。
$ gosh -r7 -e '(set! *load-suffixes* (cons ".sld" *load-suffixes*))'
と毎回打ってもいいのですが、オプション一発で追加(prependの方が使いでがありそう)できると嬉しいです。
h(2014/09/07 14:07:57 UTC):Gauche 用 の c-wrapper を MinGW (32bit) 上で動くように改造してみました。
https://github.com/Hamayama/c-wrapper-mg
libffi-3.1がMinGWに対応しているようだったので、試行錯誤の末どうにか動かすことができました。
ただ、libffi-3.1そのままではだめで、修正が必要でした。
あと、Gaucheでちょっとしたプログラムを作ったときに、実体はGitHub等に置くとして、
こういうのを作ってみましたと報告できるような、「Gauche:作品集」みたいなページを
このWikiに作ってもよいでしょうか。
h(2014/08/26 11:20:48 UTC):一時的にobject-applyにメソッドを追加して、作業後に元に戻すことは可能でしょうか。
例えば、以下のようなケースです。
(define-method object-apply ((x <top>) . args) (cons x args)) ;; (リストの先頭が手続きでなくてもよい世界) (print (1 2 3 4 5)) (print (apply + (1 2 3 4 5))) ;; (以後は元の世界に戻したいのだけど。。。) (?????)
h(2014/08/26 20:42:50 UTC):methodsスロット使って以下のようにしてみました。一応戻せたようですが。。。
;; object-applyのメソッドを保存 (define mold (slot-ref object-apply 'methods)) ;(print mold) ;; object-applyにメソッドを追加 (define-method object-apply ((x <top>) . args) (cons x args)) ;; ***** リストの先頭が手続きでなくてもよい世界 ***** (print (1 2 3 4 5)) (print (apply + (1 2 3 4 5))) ;; ***** 元の世界に戻す ***** ;; object-applyのメソッドを復帰 (define mnow (slot-ref object-apply 'methods)) ;(print mnow) (for-each (lambda (m) (delete-method! object-apply m)) mnow) (for-each (lambda (m) (add-method! object-apply m)) (reverse mold))
h(2014/08/27 07:19:49 UTC):ありがとうございます。メソッドを取り出してdで表示してみると、
required, optional, specializers というスロットがあったので、これらチェックしてやってみます。
ひとつ気になったのが、
(define-method object-apply ((x <top>) . args) (cons x args))
を、
(define-method object-apply ((x <top>)) x)
と変更しても、specializers の値が同じ (<top>) になったことです。
ユーザリファレンスの define-method の説明によると、
前者は (<top> . <top>) になりそうな感じでした。
ただ、optional は、前者が #t で後者が #f なので、区別は可能です。
そして、両方実行するとちゃんと別々のメソッドとして登録されました。
h(2014/08/28 20:30:20 UTC):一応できたものが以下になります。
https://github.com/Hamayama/noqlist
(実験用という位置づけです)
h(2014/08/30 03:57:51 UTC):同様の方法で「Gauche:数式の中置記法」を参考に中置記法をモジュールにしてみました。
https://github.com/Hamayama/numinfix
rest引数の件は了解しましたが、ユーザリファレンスの「7.4 ジェネリックファンクションとメソッド」の
define-method のところで specializers: (<myclas> <top> . <top>) という例がのっており、
specializers のみでメソッドを特定できるように読めます。
多分この記述の specializers と、メソッドのスロットの specializers が別ものなのかとは思いますが、はまりそうではありました。
h(2014/06/04 14:40:02 UTC):Windows 8でもコマンドプロンプトはCP932がデフォルトのようです。
それで、こちらのページに文字コードを変換しながら入出力するサンプルが載っていました。
http://saito.hatenablog.jp/entry/2014/04/14/104006
リダイレクトがエラーになるので判定を追加してモジュールにしてみました。
https://github.com/Hamayama/msjis
(ただし、まれにキー入力を受け付けなくなることがあります。。。)
以前からある要望だと思うので、ひとつの方法ということで挙げておきます。
ryoakg(2013/08/22 12:29:35 UTC):
要望なのか何なのか分からない話で、もうしわけないですが、
uri-encode でエンコードされる結果を、大文字に固定するか、選べる様にした方がいいのかな? という話です。
状況としては、
https://images-na.ssl-images-amazon.com/images/G/09/associates/paapi/dg/index.html?rest-signature.html
のリクエストを作っていました。
その中で uri-encode を使ったのですが、
最初うまくいかなくて
結果として uri-encode の中で使われていた
format の x を X に変えるとうまくいきました。
Gauche のバージョンは 0.9.3.3 です。
あまりwebプログラミングしないので、こういう事がよくあるのか分からないのですが。
以下の様にググってみると
https://www.google.co.jp/search?q=uri+OR+url+%E3%82%A8%E3%83%B3%E3%82%B3%E3%83%BC%E3%83%89+%E5%A4%A7%E6%96%87%E5%AD%97+%E5%B0%8F%E6%96%87%E5%AD%97&ie=utf-8&oe=utf-8&hl=ja
どっちでも良いけど、大文字の方がいいみたいな感じですね。
また、http://dev.worksap.co.jp/Members/t_tanaka/2011/03/30/dotnet-java-urlencode/
に RFC3986 の話が引用してありました。
なので、多分長期的には、大文字に固定するか、
大文字をデフォルトにするかにした方がいいのだと思います。
(小文字の方が良い場面は分からないですが)
ただそうすると uri-encode の全ての出力に影響するので、
突然切替えるのも心配な気もします。
一応、プログラム全体は以下です。
amazonに登録して、idもらわないと動かせないので、
すぐ試せなくて面倒な感じなのですが。
(use gauche.experimental.app)
(use gauche.experimental.lamb)
(use srfi-13 :only (string= string<))
(use rfc.http)
(use rfc.hmac :only (hmac-digest-string))
(use rfc.sha :only (<sha256>))
(use rfc.base64 :only (base64-encode-string))
(require "rfc/uri")
(with-module rfc.uri
(define (uri-encode :key ((:noescape echars) *rfc3986-unreserved-char-set*))
(let loop ((b (read-byte)))
(unless (eof-object? b)
(if (and (< b #x80)
(char-set-contains? echars (integer->char b)))
(write-byte b)
(format #t "%~2,'0X" b))
(loop (read-byte)))))
)
;;; 以下3つは、事前にアカウント登録が必要
;;; https://images-na.ssl-images-amazon.com/images/G/09/associates/paapi/dg/index.html?CHAP_GettingSetUp.html
(define *AWS-access-key-id* "")
(define *secret-key* "")
(define *associate-tag* "")
(define *AWS-server* "webservices.amazon.co.jp")
(define *API-version* "2011-08-01")
;;; とりあえず全部固定で
(define (make-param-list keyword)
(define fixed-param-list
`(;; fixed
("AWSAccessKeyId" ,*AWS-access-key-id*)
("Service" "AWSECommerceService")
("Version" ,*API-version*)
("AssociateTag" ,*associate-tag*)
("Timestamp" ,($ sys-strftime "%FT%TZ" $ sys-gmtime $ sys-time))
;; function: https://images-na.ssl-images-amazon.com/images/G/09/associates/paapi/dg/index.html?CHAP_OperationListAlphabetical.html
("Operation" "ItemSearch")
;; return values: https://images-na.ssl-images-amazon.com/images/G/09/associates/paapi/dg/index.html?CHAP_ResponseGroupsList.html
("ResponseGroup" "ItemAttributes")
;; arguments: https://images-na.ssl-images-amazon.com/images/G/09/associates/paapi/dg/index.html?CHAP_OperationListAlphabetical.html
("SearchIndex" "Books")
("Keywords" "computer")
))
fixed-param-list)
(define (make-sigature params)
($ base64-encode-string
$ (cut hmac-digest-string <> :key *secret-key* :hasher <sha256>)
$ string-join `("GET" ,*AWS-server* "/onca/xml" ,(http-compose-query #f params))
"\n"))
(define (make-uri)
(let1 params ($ (cut sort <> (^(a b) (string< (car a) (car b)))) $ make-param-list "dummy")
(http-compose-query "/onca/xml" `(,@params ("Signature" ,(make-sigature params))))))
;;; $ firefox `THIS.scm`
;; (print #`"http://,|*AWS-server*|,(make-uri)")
(receive (status headers body) ($ http-get *AWS-server* $ make-uri)
(unless (string= status "200")
(print status)
;; (exit 1)
)
(print body))
大文字と小文字を切替えられる様にする場合の話ですが、
上のプログラムでは直接 uri-encode 使っていなくて、
http-compose-query の中で使っているので、
単純に uri-encode にオプショナル引数を
付ければ良いとならないのが面倒そうです。
選択子としては、
なのかと思いました。
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 などするときの全順序な場合とそうでない場合?)
object-equal? メソッドでできないかな、
とやってみたらできませんね。compareが入ってないとobject-equal?も呼ばれないのか。
object-equal? を呼ぶようにしてしまうという手がひとつありますが、
この問題に関してはハッシュテーブルで比較関数とハッシュ関数をカスタマイズできるように
する、という方が根本的な解決になりそうだと思います。
(object-equal? のカスタマイズはグローバルな効果を持つので、
本来はクラスを提供する人が同時に提供すべきで、ユーザが後付けで定義するものではない。)
ryoakg2011/01/09 20:40:46 PST 言いたい事が2点ありますが、分けて書いても、混ぜて書いても、うまく書けそうにないですが、とりあえず混ぜて書きます。
現状(rev7345)
gosh> (unpack "VVV" :input (open-input-string "")) (#<eof> #<eof> #<eof>)
の様に入力が半端な部分だけに #<eof> が入る様になっている。これを #<eof> だけを返す様にして欲しい(リストに入れない)。
gosh> (unpack "VVV" :from-string "aaaabbbbcc") (1633771873 1650614882 #<eof>)
の様に入力が半端な部分だけに #<eof> が入る様になっている。私見では、これはエラー処理が面倒に思える(理由は下の「問題点(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) の様に使っているが、引数の組合せや数は何でもいい)
2つ上のプログラム辺の様に、エラーの箇所毎に分岐するなら (unpack "V") を3回やった方が良い気がする。
(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 については、何も考えつかない
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の実装はまだ変わると思うのであてにしないで欲しいのですが 方針としてはこんなとこです。
koguro(2008/10/04 03:03:14 PDT): report-error が undocumented なのでそもそも使っていいのか分からないのですが、別スレッドで REPL を実行しているときに report-error でエラーを表示したいときがあります。ところが、スレッド内では VM の defaultEscapeHandler が何もしない処理(thread_error_handler) になってしまっているため、現在の report-error の実装だとエラーが何も表示されないで終わってしまいます。できれば、フラグ指定でもいいのでエラー表示を行うようにしてほしいです。
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 ?)。
文字列の \u 記法等を R6RS と同様に ; をつけて \u3000; のようにもできると嬉しいです(SXML を書いていたら普通の文字列に紛れてしまったので)。
Rui(2006/11/15 01:23:04 PST): letrec*を提供してほしいです。現状のGaucheのletrecがletrec*の動作になっているので、名前を定義するだけでよいかと。
Rui(2006/10/13 04:56:33 PDT): モジュールをuseしているのに、エクスポートしている束縛を使っていないとき、それを指摘してくれる機能があるとよいです。gauche.testのtest-moduleが警告を出力してくれるとうれしいかも。
2006/10/12 03:17:18 PDT: string interpolation で例えば ,@a 辺りを (tree->string a) に 展開してくれると、短く書けてよいかも。
===================================================================
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)))))
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))))
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
genstubのdefine-cclassでオブジェクトを比較する関数を指定できるようになるとうれしいです。
koguro(2006/04/08 18:11:41 PDT): stub用のAPIでlong doubleとScmBignumとを変換するScm_MakeBignumFromLongDoubleとかScm_BignumToLongDoubleがあるとうれしいです(これがあるとc-wrapperでlong double対応ができるので)。
rfc.httpのhttp-get, http-put, http-postが認証に対応してくれるといいですね。401を受けたら、自分で特にハンドルしなくてもAuthorizationヘッダつきのリクエストを再送信してほしいです。
いつもlet-valuesとかを使うときに「あれっ、SRFIの何番だったけ?」と悩んでしまうので、(use srfi)とかするとsrfi-*のモジュールを全部読み込んでくれるとうれしいです。--koguro(2005/11/23 02:43:28 PST)
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)))))))
(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)))
ソケットに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が特定の戻り値を返す、みたいな 方法が現実的な線かもしれません。条件がかかるのが醜いですが…
Shiro: Port回りは0.9までに直さなくちゃならない項目の筆頭なので、 たぶん0.8.6後に本格的に取り組むことになると思います (srfi-68の進行も 横目で見てないとならないんですが)。そこで対応を考えたいと思います。
Shiro: これはそう簡単ではないんですよ。=> 議論はGauche:Schemeコードのファイナライザ
export-allする際に、頭が%のものはexportしないようなexport-all*が欲しいです。prefixが設定できればなおいいのですが、%固定で充分だと思います。今作っているモジュールのpublic/private数が62/3なので大変なことになってまして・・・。--hira(2004/03/17 02:35:42 PST)
(define-syntax define-public
(syntax-rules ()
((_ (f . args) . body)
(begin
(define (f . args) . body)
(export f)))
((_ i v)
(begin
(define i v)
(export i)))))
(define-macro (export-all-but% name)
(define (filter-publics name)
(define env (module-table (find-module name)))
(define (public? key) (not (eq? (~ (symbol->string key) 0) #\%)))
(filter public? (hash-table-keys env)))
`(export ,@(filter-publics name)))
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