Gauche:WishList

Gauche:WishList


MinGWでc-wrapperを使いたい

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に作ってもよいでしょうか。

object-applyに登録したメソッドを削除したい

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 が別ものなのかとは思いますが、はまりそうではありました。

Windowsのコマンドプロンプトで日本語(CP932)の表示と入力

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
(ただし、まれにキー入力を受け付けなくなることがあります。。。)

以前からある要望だと思うので、ひとつの方法ということで挙げておきます。

uri-encode の大文字、小文字

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 にオプショナル引数を
付ければ良いとならないのが面倒そうです。

選択子としては、

なのかと思いました。

<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 などするときの全順序な場合とそうでない場合?)

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共通)」に譲る)。

こうすれば良いという方法は思いつかないが、案としては

問題点(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回やった方が良い気がする。

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 については、何も考えつかない

問題設定について

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 の実装だとエラーが何も表示されないで終わってしまいます。できれば、フラグ指定でもいいのでエラー表示を行うようにしてほしいです。

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 ?)。

文字列の \x, \u, \U 記法

文字列の \u 記法等を R6RS と同様に ; をつけて \u3000; のようにもできると嬉しいです(SXML を書いていたら普通の文字列に紛れてしまったので)。

letrec*

Rui(2006/11/15 01:23:04 PST): letrec*を提供してほしいです。現状のGaucheのletrecがletrec*の動作になっているので、名前を定義するだけでよいかと。

useしているのに使っていないモジュールを指摘する機能

Rui(2006/10/13 04:56:33 PDT): モジュールをuseしているのに、エクスポートしている束縛を使っていないとき、それを指摘してくれる機能があるとよいです。gauche.testのtest-moduleが警告を出力してくれるとうれしいかも。

tree->string and string interpolation

2006/10/12 03:17:18 PDT: string interpolation で例えば ,@a 辺りを (tree->string a) に 展開してくれると、短く書けてよいかも。

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

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)

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)))))))

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が特定の戻り値を返す、みたいな 方法が現実的な線かもしれません。条件がかかるのが醜いですが…

Shiro: Port回りは0.9までに直さなくちゃならない項目の筆頭なので、 たぶん0.8.6後に本格的に取り組むことになると思います (srfi-68の進行も 横目で見てないとならないんですが)。そこで対応を考えたいと思います。

any, every for gauche.collection

after-gc-hook

Shiro: これはそう簡単ではないんですよ。=> 議論はGauche:Schemeコードのファイナライザ

weak-hash-table

export-all*

export-allする際に、頭が%のものはexportしないようなexport-all*が欲しいです。prefixが設定できればなおいいのですが、%固定で充分だと思います。今作っているモジュールのpublic/private数が62/3なので大変なことになってまして・・・。--hira(2004/03/17 02:35:42 PST)

add-load-path

     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

More ...