--- a/KeyedCollection.st Thu Mar 16 16:50:14 2017 +0100
+++ b/KeyedCollection.st Thu Mar 16 21:30:11 2017 +0100
@@ -130,12 +130,41 @@
!KeyedCollection methodsFor:'accessing'!
-associationAt:key
+associationAt:aKey
"return an association consisting of aKey and the element indexed
by aKey -
report an error, if no element is stored under aKey."
- ^ Association key:key value:(self at:key)
+ ^ self associationAt:aKey ifAbsent:[self errorKeyNotFound:aKey]
+
+ "Modified: / 16-03-2017 / 17:19:52 / stefan"
+!
+
+associationAt:aKey ifAbsent:exceptionBlock
+ "return an association consisting of aKey and the element indexed by aKey -
+ return result of exceptionBlock if no element is stored under aKey.
+ Warning: this is a comatibility interface only, with a different semantic as
+ the original ST80 implementation. The returned assoc is created on the fly,
+ and not the one stored in the receiver (there are not assocs there)"
+
+ |value|
+
+ value := self at:aKey ifAbsent:[^ exceptionBlock value].
+ ^ Association key:aKey value:value.
+
+ "Created: / 16-03-2017 / 17:17:05 / stefan"
+!
+
+associations
+ "return an ordered collection containing the receiver's associations."
+
+ |coll|
+
+ coll := OrderedCollection new.
+ self associationsDo:[:assoc | coll add:assoc].
+ ^ coll
+
+ "Created: / 16-03-2017 / 17:30:47 / stefan"
!
at:key
@@ -156,6 +185,83 @@
"Created: / 19.6.1998 / 00:48:23 / cg"
!
+at:aKey ifAbsent:default update:aBlock
+ "update the element stored under aKey with the result from
+ evaluating aBlock with the previous stored value as argument, or with default,
+ if there was no such key initially.
+ Return the new value stored."
+
+ ^ self at:aKey put:(aBlock value:(self at:aKey ifAbsent:default))
+
+ "Created: / 16-03-2017 / 17:28:15 / stefan"
+!
+
+at:aKey ifAbsentPut:valueBlock
+ "return the element indexed by aKey if present,
+ if not present, store the result of evaluating valueBlock
+ under aKey and return it.
+ WARNING: do not add elements while iterating over the receiver.
+ Iterate over a copy to do this."
+
+ ^ self at:aKey ifAbsent:[self at:aKey put:valueBlock value].
+
+ "Created: / 16-03-2017 / 17:23:07 / stefan"
+!
+
+at:aKey ifPresent:aBlock
+ "try to retrieve the value stored at aKey.
+ If there is nothing stored under this key, do nothing.
+ Otherwise, evaluate aBlock, passing the retrieved value as argument."
+
+ |v|
+
+ v := self at:aKey ifAbsent:[^ nil].
+ ^ aBlock value:v.
+
+ "Created: / 16-03-2017 / 17:11:27 / stefan"
+!
+
+at:aKey put:anObject
+ "add the argument anObject under key, aKey to the receiver.
+ Return anObject (sigh).
+ WARNING: do not add elements while iterating over the receiver.
+ Iterate over a copy to do this."
+
+ ^ self subclassResponsibility
+
+ "Created: / 16-03-2017 / 17:33:12 / stefan"
+!
+
+at:aKey put:anObject ifPresent:aBlock
+ "if the receiver contains an element stored under aKey,
+ retrieve it and evaluate aBlock passing the element as argument,
+ return the blocks value.
+ If not, store aValue under the key.
+ Use this with an error-reporting block, to ensure that no keys are reused"
+
+ |value isAbsent|
+
+ value := self at:aKey ifAbsent:[isAbsent := true. self at:aKey put:anObject].
+ isAbsent notNil ifTrue:[
+ ^ value.
+ ].
+
+ ^ aBlock value:value.
+
+ "Created: / 16-03-2017 / 17:38:00 / stefan"
+!
+
+at:aKey update:aBlock
+ "update the element stored under aKey with the result from
+ evaluating aBlock with the previous stored value as argument.
+ Report an error if there was no such key initially.
+ Return the new value stored."
+
+ ^ self at:aKey put:(aBlock value:(self at:aKey))
+
+ "Created: / 16-03-2017 / 17:29:22 / stefan"
+!
+
keyAtEqualValue:value
"return the key under which value is stored.
Raise an error if not found.
@@ -215,13 +321,14 @@
Raise an error if not found.
This is a slow access, since the receiver is searched sequentially.
NOTICE:
- The value is searched using identity compare.
- use #keyAtEqualValue:ifAbsent: to compare for equality."
+ The value is searched using equality compare"
- ^ self keyAtIdenticalValue:value.
+
+ ^ self keyAtEqualValue:value.
"Created: / 19-06-1998 / 00:49:16 / cg"
"Modified (comment): / 07-02-2017 / 11:13:29 / cg"
+ "Modified (comment): / 16-03-2017 / 18:00:28 / stefan"
!
keyAtValue:value ifAbsent:exceptionBlock
@@ -229,13 +336,14 @@
If not found, return the value from evaluating exceptionBlock.
This is a slow access, since the receiver is searched sequentially.
NOTICE:
- The value is searched using identity compare;
- use #keyAtEqualValue:ifAbsent: to compare for equality."
+ The value is searched using equality compare"
- ^ self keyAtIdenticalValue:value ifAbsent:exceptionBlock.
+
+ ^ self keyAtEqualValue:value ifAbsent:exceptionBlock.
"Created: / 19-06-1998 / 00:50:34 / cg"
"Modified: / 07-02-2017 / 11:13:20 / cg"
+ "Modified (comment): / 16-03-2017 / 18:00:37 / stefan"
!
keys
@@ -263,19 +371,6 @@
"Created: / 19.6.1998 / 00:56:24 / cg"
!
-findFirstKey:aBlock
- "find and return the first key, for which evaluation of the argument, aBlock
- returns true; return nil if none is detected."
-
- self keysDo:[:key |
- (aBlock value:key) ifTrue:[^ key].
- ].
- ^ nil
-
- "Created: 8.10.1996 / 22:01:31 / cg"
- "Modified: 8.10.1996 / 22:02:03 / cg"
-!
-
keysAndValuesDo:aBlock
"evaluate aBlock for each key and value"
@@ -307,6 +402,41 @@
"Created: / 19.6.1998 / 00:53:58 / cg"
! !
+!KeyedCollection methodsFor:'searching'!
+
+findFirst:aBlock ifNone:exceptionValue
+ "find the index of the first element, for which evaluation of the argument, aBlock returns true;
+ return its index or the value from exceptionValue if none detected.
+ This is much like #detect:ifNone:, however, here an INDEX is returned,
+ while #detect:ifNone: returns the element.
+
+ Here we return the first key for which aBlock matches the value.
+ Note that there is no order in a Dictionary, so any element is first."
+
+ self keysAndValuesDo:[:eachKey :eachValue| (aBlock value:eachValue) ifTrue:[^ eachKey]].
+ ^ exceptionValue value.
+
+ "
+ (KeyValueList withKeys:#('a' 'b' 'c') andValues:#('bla' 'hello' 'hallo'))
+ findFirst:[:v| v first = $h].
+ "
+
+ "Created: / 16-03-2017 / 17:46:02 / stefan"
+!
+
+findFirstKey:aBlock
+ "find and return the first key, for which evaluation of the argument, aBlock
+ returns true; return nil if none is detected."
+
+ self keysDo:[:key |
+ (aBlock value:key) ifTrue:[^ key].
+ ].
+ ^ nil
+
+ "Created: 8.10.1996 / 22:01:31 / cg"
+ "Modified: 8.10.1996 / 22:02:03 / cg"
+! !
+
!KeyedCollection methodsFor:'testing'!
includesIdenticalKey:aKey