<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=us-ascii">
<meta name="Generator" content="Microsoft Exchange Server">
<!-- converted from text --><style><!-- .EmailQuote { margin-left: 1pt; padding-left: 4pt; border-left: #800000 2px solid; } --></style>
</head>
<body>
<meta content="text/html; charset=UTF-8">
<style type="text/css" style="">
<!--
p
        {margin-top:0;
        margin-bottom:0}
-->
</style>
<div dir="ltr">
<div id="x_divtagdefaultwrapper" dir="ltr" style="font-size:12pt; color:#000000; font-family:Calibri,Helvetica,sans-serif">
<p>Hi Levente,</p>
<p><br>
</p>
<p>two goals: First of all, I was assuming that we aim to provide a comprehensive set of features in the Collections package, and having no possibility to customize the key comparison in weak key dictionaries sounded like a logical gap to me. There are no senders
 of <span>WeakKeyDictionary in the Trunk but it IMO still adds value to the package.</span> Second, I am actually having a use case for <span>PluggableWeakKeyDictionary in a third-party package (<a href="https://github.com/LinqLover/SimulationStudio/pull/34/files/3137fe3772b288654d377fc9470302ab2fd26148" class="x_OWAAutoLink">SimulationStudio#34</a>)
 where I need to compare keys by mirror primitives but still need to hold them weakly.</span></p>
<p><span><br>
</span></p>
<p><span>I have uploaded this class directly to Trunk because I could not see any harm in it and did not want to create another helper package for Collections. If there was anything wrong with this approach, I apologize and we can remove this class immediately
 again. Still, I would find a <span>PluggableWeakKeyDictionary in the Trunk useful.</span></span></p>
<p><span><span><br>
</span></span></p>
<p><span><span>> </span></span><span style="font-size:12pt">And I think there might be a better </span><span style="font-size:12pt">way to do what you want to achieve than copying all those methods.</span></p>
<p><span><span><br>
</span></span></p>
<p><span><span>What approach were you having in mind concretely? :-)</span></span></p>
<p><span><span><br>
</span></span></p>
<p><span><span>Best,</span></span></p>
<p><span><span>Christoph</span></span></p>
</div>
<hr tabindex="-1" style="display:inline-block; width:98%">
<div id="x_divRplyFwdMsg" dir="ltr"><font face="Calibri, sans-serif" color="#000000" style="font-size:11pt"><b>Von:</b> Squeak-dev <squeak-dev-bounces@lists.squeakfoundation.org> im Auftrag von Levente Uzonyi <leves@caesar.elte.hu><br>
<b>Gesendet:</b> Montag, 27. Dezember 2021 18:35:12<br>
<b>An:</b> squeak-dev@lists.squeakfoundation.org<br>
<b>Cc:</b> packages@lists.squeakfoundation.org<br>
<b>Betreff:</b> Re: [squeak-dev] The Trunk: Collections-ct.972.mcz</font>
<div> </div>
</div>
</div>
<font size="2"><span style="font-size:10pt;">
<div class="PlainText">Hi Christoph,<br>
<br>
What is your goal with such dictionary?<br>
It's now in the Trunk with no users. And I think there might be a better <br>
way to do what you want to achieve than copying all those methods.<br>
<br>
<br>
Levente<br>
<br>
On Mon, 27 Dec 2021, commits@source.squeak.org wrote:<br>
<br>
> Christoph Thiede uploaded a new version of Collections to project The Trunk:<br>
> <a href="http://source.squeak.org/trunk/Collections-ct.972.mcz">http://source.squeak.org/trunk/Collections-ct.972.mcz</a><br>
><br>
> ==================== Summary ====================<br>
><br>
> Name: Collections-ct.972<br>
> Author: ct<br>
> Time: 27 December 2021, 1:19:57.212181 am<br>
> UUID: f740e1ad-4410-0745-b615-2986366b7e75<br>
> Ancestors: Collections-tonyg.971<br>
><br>
> Adds PluggableWeakKeyDictionary, the logical combination of PluggableDictionary and WeakKeyDictionary. All methods are copied literally from PluggableDictionary, but the class inherits from WeakKeyDictionary rather than from Dictionary.<br>
><br>
> I do not like all the duplication myself but cannot think of a better solution without using composition (slow, breaking design change) or traits (breaking design change).<br>
><br>
> =============== Diff against Collections-tonyg.971 ===============<br>
><br>
> Item was added:<br>
> + WeakKeyDictionary subclass: #PluggableWeakKeyDictionary<br>
> +      instanceVariableNames: 'hashBlock equalBlock'<br>
> +      classVariableNames: ''<br>
> +      poolDictionaries: ''<br>
> +      category: 'Collections-Weak'!<br>
> + <br>
> + !PluggableWeakKeyDictionary commentStamp: 'ct 12/27/2021 01:07' prior: 0!<br>
> + I combine the features of PluggableDictionary and WeakKeyDictionary, i.e., clients can supply custom blocks for comparing and hasing my keys, and I hold weakly on my keys.!<br>
><br>
> Item was added:<br>
> + ----- Method: PluggableWeakKeyDictionary class>>integerDictionary (in category 'instance creation') -----<br>
> + integerDictionary<br>
> +      ^ self new hashBlock: [:integer | integer hash \\ 1064164 * 1009]!<br>
><br>
> Item was added:<br>
> + ----- Method: PluggableWeakKeyDictionary>>= (in category 'comparing') -----<br>
> + = anObject<br>
> +      "Two dictionaries are equal if<br>
> +       (a) they are the same 'kind' of thing.<br>
> +       (b) they have the same set of keys.<br>
> +       (c) for each (common) key, they have the same value"<br>
> + <br>
> +      self == anObject ifTrue: [ ^true ].<br>
> +      self species == anObject species ifFalse: [ ^false ].<br>
> +      hashBlock = anObject hashBlock ifFalse: [ ^false ].<br>
> +      equalBlock = anObject equalBlock ifFalse: [ ^false ].<br>
> +      self size = anObject size ifFalse: [ ^false ].<br>
> +      self associationsDo: [ :association |<br>
> +              (anObject at: association key ifAbsent: [ ^false ]) = association value<br>
> +                      ifFalse: [ ^false ] ].<br>
> +      ^true!<br>
><br>
> Item was added:<br>
> + ----- Method: PluggableWeakKeyDictionary>>collect: (in category 'enumerating') -----<br>
> + collect: aBlock <br>
> +      "Evaluate aBlock with each of my values as the argument.  Collect the resulting values into a collection that is like me. Answer with the new collection."<br>
> + <br>
> +      | newCollection |<br>
> +      newCollection := (self species new: self size)<br>
> +              hashBlock: hashBlock;<br>
> +              equalBlock: equalBlock;<br>
> +              yourself.<br>
> +      self associationsDo: [ :each |<br>
> +              newCollection at: each key put: (aBlock value: each value) ].<br>
> +      ^newCollection<br>
> + <br>
> + !<br>
><br>
> Item was added:<br>
> + ----- Method: PluggableWeakKeyDictionary>>copyEmpty (in category 'copying') -----<br>
> + copyEmpty<br>
> + <br>
> +      ^super copyEmpty<br>
> +              hashBlock: hashBlock;<br>
> +              equalBlock: equalBlock;<br>
> +              yourself!<br>
><br>
> Item was added:<br>
> + ----- Method: PluggableWeakKeyDictionary>>equalBlock (in category 'accessing') -----<br>
> + equalBlock<br>
> +      "Return the block used for comparing the elements in the receiver."<br>
> +      ^equalBlock!<br>
><br>
> Item was added:<br>
> + ----- Method: PluggableWeakKeyDictionary>>equalBlock: (in category 'accessing') -----<br>
> + equalBlock: aBlock<br>
> +      "Set a new equality block. The block must accept two arguments and return true if the argumets are considered to be equal, false otherwise"<br>
> +      equalBlock := aBlock.!<br>
><br>
> Item was added:<br>
> + ----- Method: PluggableWeakKeyDictionary>>hashBlock (in category 'accessing') -----<br>
> + hashBlock<br>
> +      "Return the block used for hashing the elements in the receiver."<br>
> +      ^hashBlock!<br>
><br>
> Item was added:<br>
> + ----- Method: PluggableWeakKeyDictionary>>hashBlock: (in category 'accessing') -----<br>
> + hashBlock: aBlock<br>
> +      "Set a new hash block. The block must accept one argument and must return the hash value of the given argument."<br>
> +      hashBlock := aBlock.!<br>
><br>
> Item was added:<br>
> + ----- Method: PluggableWeakKeyDictionary>>scanFor: (in category 'private') -----<br>
> + scanFor: anObject <br>
> +      "Scan the key array for the first slot containing either a nil (indicating an empty slot) or an element that matches anObject. Answer the index of that slot or raise an error if no slot is found. This method will be overridden in various subclasses
 that have different interpretations for matching elements."<br>
> + <br>
> +      | index start size |<br>
> +      index := start := (hashBlock<br>
> +              ifNil: [ anObject hash ]<br>
> +              ifNotNil: [ hashBlock value: anObject ]) \\ (size := array size) + 1.<br>
> +      [ <br>
> +              | element |<br>
> +              ((element := array at: index) == nil or: [<br>
> +                      equalBlock<br>
> +                              ifNil: [ element key = anObject ]<br>
> +                              ifNotNil: [ equalBlock value: element key value: anObject ] ])<br>
> +                      ifTrue: [ ^index ].<br>
> +              (index := index \\ size + 1) = start ] whileFalse.<br>
> +      self errorNoFreeSpace!<br>
><br>
> Item was added:<br>
> + ----- Method: PluggableWeakKeyDictionary>>scanForEmptySlotFor: (in category 'private') -----<br>
> + scanForEmptySlotFor: anObject<br>
> +      "Scan the key array for the first slot containing an empty slot (indicated by a nil). Answer the index of that slot. This method will be overridden in various subclasses that have different interpretations for matching elements."<br>
> + <br>
> +      | index start size |<br>
> +      index := start := (hashBlock<br>
> +              ifNil: [ anObject hash ]<br>
> +              ifNotNil: [ hashBlock value: anObject ]) \\ (size := array size) + 1.<br>
> +      [ <br>
> +              (array at: index) ifNil: [ ^index ].<br>
> +              (index := index \\ size + 1) = start ] whileFalse.<br>
> +      self errorNoFreeSpace!<br>
<br>
</div>
</span></font>
</body>
</html>