The Inbox: Collections-mt.932.mcz

Previous Topic Next Topic
 
classic Classic list List threaded Threaded
9 messages Options
Reply | Threaded
Open this post in threaded view
|

The Inbox: Collections-mt.932.mcz

commits-2
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.!


Reply | Threaded
Open this post in threaded view
|

Re: The Inbox: Collections-mt.932.mcz

marcel.taeumel
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

Am 26.03.2021 19:05:09 schrieb [hidden email] <[hidden email]>:

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.!




Reply | Threaded
Open this post in threaded view
|

Re: The Inbox: Collections-mt.932.mcz

Christoph Thiede

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:


myDict at: #fruits put: #apple.

(myDict makeListAt: #fruits) addAll: #(banana cherry date).

(myDict makeListAt: #sweets) add: 'eclair; add: 'froyo'; add: 'gingerbread'.


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

Am 26.03.2021 19:05:09 schrieb [hidden email] <[hidden email]>:

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.!




Carpe Squeak!
Reply | Threaded
Open this post in threaded view
|

Re: The Inbox: Collections-mt.932.mcz

Tony Garnock-Jones-5
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

Reply | Threaded
Open this post in threaded view
|

Re: The Inbox: Collections-mt.932.mcz

marcel.taeumel
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

Am 26.03.2021 19:50:40 schrieb Thiede, Christoph <[hidden email]>:

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:


myDict at: #fruits put: #apple.

(myDict makeListAt: #fruits) addAll: #(banana cherry date).

(myDict makeListAt: #sweets) add: 'eclair; add: 'froyo'; add: 'gingerbread'.


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

Am 26.03.2021 19:05:09 schrieb [hidden email] <[hidden email]>:

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.!




Reply | Threaded
Open this post in threaded view
|

Re: The Inbox: Collections-mt.932.mcz

Christoph Thiede

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

Am 26.03.2021 19:50:40 schrieb Thiede, Christoph <[hidden email]>:

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:


myDict at: #fruits put: #apple.

(myDict makeListAt: #fruits) addAll: #(banana cherry date).

(myDict makeListAt: #sweets) add: 'eclair; add: 'froyo'; add: 'gingerbread'.


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

Am 26.03.2021 19:05:09 schrieb [hidden email] <[hidden email]>:

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.!




Carpe Squeak!
Reply | Threaded
Open this post in threaded view
|

Re: The Inbox: Collections-mt.932.mcz

marcel.taeumel
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

Am 26.03.2021 20:10:41 schrieb Thiede, Christoph <[hidden email]>:

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

Am 26.03.2021 19:50:40 schrieb Thiede, Christoph <[hidden email]>:

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:


myDict at: #fruits put: #apple.

(myDict makeListAt: #fruits) addAll: #(banana cherry date).

(myDict makeListAt: #sweets) add: 'eclair; add: 'froyo'; add: 'gingerbread'.


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

Am 26.03.2021 19:05:09 schrieb [hidden email] <[hidden email]>:

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.!




Reply | Threaded
Open this post in threaded view
|

Re: The Inbox: Collections-mt.932.mcz

Tony Garnock-Jones-5
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:
> ...

Reply | Threaded
Open this post in threaded view
|

Re: The Inbox: Collections-mt.932.mcz

Christoph Thiede

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!