1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
|
/* __ *\
** ________ ___ / / ___ Scala API **
** / __/ __// _ | / / / _ | (c) 2003-2005, LAMP/EPFL **
** __\ \/ /__/ __ |/ /__/ __ | **
** /____/\___/_/ |_/____/_/ | | **
** |/ **
** $Id$
\* */
package scala.collection.mutable;
/** This trait represents mutable maps. Concrete map implementations
* just have to provide functionality for the abstract methods in
* <code>scala.collection.Map</code> as well as for <code>update</code>,
* and <code>remove</code>.
*
* @author Matthias Zenger
* @version 1.1, 09/05/2004
*/
[cloneable]
trait Map[A, B] extends AnyRef with scala.collection.Map[A, B] with Scriptable[Message[Pair[A, B]]] {
/** This method allows one to add a new mapping from <code>key</code>
* to <code>value</code> to the map. If the map already contains a
* mapping for <code>key</code>, it will be overridden by this
* function.
*
* @param key
* @param value
*/
def update(key: A, value: B): Unit;
/** This method defines syntactic sugar for adding or modifying
* mappings. It is typically used in the following way:
* <pre>
* map += key -> value;
* </pre>
*/
def +=(key: A): MapTo = new MapTo(key);
/** This method adds all the mappings provided by an iterator of
* parameter <code>map</code> to the map.
*
* @param map
*/
def ++=(map: Iterable[Pair[A, B]]): Unit = ++=(map.elements);
/** This method adds all the mappings provided by an iterator of
* parameter <code>map</code> to the map.
*
* @param it
*/
def ++=(it: Iterator[Pair[A, B]]): Unit = it foreach {
case Pair(key, value) => update(key, value);
}
/** <code>incl</code> can be used to add many mappings at the same time
* to the map. The method assumes that a mapping is represented
* by a <code>Pair</code> object who's first component denotes the
* key, and who's second component refers to the value.
*
* @param mappings
*/
def incl(mappings: Pair[A, B]*): Unit = ++=(mappings.elements);
/** This method removes a mapping from the given <code>key</code>.
* If the map does not contain a mapping for the given key, the
* method does nothing.
*/
def -=(key: A): Unit;
/** This method removes all the mappings for keys provided by an
* iterator over the elements of the <code>keys</code> object.
*
* @param keys
*/
def --=(keys: Iterable[A]): Unit = --=(keys.elements);
/** This method removes all the mappings for keys provided by an
* iterator over the elements of the <code>keys</code> object.
*
* @param it
*/
def --=(it: Iterator[A]): Unit = it foreach -=;
/** This method will remove all the mappings for the given sequence
* of keys from the map.
*
* @param keys
*/
def excl(keys: A*): Unit = --=(keys.elements);
/** Removes all mappings from the map. After this operation is
* completed, the map is empty.
*/
def clear: Unit = keys foreach -=;
/** This function transforms all the values of mappings contained
* in this map with function <code>f</code>.
*
* @param f
*/
def map(f: (A, B) => B): Unit = elements foreach {
case Pair(key, value) => update(key, f(key, value));
}
/** This method removes all the mappings for which the predicate
* <code>p</code> returns <code>false</code>.
*
* @param p
*/
def filter(p: (A, B) => Boolean): Unit = toList foreach {
case Pair(key, value) => if (!p(key, value)) -=(key);
}
/** Send a message to this scriptable object.
*
* @param cmd the message to send.
*/
def <<(cmd: Message[Pair[A, B]]): Unit = cmd match {
case Include(Pair(k, v)) => update(k, v);
case Update(Pair(k, v)) => update(k, v);
case Remove(Pair(k, _)) => this -= k;
case Reset() => clear;
case s: Script[Pair[A, B]] => s.elements foreach <<;
case _ => error("message " + cmd + " not understood");
}
/** Return a clone of this map.
*
* @return an map with the same elements.
*/
override def clone(): Map[A, B] = super.clone().asInstanceOf[Map[A, B]];
/** The hashCode method always yields an error, since it is not
* safe to use mutable maps as keys in hash tables.
*
* @return never.
*/
override def hashCode(): Int = error("unsuitable as hash key");
/** Returns a string representation of this map which shows
* all the mappings.
*/
override def toString() =
if (size == 0)
"{}"
else
"{" + {
val iter = elements;
var res = mappingToString(iter.next);
while (iter.hasNext) {
res = res + ", " + mappingToString(iter.next);
}
res;
} + "}";
/** This method controls how a mapping is represented in the string
* representation provided by method <code>toString</code>.
*
* @param p
*/
def mappingToString(p: Pair[A, B]) = p._1.toString() + " -> " + p._2;
class MapTo(key: A) {
def ->(value: B): Unit = update(key, value);
}
}
|