UWSCで可変引数を扱う

UWSCで可変引数を扱う方法を考えてみた。


UWSCでは、パラメーターに初期値を与えて省略可にできる。
しかし、この方法で可変引数を実現すると、二つの欠点がある。

  1. 可変個数の最大値が決まってしまう(実用上は問題ないことが多い)
  2. 初期値を適切に設定するのが難しいケースがある(数を渡して解決もできる)

初期値を与える方式

PROCEDURE vprintf(p1=NULL, p2=NULL, p3=NULL, p4=NULL)
	// 略
FEND

NULLを取りえない関数であれば、これで問題ない
もしあらゆる値を取りうる関数ならば、数を渡す

PROCEDURE vprintf(n=0, p1=NULL, p2=NULL, p3=NULL, p4=NULL)
	// 略
FEND

この例では第一引数の分だけ、p?が有効という規約。


が、どうしても最大数は固定となってしまう。
最大数をも可変にしたい場合を考える。

最大数を可変にした方式

追記 2014/12/09
ScriptControlのRunメソッド呼び出しでは、引数15個まででした、、、。
ということで、やむなく最大数固定の修正版を書きました。
UWSCで可変引数を扱う(修正版) - じゅんじゅんのきまぐれ

ScriptControlのRunメソッドが可変引数であることを利用する。
VariableArguments.uws

OPTION EXPLICIT

IFB GET_UWSC_NAME = "VariableArguments.uws" THEN
	DIM test = 56
	vprintf(VA.SC.Run("args", "めっせーじ", test, 17, "b"))
ENDIF

PROCEDURE vprintf(args)
	PRINT args.length
	DIM i
	IF args.length THEN args.Set(0, "書き換えた")
	FOR i = 0 TO args.length - 1
		PRINT "<#TAB>" + args.Get(i)
	NEXT
FEND



MODULE VA
	PUBLIC SC

	TEXTBLOCK _variable_arguments_function
		function args() {
			var ret = arguments
			ret.Set = function(i, val) { this[i] = val }
			ret.Get = function(i) { return this[i] }
			return ret
		}
	ENDTEXTBLOCK

	PROCEDURE VA
		SC = CreateOleObj("ScriptControl")
		SC.language = "JScript"
		SC.AddCode(_variable_arguments_function)
	FEND
ENDMODULE
解説

可変引数の関数は、オブジェクトを一つ受け取る関数として定義する。
(例は、PROCEDURE vprintf(args))
引数の個数は、lengthプロパティ。値の取得・設定は、Get/Setメソッドを利用する。
可変引数の関数を呼び出す際は、VA.SC.Run("args", 「可変個の引数」)を渡す。


原理としては、JScriptの関数が全て可変引数であり、全引数はargumentsオブジェクトに入っていることを利用しています。
argumentsオブジェクトは、Arrayに似て非なるものなので、アクセッサを追加しています。
Arrayの機能を使って載せ替えるという手もあるけど、ま、いいでしょ。