Kimura Fuyuki
fuyuk****@hadal*****
2003年 2月 19日 (水) 11:49:38 JST
最初に背景を明かしておきますと、これはDICT(RFC2229)のモジュールを書い ているなかで出てきた問題です。たとえばこのプロトコルにはMATCHというコ マンドがあるのですが、 MATCH database strategy word このうちdatabaseとstrategyにはデフォルト値のようなものがあるので、メソッ ドの引数を省略可能にしたいと思ったわけです。つまり、 (define-method dict-match ((self <dict>) word . args) (let-optionals* args ((database "*") (strategy ".")) のような感じです。で、これを呼び出すコマンドを書く段になって、あれ困っ たな、と。 ちなみにRuby/DICTではmatchメソッドの引数は省略不可です。 DICT#match(database, strategy, word) そのかわり、デフォルト値を定数として提供しています。 DICT::ALL_DATABASES DICT::DEFAULT_MATCH_STRATEGY PerlのNet::Dictでは、databaseだけ省略できます(別に処理するdatabaseを指 定するためのメソッドがある)。 match ( $pattern, $strategy [, @dbs] ) デフォルトのstrategyを使いたければ、"."を指定する必要があります。 At Tue, 18 Feb 2003 14:57:47 -1000 (HST), Shiro Kawai <shiro****@lava*****> wrote: > > optional引数の欠点は、前の方の引数だけ「無指定」という指定が > できないことでしょうね。必然的に、「後のほうの引数は前の方の > 引数が指定されて初めて意味を持つ」といった暗黙の制約がかかります。 そうですね。でも実際には前のほうのオプショナル引数を無指定にしたくなる 場合もあると思います。たとえばstring-joinでgrammerだけ指定したいとか。 Schemeではキーワードが標準ではないので、ちょっと無理をしてオプショナル 引数を使っているということでしょうか。 (脇にそれますが、マニュアルにはstring-joinのdelimのデフォルトが何であ るか書いていません) > どの引数も等分に出てくる可能性がある場合は、キーワード引数で > 渡した方がすっきりするかもしれません。 > > (define (do-something . args) > (let-keywords* args ((host "www.yahoo.com") > (port 80)) > ...)) > > 渡すほうは引数リストを用意してやればいいので。 > > (define (main args) > (let ((do-args '())) > (parse-options (cdr args) > (("h=s" (host) (push! do-args `(,host :host))) > ("p=i" (port) (push! do-args `(,port :port))))) > (apply do-something (reverse do-args)))) 暗黙の前提は「hostを指定することはよくあるがportまで指定することはめっ たにない」だったのですが、やはりこの場合はキーワードを使ったほうがいい ようですね。どうもキーワードはおおげさな感じがして使うのをためらってし まうのですが > どうしてもoptional引数でやるなら、#fが渡された場合は > デフォルト値を使う、みたいなAPIにしておいて、次のように > 2段構えにするとか。 > > (define (do-something . args) > (let-optionals* args ((host #f) > (port #f)) > (let ((host (or host "www.yahoo.com")) > (port (or port 80))) > ...))) > > 欠点: > (1) 「無指定」を指定するための値は有効な値として渡せない > (2) do-somethingが長くなる Common Lispはたしかこんな感じですよね(nilを置いておけば省略したのと同 じ)。あれはあれで便利だと思うのですが、Schemeには似合わない気もします。 > 一般的に使える「無指定」を指定する値があると便利そうなんですが、 > Scheme的には「無指定」値を決めた途端、その「無指定」値を > 引数として受け渡したくなる場面が出て来るので、実際には使えない > んですよね。 私も何度か「ここで未初期化値があれば便利なのに」とか思ったことがあるの ですが、そう簡単に解決するわけがありませんでした。:) -- 木村 冬樹