Shammer's Philosophy

My private adversaria

コマンドライン引数をKeywordのように扱うには?その1

&KEY をちょっとだけ使用してみようと思う - Shammerismで、コマンドライン引数をKeywordのように扱うことができないか、というように考えて結局やらずじまいだったが。ちょっといろいろおさらいしつつやってみる。
まず、対象は ClozureCL で、コマンドライン引数を扱うには *command-line-argument-list* を使用する。スクリプトとして動作させるなら、*unprocessed-command-line-arguments* でもよいが、*unprocessed-command-line-arguments* の場合は引数は -- 以降のものになる。まあ、これに合わせて、*command-line-argument-list* でも -- 以降が引数として扱われるようにしてみたい。こうすればいいだけ。

(let ((x (cdr (member "--" *command-line-argument-list* :test 'string-equal))))
...

この場合、x に -- 以降の文字列が格納される。単純に以下のようにするとどういう状態で取得されるかがわかる。

(defun main ()
  (let ((x (cdr (member "--" *command-line-argument-list* :test 'string-equal))))
    (format t "param is ~A, param type is ~A~%" x (type-of x))))

これを

(save-application "test" :toplevel-function #'main :prepend-kernel t)

コンパイルして、./test -- aaa xxx とかやると以下のようになる。

$ ./test -- aaa xxx
param is (aaa xxx), param type is CONS
$

ここでは普通に aaa と xxx は文字列として扱われている。これを :key value というような引数を渡すことで、キーワードとして使用されるようにしたい。

$ ./test -- :key value
param is (:key value), param type is CONS
$

とりあえずはよさげ。本当にキーワードになっているか。キーワードなら、(getf x :key) で value を取得できるはず。そこで、main を以下のように変更する。

(defun main ()
  (let ((x (cdr (member "--" *command-line-argument-list* :test 'string-equal))))
    (format t "param is ~A, param type is ~A~%" x (type-of x))
    (format t "key is ~A." (getf x :key))))

そして、これを再度コンパイルして ./test -- :key value を実行。その結果が以下。

$ ./test -- :key value
param is (:key value), param type is CONS
key is NIL.
$

値を取得できていない。。。:key が渡されていても、Keyword 引数としてではなく単純な文字列として扱われてしまっている、ということと思われる。これを解消するには、:keyword 引数を付与して intern をしてやる、というのでどうか。これはまた今度やってみよう。