ultimatepp/uppdev/TopicTest/src.tpp/Tutorial$en-us.tpp
cxl 2e4b276e07 Merge continued
git-svn-id: svn://ultimatepp.org/upp/trunk@10263 f0d560ea-af0d-0410-9eb7-867de7ffcac7
2016-10-04 08:34:39 +00:00

243 lines
19 KiB
C++

TITLE("Tutorial")
TOPIC_TEXT(
"[ $$0,0#00000000000000000000000000000000:Default][l288;i704;a17;O9;~~~.992; $$1,"
"0#10431211400427159095818037425705:param][a83;*R6 $$2,5#3131016247420302412518841"
"7583966:caption][b83;* $$3,5#07864147445237544204411237157677:title][b167;a42;C $"
"$4,6#40027414424643823182269349404212:item][b42;a42; $$5,5#4541300047534217475409"
"1244180557:text][l288;a17; $$6,6#27521748481378242620020725143825:desc][l321;t246"
";C@5;1 $$7,7#20902679421464641399138805415013:code][b2503; $$8,0#6514237545610002"
"3862071332075487:separator][*@(0.0.255) $$9,0#83433469410354161042741608181528:ba"
"se][t4167;C+117 $$10,0#37138531426314131251341829483380:class][l288;a17;*1 $$11,1"
"1#70004532496200323422659154056402:requirement][i416;b42;a42;O9;~~~.416; $$12,12#"
"10566046415157235020018451313112:tparam][b167;C $$13,13#9243045944346046191110808"
"0531343:item1][a42;C $$14,14#77422149456609303542238260500223:item2][*@2$(0.128.1"
"28) $$15,15#34511555403152284025741354420178:NewsDate][l321;*C$7 $$16,16#03451589"
"433145915344929335295360:result][l321;b83;a83;*C$7 $$17,17#0753155046352950537122"
"8428965313:result`-line][l160;t4167;*C+117 $$18,5#8860394944220582595880005322242"
"5:package`-title][{_}%EN-US [s2; Tutorial - NTL in 10 steps&][s5; This tutorial i"
"s as brief as is possible and should serve as basic overview of NTL. See referenc"
"e documentation for further information.&][s3; 1. Vector basics&][s5; Let us star"
"t with a simple [* Vector] of ints&][s7; -|[* Vector<int>] v;&][s5; You can add e"
"lements to the Vector as parameters of the [* Add] method&][s7; -|v.[* Add](1);&]"
"[s7; -|v.Add(2);&][s7; -|v.Add(3);&][s5; To iterate Vector you can use indices&]["
"s7; -|for(int i = 0; i < v.[* GetCount](); i`++)&][s7; -|-|cout << v[* `[]i[* `]]"
" << 'n';&][s16; 1&][s16; 2&][s16; 3&][s5; or iterators&][s7; -|for(Vector<int>"
"`::[* Iterator] q = v.[* Begin](), e = v.[* End](); q != e; q`++)&][s7; -|-|cout "
"<< [* *]q << 'n';&][s16; 1&][s16; 2&][s16; 3&][s3; 2. Vector operations&][s5; "
"You can [* Insert] or [* Remove] elements at random posit")
TOPIC_TEXT(
"ions of Vector&][s7; -|Vector<int> v;&][s7; -|v.Add(1);&][s7; -|v.Add(2);&][s7; "
"-|&][s7; -|v.[* Insert](1, 10);&][s17; v = { 1, 10, 2 }&][s7; -|v.[* Remove](0);"
"&][s17; v = { 10, 2 }&][s5; [* At] method returns element at specified position "
"ensuring that such a position exists. If there is not enough elements in Vector, "
"required number of elements is added. If second parameter of At is present, newly"
" added elements are initialized to this value. As an example, we will create dist"
"ribution of RandomValue with unknown maximal value&][s7; &][s7; -|v.Clear();&][s7"
"; -|for(int i = 0; i < 10000; i`++)&][s7; -|-|v.[* At](RandomValue(), 0)`++;&][s1"
"7; v = { 958, 998, 983, 1012, 1013, 1050, 989, 998, 1007, 992 }&][s5;* [* You ca"
"n apply algorithms on containers, e.g. ]Sort&][s7; -|[* Sort](v);&][s17; v = { 9"
"58, 983, 989, 992, 998, 998, 1007, 1012, 1013, 1050 }&][s3; 3. Transfer issues&]["
"s5; Often you need to pass content of one container to another of the same type. "
"For performance reasons, NTL containers follow [^dpp`:`/`/SourceDoc`/Containers`/"
"pick`_^ default pick semantics], that means that source container is destroyed&]["
"s7; -|Vector<int> v;&][s7; -|v.Add(1);&][s7; -|v.Add(2);&][s7; &][s7; -|Vector<in"
"t> v1 [* =] v;&][s5;^dpp`:`/`/SourceDoc`/Containers`/pick`_^ [^^ now source Vecto"
"r ][C^^ v][^^ is destroyed - picked - and you can no longer access its content. "
"Awful it might seem, it allows using containers as return values. If you really n"
"eed to preserve value of source, you can use ]optional deep copy operator or cons"
"tructor&][s7; -|v [* <<=] v1;&][s5; Now both containers have the same content. Co"
"nstructor form of same operation is distinguished by an additional int parameter&"
"][s7; -|Vector<int> v2(v[* , 0]);&][s3; 4. Client types&][s5; So far we were usin"
"g int as type of elements. In order to store client defined types into the Vector"
" (and the Vector [^dpp`:`/`/SourceDoc`/Containers`/Overview^ flavor]) type must s"
"atisfy [^dpp`:`/`/SourceDoc`/Containers`/Moveable^ moveab")
TOPIC_TEXT(
"le] requirement - in short, it must not contain back-pointers or virtual methods"
". Type must be marked as moveable in order to define interface contract using&][s"
"7; -|struct Distribution : [* Moveable]<Distribution> {&][s7; -|-|string tex"
"t;&][s7; -|-|Vector<int> data;&][s7; -|};&][s5; Now to add Distrubution elements "
"you cannot use Add with parameter, because it requires elements to have default d"
"eep-copy constructor - and Distribution does not have one, as Vector<int> has def"
"ault pick-constructor, so Distribution itself has pick-constructor. It would no b"
"e a good idea either, because deep-copy would involve expensive copying of inner"
" Vector.&][s5; Instead, [* Add] without parameters has to be used - it default co"
"nstructs (that is cheap) element in Vector and returns reference to it&][s7; -|Ve"
"ctor<Distribution> dist;&][s7; -|for(n = 5; n <= 10; n`++) {&][s7; -|-|Distributi"
"on`& d = dist.[* Add]();&][s7; -|-|char h`[20`];&][s7; -|-|sprintf(h, \"Test %d\""
", n);&][s7; -|-|d.text = h;&][s7; -|-|for(i = 0; i < 10000; i`++)&][s7; -|-|-|d.d"
"ata.At(rand() % n, 0)`++;&][s7; -|}&][s7; -|for(i = 0; i < dist.GetCount(); i`++)"
"&][s7; -|-|cout << dist`[i`] << 'n';&][s7; &][s16; Test 5: { 2018, 1992, 2025, 1"
"988, 1977 }&][s16; Test 6: { 1670, 1682, 1668, 1658, 1646, 1676 }&][s16; Test 7"
": { 1444, 1406, 1419, 1493, 1370, 1418, 1450 }&][s16; Test 8: { 1236, 1199, 1245"
", 1273, 1279, 1302, 1250, 1216 }&][s16; Test 9: { 1115, 1111, 1100, 1122, 1192, "
"1102, 1089, 1064, 1105 }&][s16; Test 10: { 969, 956, 1002, 1023, 1006, 994, 1066"
", 1022, 929, 1033 }&][s5; Another possibility is to use AddPick method, which use"
"s pick-constructor instead of deep-copy constructor. E.g. Distribution elements m"
"ight be generated by some function &][s7; -|Distribution CreateDist(int n);&][s5;"
" and code for adding such elements to Vector then looks like&][s7; -|for(n = 5; n"
" <= 10; n`++)&][s7; -|-|dist.[* AddPick](CreateDist(n));&][s5; alternatively, you"
" can use default-constructed variant too&][s7; -|-|dist.Add")
TOPIC_TEXT(
"() = CreateDist(); // alternative&][s3; 5. Array flavor&][s5; If elements do not"
" satisfy requirements for Vector flavor, they can still be stored in Array flavor"
". Another reason for using Array is need for referencing elements - Array flavor "
"never invalidates references or pointers to them.&][s5; E.g., std`::list implemen"
"tation is often non-moveable, so you have to use Array&][s7; -|[* Array]< std`::l"
"ist<int> > al;&][s7; -|for(int i = 0; i < 4; i`++) {&][s7; -|-|std`::list<int>`& "
"l = al.Add();&][s7; -|-|for(int q = 0; q < i; q`++)&][s7; -|-|-|l.push_back(q);&]"
"[s7; -|}&][s3; 6. Polymorphic Array&][s5; Array can even be used for storing poly"
"morphic elements &][s7; -|struct Number {&][s7; -|-|virtual double Get() const = "
"0;&][s7; -|};&][s7; &][s7; -|struct Integer : public Number {&][s7; -|-|int n;&]["
"s7; -|-|virtual double Get() const { return n; }&][s7; -|&][s7; -|-|Integer(int n"
") : n(n) {}&][s7; -|};&][s7; &][s7; -|struct Double : public Number {&][s7; -|-|d"
"ouble n;&][s7; -|-|virtual double Get() const { return n; }&][s7; -|&][s7; -|-|Do"
"uble(double n) : n(n) {}&][s7; -|};&][s5; In this case, elements are added using "
"Add with pointer to base element type parameter. Do not be confused by new and po"
"inter, Array takes ownership of passed object and behaves like container of base"
" type elements&][s7; -|Array<Number> num;&][s7; -|num.[* Add]([* new] Integer(3))"
";&][s7; -|num.Add(new Double(15.5));&][s7; -|num.Add(new Double(2.23));&][s7; -|n"
"um.Add(new Integer(2));&][s7; -|num.Add(new Integer(20));&][s7; -|num.Add(new Dou"
"ble(-2.333));&][s17; num = { 3, 15.5, 2.23, 2, 20, -2.333 }&][s5; Thanks to well"
" defined algorithm requirements, you can e.g. directly apply Sort on such Array&]"
"[s7; -|bool operator<(const Number`& a, const Number`& b)&][s7; -|{&][s7; -|-|ret"
"urn a.Get() < b.Get();&][s7; -|}&][s7; &][s7; .......&][s7; &][s7; -|Sort(num);&]"
"[s17; num = { -2.333, 2, 2.23, 3, 15.5, 20 }&][s3; 7. Bidirectional containers&]"
"[s5; Vector and Array containers allow fast adding and re")
TOPIC_TEXT(
"moving elements at the end of sequence. Sometimes, same is needed at begin of se"
"quence too (usually to support FIFO like operations). In such case, BiVector and "
"BiArray should be used&][s7; -|BiVector<int> n;&][s7; -|n.[* AddHead](1);&][s7; -"
"|n.[* AddTail](2);&][s7; -|n.AddHead(3);&][s7; -|n.AddTail(4);&][s17; n = { 3, 1"
", 2, 4 }&][s7; -|n.[* DropHead]();&][s17; n = { 1, 2, 4 }&][s7; -|n.[* DropTail]"
"();&][s17; n = { 1, 2 }&][s7; -|BiArray<Number> num;&][s7; -|num.AddHead(new Int"
"eger(3));&][s7; -|num.AddTail(new Double(15.5));&][s7; -|num.AddHead(new Double(2"
".23));&][s7; -|num.AddTail(new Integer(2));&][s7; -|num.AddHead(new Integer(20));"
"&][s7; -|num.AddTail(new Double(-2.333));&][s17; num = { 20, 2.23, 3, 15.5, 2, -"
"2.333 }&][s3; 8. Index&][s5; Index is a container very similar to the plain Vecto"
"r (it is random access array of elements with fast addition at the end) with one "
"unique feature - it is able to fast retrieve position of element with required va"
"lue using [* Find] method&][s7; -|[* Index]<string> ndx;&][s7; -|ndx.[* Add](\"al"
"fa\");&][s7; -|ndx.Add(\"beta\");&][s7; -|ndx.Add(\"gamma\");&][s7; -|ndx.Add(\"d"
"elta\");&][s7; -|ndx.Add(\"kappa\");&][s17; ndx = { alfa, beta, gamma, delta, ka"
"ppa }&][s7; -|DUMP(ndx.[* Find](\"beta\"))&][s17; ndx.Find(\"beta\") = 1&][s5; I"
"f element is not present in Index, Find returns a negative value&][s7; -|DUMP(ndx"
".Find(\"something\"));&][s17; ndx.Find(\"something\") = -1&][s5; Any element can"
" be replaced using [* Set] method&][s7; -|ndx.[* Set](0, \"delta\");&][s17; ndx "
"= { delta, beta, gamma, delta, kappa }&][s5; If there are more elements with the "
"same value, they can be iterated using [* FindNext] method&][s7; -|int fi = ndx.F"
"ind(\"delta\");&][s7; -|while(fi >= 0) {&][s7; -|-|cout << fi << \" \";&][s7; -|-"
"|fi = ndx.[* FindNext](fi);&][s7; -|}&][s7; -|cout << 'n';&][s17; 0 3-|&][s5; [*"
" FindAdd] method retrieves position of element like Find, but if element is not p"
"resent in Index, it is added&][s7; -|DUMP(ndx.[* FindAdd](\"one\"));&][s7; -|DUMP"
"(n")
TOPIC_TEXT(
"dx.FindAdd(\"two\"));&][s7; -|DUMP(ndx.FindAdd(\"three\"));&][s7; -|DUMP(ndx.Fin"
"dAdd(\"two\"));&][s7; -|DUMP(ndx.FindAdd(\"three\"));&][s7; -|DUMP(ndx.FindAdd(\""
"one\"));&][s7; &][s16; ndx.FindAdd(\"one\") = 5&][s16; ndx.FindAdd(\"two\") = 6"
"&][s16; ndx.FindAdd(\"three\") = 7&][s16; ndx.FindAdd(\"two\") = 6&][s16; ndx."
"FindAdd(\"three\") = 7&][s16; ndx.FindAdd(\"one\") = 5&][s5; Removing elements f"
"rom random access sequence is always expensive, that is why rather than remove, I"
"ndex supports [* Unlink] and [* UnlinkKey ]operations, which leave element in Ind"
"ex but make it invisible for Find operation&][s7; -|ndx.[* Unlink](2);&][s7; -|nd"
"x.[* UnlinkKey](\"kappa\");&][s7; &][s7; -|DUMP(ndx.Find(ndx`[2`]));&][s7; -|DUMP"
"(ndx.Find(\"kappa\"));&][s7; &][s16; ndx.Find(ndx`[2`]) = -1&][s16; ndx.Find(\""
"kappa\") = -1&][s5; You can test whether element at given position is unlinked us"
"ing [* IsUnlinked] method&][s7; -|DUMP(ndx.[* IsUnlinked](1));&][s7; -|DUMP(ndx.I"
"sUnlinked(2));&][s7; &][s16; ndx.IsUnlinked(1) = 0&][s16; ndx.IsUnlinked(2) = 1"
"&][s5; Unlinked positions can be reused by [* Put] method&][s7; -|ndx.[* Put](\"f"
"oo\");&][s17; ndx = { delta, beta, foo, delta, kappa, one, two, three }&][s7; -|"
"DUMP(ndx.Find(\"foo\"));&][s17; ndx.Find(\"foo\") = 2&][s5; You can also remove "
"all unlinked elements from Index using [* Sweep] method&][s7; -|ndx.Sweep();&][s1"
"7; ndx = { delta, beta, foo, delta, one, two, three }&][s5; As we said, operatio"
"ns directly removing or inserting elements of Index are very expensive, but somet"
"imes this might not matter, so they are available too&][s7; -|ndx.[* Remove](1);&"
"][s17; ndx = { delta, foo, delta, one, two, three }&][s7; -|ndx.[* RemoveKey](\""
"two\");&][s17; ndx = { delta, foo, delta, one, three }&][s7; -|ndx.[* Insert](0,"
" \"insert\");&][s17; ndx = { insert, delta, foo, delta, one, three }&][s5; Final"
"ly, [* PickKeys] operation allows you to obtain Vector of elements of Index in lo"
"w constant time operation (while destroying source Index)&][s7; -|Vector<string> "
"d = ndx.[* Pic")
TOPIC_TEXT(
"kKeys]();&][s7; -|Sort(d);&][s17; d = { delta, delta, foo, insert, one, three }"
"&][s3; 9. Index and client types&][s5; In order to store elements to Index, they "
"must be moveable (you can use [* ArrayIndex] for types that are not) and they mus"
"t have defined the operator== and a function to compute hash value. Notice usage "
"of [* GetHashValue] for types already known to NTL (fundamental types and `[w`]st"
"ring) and [* CombineHash] to combine both hash values into final result&][s7; -|s"
"truct Person : Moveable<Person> {&][s7; -|-|string name;&][s7; -|-|string surname"
";&][s7; -|&][s7; -|-|Person(string name, string surname)&][s7; -|-|: name(name), "
"surname(surname) {}&][s7; -|-|Person() {}&][s7; -|};&][s7; &][s7; -|unsigned [* G"
"etHashValue](const Person`& p)&][s7; -|{&][s7; -|-|return [* CombineHash]([* GetH"
"ashValue](p.name), &][s7; -|-| [* GetHashValue](p.surname));&]["
"s7; -|}&][s7; &][s7; -|bool operator==(const Person`& a, const Person`& b)&][s7; "
"-|{&][s7; -|-|return a.name == b.name `&`& a.surname == b.surname;&][s7; -|}&][s7"
"; &][s7; .......&][s7; &][s7; -|Index<Person> p;&][s7; -|p.Add(Person(\"John\", \""
"Smith\"));&][s7; -|p.Add(Person(\"Paul\", \"Carpenter\"));&][s7; -|p.Add(Person(\""
"Carl\", \"Engles\"));&][s7; -| &][s7; -|DUMP(p.Find(Person(\"Paul\", \"Carpe"
"nter\")));&][s17; p.Find(Person(\"Paul\", \"Carpenter\")) = 1&][s5; If type cann"
"ot be stored in Index or if references to elements are required, [* ArrayIndex] c"
"an be used&][s7; -|unsigned GetHashValue(const Number`& n)&][s7; -|{&][s7; -|-|re"
"turn GetHashValue(n.Get());&][s7; -|}&][s7; &][s7; -|bool operator==(const Number"
"`& a, const Number`& b)&][s7; -|{&][s7; -|-|return a.Get() == b.Get();&][s7; -|}&"
"][s7; &][s7; .......&][s7; &][s7; -|[* ArrayIndex]<Number> n;&][s7; -|n.Add(new I"
"nteger(100));&][s7; -|n.Add(new Double(10.5));&][s7; -|n.Add(new Integer(200));&]"
"[s7; -|n.Add(new Double(20.5));&][s17; n = { 100, 10.5, 200, 20.5 }&][s7; -|DUMP"
"(n.Find(Double(10.5)));&][s17; n.Find(Double(10.5)) = 1&][s3; 10. VectorMa")
TOPIC_TEXT(
"p&][s5; VectorMap is nothing more than a simple composition of Index and Vector."
" You can use [* Add] methods to put elements into the VectorMap&][s7; -|[* Vector"
"Map]<string, Person> m;&][s7; -|&][s7; -|m.[* Add](\"1\", Person(\"John\", \"Smit"
"h\"));&][s7; -|m.Add(\"2\", Person(\"Carl\", \"Engles\"));&][s7; &][s7; -|Person`"
"& p = m.[* Add](\"3\");&][s7; -|p.name = \"Paul\";&][s7; -|p.surname = \"Carpente"
"r\";&][s5; VectorMap provides constant access to its underlying Index and Vector&"
"][s7; -|DUMP(m.[* GetKeys]());&][s7; -|DUMP(m.[* GetValues]());&][s7; &][s16; m.G"
"etKeys() = { 1, 2, 3 }&][s16; m.GetValues() = { John Smith, Carl Engles, Paul Car"
"penter }&][s7; &][s5; You can use indices to iterate map contents&][s7; -|for(i ="
" 0; i < m.GetCount(); i`++)&][s7; -|-|cout << m.[* GetKey](i) << \": \" << m[* `["
"]i[* `]] << 'n';&][s7; &][s16; 1: John Smith&][s16; 2: Carl Engles&][s16; 3: Paul"
" Carpenter&][s7; &][s5; You can use [* Find] method to retrieve position of eleme"
"nt with required key&][s7; -|DUMP(m.[* Find](\"2\"));&][s17; m.Find(\"2\") = 1&]["
"s5; or [* Get] method to retrieve corresponding value&][s7; -|DUMP(m.[* Get](\"2\""
"));&][s17; m.Get(\"2\") = Carl Engles&][s5; Get method is also present in operato"
"r form allowing VectorMap to act like functor&][s7; -|DUMP(m(\"1\"));&][s17; m(\""
"1\") = John Smith&][s5; Passing key not present in VectorMap as Get parameter is "
"a logic error, but there exists two parameter version that returns second paramet"
"er if key is not in VectorMap&][s7; -|DUMP(m.Get(\"33\", Person(\"unknown\", \"pe"
"rson\")));&][s17; m.Get(\"33\", Person(\"unknown\", \"person\")) = unknown person"
"&][s5; As with Index, you can use [* Unlink] to make elements invisible for Find "
"operations&][s7; -|m.Unlink(1);&][s7; -|DUMP(m.Find(\"2\"));&][s17; m.Find(\"2\")"
" = -1&][s5; You can use [* SetKey] method to change the key of the element&][s7; "
"-|m.[* SetKey](1, \"33\");&][s7; -|DUMP(m.Get(\"33\", Person(\"unknown\", \"perso"
"n\")));&][s17; m.Get(\"33\", Person(\"unknown\", \"person\")) = Carl Engles&][s5;"
" If there are more elements with the ")
TOPIC_TEXT(
"same key in VectorMap, you can iterate them using [* FindNext] method&][s7; -|m."
"Add(\"33\", Person(\"Peter\", \"Pan\"));&][s7; &][s16; m.GetKeys() = { 1, 33, 3, "
"33 }&][s16; m.GetValues() = { John Smith, Carl Engles, Paul Carpenter, Peter Pan "
"}&][s7; &][s7; -|int q = m.Find(\"33\");&][s7; -|while(q >= 0) {&][s7; -|-|cout <"
"< m`[q`] << 'n';&][s7; -|-|q = m.[* FindNext](q);&][s7; -|}&][s7; -|&][s16; Carl "
"Engles&][s16; Peter Pan&][s7; &][s5; You can reuse unlinked positions using [* Pu"
"t] method&][s7; -|m.[* UnlinkKey](\"33\");&][s7; -|m.[* Put](\"22\", Person(\"Ali"
"\", \"Baba\"));&][s7; -|m.Put(\"44\", Person(\"Ivan\", \"Wilks\"));&][s7; &][s16;"
" m.GetKeys() = { 1, 22, 3, 44 }&][s16; m.GetValues() = { John Smith, Ali Baba, Pa"
"ul Carpenter, Ivan Wilks }&][s7; &][s5; [* GetSortOrder] algorithm returns order "
"of elements as Vector<int> container. You can use it to order content of VectorMa"
"p without actually moving its elements&][s7; -|bool operator<(const Person`& a, c"
"onst Person`& b)&][s7; -|{&][s7; -|-|return a.surname == b.surname ? a.name < b.n"
"ame&][s7; -| : a.surname < b.surname;&][s7; -|}&][s7"
"; &][s7; .......&][s7; &][s7; -|Vector<int> order = [* GetSortOrder](m.GetValues("
"));&][s17; order = { 1, 2, 0, 3 }&][s7; -|for(i = 0; i < order.GetCount(); i`++)&"
"][s7; -|-|cout << m.GetKey(order`[i`]) << \": \" << m`[order`[i`]`] << 'n';&][s7;"
" &][s16; 22: Ali Baba&][s16; 3: Paul Carpenter&][s16; 1: John Smith&][s16; 44: Iv"
"an Wilks&][s7; &][s5; You can get Vector of values or keys using [* PickValues] r"
"esp. [* PickKeys] methods in low constant time, while destroying content of sourc"
"e VectorMap&][s7; -|Vector<Person> ps = m.[* PickValues]();&][s17; ps = { John Sm"
"ith, Ali Baba, Paul Carpenter, Ivan Wilks }&][s5; If type of values does not sati"
"sfy requirements for Vector elements or if references to elements are needed, you"
" can use [* ArrayMap] instead&][s7; -|[* ArrayMap]<string, Number> am;&][s7; -|am"
".Add(\"A\", new Integer(1));&][s7; -|am.Add(\"B\", new Double(2.0));&][s7; &][s16"
"; am")
TOPIC_TEXT(
".GetKeys() = { A, B }&][s16; am.GetValues() = { 1, 2 }&][s7; &][s7; -|DUMP(am.Ge"
"t(\"A\"));&][s7; -|DUMP(am.Find(\"B\"));&][s7; &][s16; am.Get(\"A\") = 1&][s16; a"
"m.Find(\"B\") = 1")