UWSCで連想配列を配列にする

UWSC連想配列(HASHTBL)は、配列に入れられない。
関数の返り値にもできない。
これが、たま〜に、もどかしい。
ということで、考えてみた。



とりあえず結論

javascriptでやりますか。
HashObj.uws

OPTION EXPLICIT

IFB GET_UWSC_NAME = "HashObj.uws" THEN
	DIM pets = HashObj.Create(TRUE), i
	pets.Set("Brown", "Dog")
	pets.Set("Black", "Cat")
	PRINT "I love " + pets.Get("Brown")
	IF pets.Exists("Brown") THEN PRINT "Buy dog foods."
	IF MSGBOX("Is Black alive?", BTN_YES OR BTN_NO) = BTN_NO THEN ret = pets.Remove("Black")
	FOR i = 0 TO pets.Length() - 1
		PRINT pets.Key(i) + " " + pets.Val(i)
	NEXT
	pets.RemoveAll()

	// 配列化試験
	DIM d[9]
	FOR i = 0 TO LENGTH(d) - 1
		d[i] = HashObj.Create()
		d[i].Set(1, "test")
	NEXT
	FOR i = 0 TO LENGTH(d) - 1
		IF d[i].Get(1) <> "test" THEN PRINT "NG: d[" + i + "].Get(1): " + d[i].Get(1)
		d[i].RemoveAll()
	NEXT

	HashObj.Dispose()
ENDIF


MODULE HashObj
	DIM _sct

	TEXTBLOCK _JS_SRC
		var HashObj = function(bcase, bsort) {
			this._keys = new Array()
			this._case = bcase
			this._sort = bsort
			this.KeyConv = function(key) {
				var ret = key
				if(this._case == 0 && (typeof key == "string" || key instanceof String)) {
					ret = key.toUpperCase()
				}
				return ret
			}
			this.Get = function(key) {
				return this[this.KeyConv(key)]
			}
			this.Set = function(key, val) {
				var n = this.KeyConv(key)
				for(var i = 0; i < this._keys.length; i++) {
					if(this.KeyConv(this._keys[i]) == n) {
						this[n] = val
						n = ""
					}
				}
				if((typeof n != "string" && !(n instanceof String)) || n.length > 0) {
					this._keys[this._keys.length] = key
					if(this._sort == 1) this._keys.sort()
					this[n] = val
				}
			}
			this.Key = function(index) {
				return this._keys[index]
			}
			this.Val = function(index) {
				return this[this.KeyConv(this.Key(index))]
			}
			this.Length = function() {
				return this._keys.length
			}
			this.Exists = function(key) {
				return (this.KeyConv(key) in this)
			}
			this.Remove = function(key) {
				key = this.KeyConv(key)
				var ret = false
				for(var i = 0; i < this._keys.length; i++) {
					if(this.KeyConv(this._keys[i]) == key) {
						this._keys.splice(i, 1)
						ret = true
					}
				}
				delete this[key]
				return ret
			}
			this.RemoveAll = function() {
				for(var i = 0; i < this._keys.length; i++) {
					delete this[this.KeyConv(this._keys[i])]
				}
				this._keys = new Array()
			}
		}
	ENDTEXTBLOCK

	PROCEDURE HashObj
		_sct = CREATEOLEOBJ("ScriptControl")
		_sct.Language = "JScript"
		_sct.ExecuteStatement(_JS_SRC)
	FEND

	PROCEDURE Dispose()
		_sct.Reset()
		_sct = Nothing
	FEND

	FUNCTION Create(bCase=FALSE, bSort=FALSE, name="HashObj")
		DIM c = 0, s = 0
		IF bCase THEN c = 1
		IF bSort THEN s = 1
		RESULT = _sct.Eval("new " + name + "(" + c + "," + s + ")")
	FEND

ENDMODULE

使い方

以下のような場合

	HASHTBL pets = HASH_CASECARE
	pets["Brown"] = "Dog"
	pets["Black"] = "Cat"
	PRINT "I love " + pets["Brown"]
	IF pets["Brown", HASH_EXISTS] THEN PRINT "Buy dog foods."
	IF MSGBOX("Is Black alive?", BTN_YES OR BTN_NO) = BTN_NO THEN ret = pets["Black", HASH_REMOVE]
	FOR i = 0 TO LENGTH(pets) - 1
		PRINT pets[i, HASH_KEY] + " " + pets[i, HASH_VAL]
	NEXT
	pets = HASH_REMOVEALL

テスト用コードにあるように、以下のように変えます。

	CALL HashObj
	DIM pets = HashObj.Create(TRUE)
	pets.Set("Brown", "Dog")
	pets.Set("Black", "Cat")
	PRINT "I love " + pets.Get("Brown")
	IF pets.Exists("Brown") THEN PRINT "Buy dog foods."
	IF MSGBOX("Is Black alive?", BTN_YES OR BTN_NO) = BTN_NO THEN ret = pets.Remove("Black")
	FOR i = 0 TO pets.Length() - 1
		PRINT pets.Key(i) + " " + pets.Val(i)
	NEXT
	pets.RemoveAll()

HashObj.Createの第一引数がHASH_CASECAREで、第二引数がHASH_SORT。
設定と取得に、Setメソッド/Getメソッドというのがダサいですが、、、。
配列に入れられるし、RESULTにも設定できるので、許してくださいな。