AssociativeArray/OperatorOverloading
Operators
Associative arrays use angle brackets as a "natural" notation. The operators are defined in the demonstration commandlet; they should be defined in a root-ward class so they can be used widely. This is just a proof of concept.
AADemoCommandlet
The commandlet contains the definitions and some demonstration code.
class AADemoCommandlet extends Commandlet; /* The left-angle bracket operator. Returns an AAProxy, a proxy that can be converted either to a string or to a "reference" to a string. The operator parameters are an associative array and the string index into the array. */ final operator(24) AAProxy < (out AssociativeArray A, coerce string index) { local AAProxy aa; aa = new(None) class'AAProxy'; aa.init(A, index); return aa; } // operator < /* The right-angle bracket operator; a postoperator as it finishes an expression with an AAProxy (an associative array generated the proxy). This converts a proxy to an r-value (a string) */ final postoperator string > (AAProxy proxy) { return proxy.r_value(); } // operator > /* The combined right-angle bracket and assignment operator. It takes the rhs of the operator (a string) and assigns the value to the appropriate slot in the array. This operator converts the AAProxy into an l-value. */ final operator(24) string >= (AAProxy A, coerce string value) { return A.l_value(value); } // operator >= /* The left-angle bracket for use with AssociativeArrayIterator. Note that it returns an AAProxy permitting the > and >= operators defined above to be used on the right end of an iterator expression. */ final preoperator AAProxy < (AssociativeArrayIterator ai) { local AAProxy aa; aa = new(None) class'AAProxy'; aa.init(ai.getCollection(), ai.getIndex()); return aa; } // operator < /* preoperator increment for iterators. No postoperator is defined because it requires creation of a temporary iterator and I didn't feel like worrying about where the spare copy went. */ final preoperator AssociativeArrayIterator ++(out AssociativeArrayIterator ai) { ai.next(); return ai; } // operator ++ /* iterator's not equality comparison. Equality would be easy to write and this could have been defined in terms of equality but the extra function call seemed a waste (given script speed). */ final operator(26) bool != (AssociativeArrayIterator lhs, AssociativeArrayIterator rhs) { return !lhs.same(rhs); } /* Main function of the commandlet. Ignores its input arguments and demonstrates the use of the associative array operators and iterators. */ function int main(string args) { local AssociativeArray A; local AssociativeArrayIterator i; // construct a new, initially empty associative array A = new(None) class'AssociativeArray'; // populate the array with some values; note that the ">=" is one symbol A<"fish">= "shark"; A<"dog">= ("new"$"found"$"land"); // parentheses are required A<"cat">= "persian"; A<"cow">= "zebu"; A<"bird">= "penguin"; A<"rodent">= "gerbil"; // i iterates across the elements within the associative array // first and second return the key and value portions of an associative // array entry for(i = A.begin(); i != A.end(); ++i) { log("A<" $ i.first() $ "> = " $ i.second()); } // modify the contents of the associative array; put each entry inside // curly braces for(i = A.begin(); i != A.end(); ++i) { <i>= ("{" $ i.second() $ "}"); } for(i = A.begin(); i != A.end(); ++i) { log("<i> = "$<i>); // this will just print out the values in the array } // if an element doesn't exist, returns "" without inserting an item log("No such item: A<\"gamma\"> = "$A<"gamma">); return 0; } // main //AADemoCommandlet
AAProxy
The demonstration uses an AAProxy type. This type tracks a location in an associative array and permits that entry to be returned or set. It is simply a reference some associative array and a string index. This is enough informatino to either insert or retrieve a value in the associative array.
class AAProxy extends Object; /* AAProxy - Associative Array proxy class. The proxy is returned by the < indexing operator and can be converted to either a l-value or an r-value (okay, almost an r-value; the proxy can set the underlying element in the Associative Array). */ /* An AAProxy serves as in the stead of an associative array element. To be able to simulate an r-value, the array and the index must both be kept in the proxy. Both are private to limit access to the three interface functions. */ var private AssociativeArray A; var private string ndx; /* init - initializes the proxy object with an associative array and an index. */ function init(AssociativeArray AA, string index) { A = AA; ndx = index; } // init /* Read the value from the given location in the associative array. Effectively convert the proxy to an r-value representing the given element in the associative array.*/ function string r_value() { return A.lookup(ndx); } // r_value /* Set the value represented by the proxy to the value provided as a parameter to this function. Effectively convert the proxy to an l-value representing the given element in the associative array. */ function string l_value(string v) { A.insert(ndx, v); return v; } // l_value