3 *new { arg n=8; ^super.new(n*2) }
4 *newFrom { arg aCollection;
5 var newCollection = this.new(aCollection.size);
6 aCollection.keysValuesDo({ arg k,v, i; newCollection.put(k,v) });
12 ^array.at(this.scanFor(key) + 1)
14 atFail { arg key, function;
17 if ( val.isNil, { ^function.value }, { ^val });
20 this.keysValuesDo({ |k, v|
21 if(k.matchItem(key)) { ^v }
28 add { arg anAssociation;
29 this.put(anAssociation.key, anAssociation.value);
34 value ?? { this.removeAt(key); ^this };
35 index = this.scanFor(key);
36 array.put(index+1, value);
37 if ( array.at(index).isNil, {
38 array.put(index, key);
40 if (array.size < (size * 4), { this.grow });
43 putAll { arg ... dictionaries;
44 dictionaries.do {|dict|
45 dict.keysValuesDo { arg key, value;
51 args.pairsDo { |key, val| this.put(key, val) }
55 args = args ?? { this.keys };
57 var val = this.at(key);
58 val !? { result = result.add(key).add(val) }
63 associationAt { arg key;
64 var index = this.scanFor(key);
66 ^Association.new(array.at(index), array.at(index+1));
71 associationAtFail { arg argKey, function;
72 var index = this.scanFor(argKey);
73 var key = array.at(index);
74 if ( key.isNil, { ^function.value }, {
75 ^Association.new(key, array.at(index+1)) });
77 keys { arg species(Set);
78 var set = species.new(size);
79 this.keysDo({ arg key; set.add(key) });
83 var list = List.new(size);
84 this.do({ arg value; list.add(value) });
90 this.do({ arg item2; if (item1 == item2, {^true}) });
93 includesKey { arg key;
94 ^this.at( key ).notNil;
100 var index = this.scanFor(key);
101 var atKeyIndex = array.at(index);
102 if ( atKeyIndex.isNil, { ^nil });
103 val = array.at(index+1);
104 array.put(index, nil);
105 array.put(index+1, nil);
107 this.fixCollisionsFrom(index);
110 removeAtFail { arg key, function;
112 var index = this.scanFor(key);
113 var atKeyIndex = array.at(index);
114 if ( atKeyIndex.isNil, { ^function.value });
115 val = array.at(index+1);
116 array.put(index, nil);
117 array.put(index+1, nil);
119 this.fixCollisionsFrom(index);
123 remove { ^this.shouldNotImplement(thisMethod) }
124 removeFail { ^this.shouldNotImplement(thisMethod) }
127 keysValuesDo { arg function;
128 this.keysValuesArrayDo(array, function);
130 keysValuesChange { arg function;
131 this.keysValuesDo({ arg key, value, i;
132 this.put(key, function.value(key, value, i));
136 this.keysValuesDo({ arg key, value, i;
137 function.value(value, i);
140 keysDo { arg function;
141 this.keysValuesDo({ arg key, val, i;
142 function.value(key, i);
145 associationsDo { arg function;
146 this.keysValuesDo({ arg key, val, i;
147 function.value( Association.new(key, val), i);
150 pairsDo { arg function;
151 this.keysValuesArrayDo(array, function);
154 collect { arg function;
155 var res = this.class.new(this.size);
156 this.keysValuesDo { arg key, elem; res.put(key, function.value(elem, key)) }
159 select { arg function;
160 var res = this.class.new(this.size);
161 this.keysValuesDo { arg key, elem; if(function.value(elem, key)) { res.put(key, elem) } }
164 reject { arg function;
165 var res = this.class.new(this.size);
166 this.keysValuesDo { arg key, elem; if(function.value(elem, key).not)
167 { res.put(key, elem) } }
172 var dict = this.class.new(this.size);
173 this.keysValuesDo {|key, val|
179 merge {|that, func, fill = true|
180 var commonKeys, myKeys = this.keys, otherKeys = that.keys;
183 if (myKeys == otherKeys) {
186 commonKeys = myKeys.sect(otherKeys);
189 commonKeys.do { |key|
190 res[key] = func.value(this[key], that[key], key)
194 myKeys.difference(otherKeys).do { |key| res[key] = this[key] };
195 otherKeys.difference(myKeys).do { |key| res[key] = that[key] };
200 blend { |that, blend = 0.5, fill = true, specs|
202 ^this.merge(that, { |a, b, key|
203 var spec = if (specs.notNil) { specs[key].asSpec };
205 spec.map(blend(spec.unmap(a), spec.unmap(b), blend))
212 findKeyForValue { arg argValue;
213 this.keysValuesArrayDo(array, { arg key, val, i;
214 if (argValue == val, { ^key })
219 sortedKeysValuesDo { arg function, sortFunc;
220 var keys = this.keys(Array);
223 keys.do { arg key, i;
224 function.value(key, this[key], i);
230 if( this.isEmpty, { ^nil }); // empty dictionary
232 index = (array.size >> 1).rand << 1; // generate an even index.
233 array.at(index).isNil; // key is at even index.
235 // return the value for the first non Nil key we find.
236 // the value is at the odd index.
237 ^array.at(index + 1);
241 if( this.isEmpty, { ^nil });
242 this.keysValuesDo { arg key, val;
243 assoc = assoc.add(key -> val);
245 ^assoc.sort(func).collect(_.key)
248 var keys = this.keys.asArray.powerset;
249 ^keys.collect { | list |
250 var dict = this.class.new;
251 list.do { |key| dict.put(key, this[key]) };
257 transformEvent { arg event;
260 embedInStream { arg event;
261 ^yield(event !? { event.copy.putAll(this) })
266 if ( this.notEmpty ){
267 this.keysValuesDo({ arg key, value; array = array.add([key,value]); });
268 array = array.sort({ arg a, b; a.at(0) < b.at(0) });
275 var array = Array.new(this.size * 2);
276 this.keysValuesDo { |key, val| array.add(key); array.add(val) };
280 // PRIVATE IMPLEMENTATION
281 keysValuesArrayDo { arg argArray, function;
282 // special byte codes inserted by compiler for this method
283 var i=0, j=0, key, val;
284 var arraySize = argArray.size;
285 while ({ i < arraySize },{
286 key = argArray.at(i);
288 val = argArray.at(i+1);
289 function.value(key, val, j);
297 var oldElements = array;
298 array = Array.newClear(array.size * 2);
299 this.keysValuesArrayDo(oldElements,
301 index = this.scanFor(key);
302 array.put(index, key);
303 array.put(index+1, val);
306 fixCollisionsFrom { arg index;
309 var oldIndex = index;
310 var lastKeyIndex = array.size - 2;
312 if (oldIndex == lastKeyIndex, { oldIndex = 0 }, { oldIndex = oldIndex + 2 });
313 (key = array.at(oldIndex)).notNil
315 newIndex = this.scanFor(key);
316 if ( oldIndex != newIndex, {
317 array.swap(oldIndex, newIndex);
318 array.swap(oldIndex+1, newIndex+1)
322 scanFor { arg argKey;
323 var maxHash = array.size div: 2;
324 var start = (argKey.hash % maxHash) * 2;
325 var end = array.size-1;
327 forBy( start, end, 2, { arg i;
328 var key = array.at(i);
329 if ( key.isNil or: { key == argKey }, { ^i });
332 forBy( 0, start-2, 2, { arg i;
333 var key = array.at(i);
334 if ( key.isNil or: { key == argKey }, { ^i });
339 storeItemsOn { arg stream, itemsPerLine = 5;
340 var itemsPerLinem1 = itemsPerLine - 1;
341 var last = this.size - 1;
342 this.associationsDo({ arg item, i;
343 item.storeOn(stream);
344 if (i < last, { stream.comma.space;
345 if (i % itemsPerLine == itemsPerLinem1, { stream.nl.space.space });
349 printItemsOn { arg stream, itemsPerLine = 5;
350 var itemsPerLinem1 = itemsPerLine - 1;
351 var last = this.size - 1;
352 this.associationsDo({ arg item, i;
353 item.printOn(stream);
354 if (i < last, { stream.comma.space;
355 if (i % itemsPerLine == itemsPerLinem1, { stream.nl.space.space });
361 IdentityDictionary : Dictionary {
362 var <>proto; // inheritance of properties
363 var <>parent; // inheritance of properties
366 // if know is set to true then not understood messages will look in the dictionary
367 // for that selector and send the value message to them.
369 *new { arg n=8, proto, parent, know=false;
370 ^super.new(n).proto_(proto).parent_(parent).know_(know)
375 ^this.primitiveFailed
376 /*^array.at(this.scanFor(key) + 1)*/
378 put { arg key, value;
380 value ?? { this.removeAt(key); ^this };
381 ^this.primitiveFailed
384 index = this.scanFor(key);
385 array.put(index+1, value);
386 if ( array.at(index).isNil, {
387 array.put(index, key);
389 if (array.size < (size * 4), { this.grow });
393 putGet { arg key, value;
395 ^this.primitiveFailed
397 var index, atKey, prev;
398 index = this.scanFor(key);
399 prev = array.at(index + 1);
400 array.put(index+1, value);
401 if ( array.at(index).isNil, {
402 array.put(index, key);
404 if (array.size < (size * 4), { this.grow });
410 includesKey { arg key;
411 ^this.at( key ).notNil;
414 findKeyForValue { arg argValue;
415 this.keysValuesArrayDo(array, { arg key, val, i;
416 if (argValue === val, { ^key })
420 scanFor { arg argKey;
421 ^array.atIdentityHashInPairs(argKey)
424 doesNotUnderstand { arg selector ... args;
428 func = this[selector];
430 ^func.functionPerformList(\value, this, args);
433 if (selector.isSetter) {
434 selector = selector.asGetter;
435 if(this.respondsTo(selector)) {
436 warn(selector.asCompileString
437 + "exists a method name, so you can't use it as pseudo-method.")
439 ^this[selector] = args[0];
441 func = this[\forward];
443 ^func.functionPerformList(\value, this, selector, args);
447 ^this.superPerformList(\doesNotUnderstand, selector, args);
451 // The Quant class assumes the quant/phase/offset scheduling model.
452 // If you want a different model, you can write a dictionary like so:
453 // (nextTimeOnGrid: { |self, clock| ... calculate absolute beat number here ... },
454 // parameter: value, parameter: value, etc.)
455 // If you leave out the nextTimeOnGrid function, fallback to quant/phase/offset.
457 nextTimeOnGrid { |clock|
458 if(this[\nextTimeOnGrid].notNil) {
459 ^this[\nextTimeOnGrid].value(this, clock)
461 ^clock.nextTimeOnGrid(this[\quant] ? 1, (this[\phase] ? 0) - (this[\offset] ? 0))
464 asQuant { ^this.copy }
465 timingOffset { ^this[\timingOffset] } // for synchWithQuant()