2008/3/13 の comp.lang.scheme
Gambit-C's FFI and variadic functions - comp.lang.scheme
質問
Gambit-C の ncurses バインディングを書いているんだけど Gambit-C の FFI では printw のような Variadic function はサポートされないんだ。
どうしたらよいだろう?
(注)Variadic という単語が分からなくて調べたら見つかりました。可変長引数の関数のことでした。
, a variadic function is a function of variable arity; that is, one which can take different numbers of arguments.
回答
Scheme は強い value typed、これに対して C は 弱い variable typed なので、Cの可変長引数へのバインディングを安全に提供するのは難しい。(実行時のコストがかかるし安全でない)
だから Scheme で以下のように実装するのはどうだろう?
(printw-int an-int) --> printw("%d",an-int); (printw-float a-float) --> printw("%f",a-float); (printw-string a-string) --> printw("%s",a-string); (define (printw fmt . args) (let loop ((chunks (parse-printw-fmt fmt)) ;; (parse-printw-fmt "abc %d def %s ghi %f klm") ;; --> ("abc " #<fmt-integer> " def " #<fmt-string> ;; " ghi " #<fmt-float> " klm") (args args) (if (null? chunks) (if (null? args) 'nil (error "Too many args")) (loop (rest chunks) (let ((item (first chunks)) (arg (first args))) (cond ((string? item) (printw-string item) args) ((fmt-string? item) (if (string? arg) (printw-string arg) (error "%s expects a string argument")) (rest args)) ((fmt-integer? item) (if (integer? arg) (printw-integer arg) (error "%d expects an integer argument")) (rest args)) ((fmt-float? item) (if (float? arg) (printw-float arg) (error "%f expects a float argument")) (rest args)) ...)))))))
(感想)FFIの話は個人的にタイムリーだ。回答者の指摘の通り、実行時に渡された値の Scheme 上での型を調べて C が期待する型に変換するのは難しそう。
(蛇足)ここ数日の comp.lang.scheme を見ていると Stalin ってのが割と使われているコンパイラなのかな。