A new version of Collections was added to project The Inbox:
http://source.squeak.org/inbox/Collections-mt.932.mcz ==================== Summary ==================== Name: Collections-mt.932 Author: mt Time: 26 March 2021, 7:04:57.368373 pm UUID: b6c0c2c9-0a4f-684c-87a7-069813edd154 Ancestors: Collections-dtl.931 Sketch of a dictionary that has collections as values. dict := CollectionsDictionary new. (dict at: #fruits) addAll: #(apple apple peach). (dict at: #sweets) add: #nougat. dict removeKey: #sweets. dict explore. =============== Diff against Collections-dtl.931 =============== Item was added: + Dictionary subclass: #CollectionsDictionary + instanceVariableNames: 'collectionClass' + classVariableNames: '' + poolDictionaries: '' + category: 'Collections-Unordered'! Item was added: + ----- Method: CollectionsDictionary class>>defaultCollectionClass (in category 'defaults') ----- + defaultCollectionClass + + ^ OrderedCollection! Item was added: + ----- Method: CollectionsDictionary class>>newOnBags (in category 'instance creation') ----- + newOnBags + + ^ self new + setCollectionClass: Bag; + yourself! Item was added: + ----- Method: CollectionsDictionary class>>newOnOrderedCollections (in category 'instance creation') ----- + newOnOrderedCollections + + ^ self new + setCollectionClass: OrderedCollection; + yourself! Item was added: + ----- Method: CollectionsDictionary class>>newOnSets (in category 'instance creation') ----- + newOnSets + + ^ self new + setCollectionClass: Set; + yourself! Item was added: + ----- Method: CollectionsDictionary>>at: (in category 'accessing') ----- + at: key + + ^ self at: key ifAbsent: [super at: key put: collectionClass new]! Item was added: + ----- Method: CollectionsDictionary>>at:put: (in category 'accessing') ----- + at: key put: value + + self shouldNotImplement.! Item was added: + ----- Method: CollectionsDictionary>>collectionClass (in category 'accessing') ----- + collectionClass + + ^ collectionClass! Item was added: + ----- Method: CollectionsDictionary>>initialize: (in category 'initialization') ----- + initialize: n + + super initialize: n. + self setCollectionClass: self class defaultCollectionClass.! Item was added: + ----- Method: CollectionsDictionary>>setCollectionClass: (in category 'initialization') ----- + setCollectionClass: aClass + + collectionClass := aClass.! |
Hi all! What do you think? Does it makes sense to pursue this idea of "dictionaries with collections as values" and enrich it with tests and documentation? Best, Marcel
|
Hi Marcel,
I'm a bit afraid of creating more subclasses of Collection or Dictionary for two reasons:
1. Different subclasses are incompatible. If you wanted a special dictionary that has weak keys and holds collections, you would need to create another subclass and duplicate some of the logic. 2. Such a design change could introduce ambivalence and doubts about what subclass to choose, and if you choose the wrong class, you will need to do additional conversions. For example, should Collection >> #groupBy: return CollectionsDictionary instances with your proposal? If there is any other legacy code that does not use CollectionsDictionary, you will need to check or fix its type to avoid DNUs when further logic might be added to CollectionsDictionary later. Sometimes I have the feeling that the approach of creating too many collection/dictionary subclasses could violate the idea of polymorphy because they effectively remove genericity from their subclasses and refuse a lot of bequest (e.g., the math functions protocol from Collection).
That being said, I'm not completely against the idea, but these are some common concerns I have on collection subclassing in general. I would like to avoid ending up with a convoluted design such as .NET has, which contains next to the generic List<T>: StringList, StringCollection, StringDictionary, ListCollection, IntCollection, etc. ... :-)
Hypothetically, an alternative approach would be to add a new protocol to an existing superclass, for example 'list enumerating' on Dictionary, which would provide for compatibility with other data structures. For example, existing items could even be wrapped into a list when doing something like:
See Collection >> #associationsDo: for another example. What do you think about it? :-)
However, these are only my 2 cents without a clear opinion. Looking forward to your arguments! :-)
Best, Christoph Von: Squeak-dev <[hidden email]> im Auftrag von Taeumel, Marcel
Gesendet: Freitag, 26. März 2021 19:08 Uhr An: squeak-dev Betreff: Re: [squeak-dev] The Inbox: Collections-mt.932.mcz
Hi all!
What do you think? Does it makes sense to pursue this idea of "dictionaries with collections as values" and enrich it with tests and documentation?
Best,
Marcel
Carpe Squeak!
|
In reply to this post by marcel.taeumel
On 3/26/21 7:08 PM, Marcel Taeumel wrote:
> What do you think? Does it makes sense to pursue this idea of > "dictionaries with collections as values" and enrich it with tests and > documentation? I frequently use dictionaries mapping keys to sets of values. I rely often on these invariants: - retrieval of a not-present key yields an empty collection - removal of all the items from a given key's collection automatically removes the key as well I've never needed 'size' to yield anything other than the number of keys. Christoph's concerns about interface/implementation explosion are well-founded, though, I reckon; do... do we still have traits in Squeak? Cheers, Tony |
In reply to this post by Christoph Thiede
Hi Christoph, thanks for the comments. I think that some of your comments address problems with Dictionary or the collection hierarchy in general. This proposal is just about avoiding the following: (myDict at: #fruits ifAbsentPut: [OrderedCollection new]) add: #apple. Best, Marcel
|
Hi Marcel, Hi Tony,
> This proposal is just about avoiding the following: >
> (myDict at: #fruits ifAbsentPut: [OrderedCollection new]) add: #apple.
Well, but wouldn't a selector like I proposed (#makeListAt:) suffice to solve this problem? This would seem like a more lightweight approach to me than another subclass. :-)
Regarding Tony's second invariant, maybe something like #cleanUpEmptyLists would suffice? Or #makeListAt:do: which automatically deletes the list if empty after evaluating aBlock ...
> I think that some of your comments address problems with Dictionary or the collection hierarchy in general.
Indeed, but my criticism was also about the number of subclasses in Collections in general. :-)
Best,
Christoph
Von: Squeak-dev <[hidden email]> im Auftrag von Taeumel, Marcel
Gesendet: Freitag, 26. März 2021 20:03:24 An: squeak-dev Betreff: Re: [squeak-dev] The Inbox: Collections-mt.932.mcz
Hi Christoph,
thanks for the comments. I think that some of your comments address problems with Dictionary or the collection hierarchy in general.
This proposal is just about avoiding the following:
(myDict at: #fruits ifAbsentPut: [OrderedCollection new]) add: #apple.
Best,
Marcel
Carpe Squeak!
|
Hi Christoph. > Well, but wouldn't a selector like I proposed (#makeListAt:) suffice to solve this problem? > This would seem like a more lightweight approach to me than another subclass. :-) I suppose not. It would be more difficult to use because you expect the clients to use another interface. The kind of dictionary object can easily be hidden. Best, Marcel
|
What about something like:
collection: aClass at: key do: aBlock | coll result | coll := self at: key ifAbsentPut: [aClass new]. result := aBlock value: coll. coll ifEmpty: [self removeKey: key]. ^ result ... perhaps with `ensure:` to do the removal? Then: myDictOfSets collection: Set at: #key1 do: [:s | s add: 123]. On 3/26/21 8:17 PM, Marcel Taeumel wrote: > ... |
Hi Marcel,
do I understand correctly that your point is to reach polymorphy with other types of dictionaries? Well, that changes things, of course. :-) (Then again, which client can expect a regular dictionary not to answer KeyNotFound for arbitrary items that have not been added before? ) I think the use case of mapping values to collections is not being represented in a sufficient way in the current Collections API, thus I find your proposal very interesting. For reference, .NET has
IGrouping`2 which appears as a similar concept to me. I don't want to block your proposal in any way (not that I would be in that position at all :D), I'm just curious about our plans on subclassing Dictionary in general.
Just for interest, do you maybe have some other concrete use cases for a CollectionsDictionary in Squeak? :-)
Best,
Christoph
Von: Squeak-dev <[hidden email]> im Auftrag von Tony Garnock-Jones <[hidden email]>
Gesendet: Freitag, 26. März 2021 20:26:31 An: The general-purpose Squeak developers list; Taeumel, Marcel Betreff: Re: [squeak-dev] The Inbox: Collections-mt.932.mcz What about something like:
collection: aClass at: key do: aBlock | coll result | coll := self at: key ifAbsentPut: [aClass new]. result := aBlock value: coll. coll ifEmpty: [self removeKey: key]. ^ result ... perhaps with `ensure:` to do the removal? Then: myDictOfSets collection: Set at: #key1 do: [:s | s add: 123]. On 3/26/21 8:17 PM, Marcel Taeumel wrote: > ...
Carpe Squeak!
|
Free forum by Nabble | Edit this page |