コマンドの実行データと実行方式
コマンドのクロージャとよく似たデータだが、次のようなデータを考える。
{
"arg0": univ,
"args": [univ*],
"opts": {*:univ?}(propNameFormat="name"),
"additionalEnv": {*:univ?}(propNameFormat="name"),
"input": univ
}
注意:arg0とargsを一緒にしたのがargvだが、argv[0], argv[1:] と分解するのがメンドイので最初から別にしておく。ただし、%1がargs[0]となり番号がずれる。この点では、argv[1]と書いたほうが良い。
このJSONオブジェクトの各プロパティを同名の変数に代入した状況で考える。つまり、%arg0 とかでプロパティ値を参照できる。他に、%cmd にコマンドの名前(環境に依存しないようにフルネームが望ましい)が入っているとする。
このとき、与えられた実行データ(クロージャの変種)のもとでコマンドを実行するには次のようにする。
- %input? | [%additionalEnv, pass] | unclose {call %cmd --0=%arg0? %--*opts %#args}
このパイプラインを説明する。動的なコマンド実行には、このパイプラインが絶対に必要となる。(このパイプラインに相当する単一コマンドを準備してもいいけど。)
unclose
「try-catchの双対となる構造」で説明している。追加する環境変数を表すオブジェクトと標準入力を受け取って、ブロック内を新しい環境変数セットのもとで実行する。
--0=%arg0?
コマンドにarg0を渡すにはこうする。arg0がundefinedだと例外を起こすので、'?'を付けておく。'?'があれば、値としての#'undefinedがarg0に入る。
%--*opts
現在でも、%--foo のような構文が使える。これは、--foo=%foo? と同値だが短く書けて便利。
%obj がオブジェクトを値とする変数として、%--*obj は、%obj をコマンドラインオプションとしてコマンドに渡すことを指示する。%objが空({})なら、オプションが指定されなかったと同じだし、定義されてないオプションと同名のプロパティがあればエラーとなる。定義されている名前でも型エラーは起こりうる。
例えば、%obj が {"safe": true, "default": null} のとき %cmd %--*obj は次のように展開される。
- %cmd --safe=true --default=null
ただし、コマンドラインを文字列として操作するような(危険でまどろっこしい)方法は使わない。データ構造をそのままコマンド・クロージャにコピーする。
なお、%--* と変数名を省略した場合は、%_OPTS が使われる。
%#args
%--*opts と同様だ。%arrが配列を値とする変数のとき、配列のすべての項目がコマンドライン引数として展開される。例えば、%arr が ["hello", "world"] のと、%cmd %#arr は、
- %cmd hello world
%arrが歯抜け配列である場合もサポートする。
なお、%# と変数名を省略した場合は、%_ARGV の1以上のスライスが使われる。%_ARGV の1以上のスライスを %_ARGS とするなら、%#_ARGS と書けるが、%_ARGS は自動的に定義はされない(%_ARGVで間に合うので)。