<div dir="auto">It’s an interesting idea, but this implementation could cause problems. For example, the cache only grows, and over time you run out of memory. And the symbol you create should uniquely identify with the message (receiver, selector, arguments), maybe you should use the message itself as key instead? But even considering those things, I’m not sure this is a practical idea that I’d use in my code.</div><div dir="auto"><br></div><div dir="auto">Have you used a Smalltalk with support for instance-specific methods? I have some objects that are immutable in some sense (equality is invariant over the instances lifetime, but they can change state as long as it doesn’t break that invariant, for example to cache computations, or to do lazy initialization and let some data be computed only when needed). These objects often implement some unary messages that are “pure functions”, i.e. they will always compute the same value for a given instance, so they could be cached. I normally cache them in a properties dictionary that each instance has, sometimes in an instance variable, but if we had instance-specific methods I could just use that. For example, say you want to do this for the average of #(1 2 3), then you implement the method >>#average so that at the end, before returning the computed value, adds a new instance method #average to the receiver that stores that value as a literal and just returns that value, i.e. a method that decompiled would look like this:</div><div dir="auto"><br></div><div dir="auto">average</div><div dir="auto">    ^ 2</div><div dir="auto"><br></div><div dir="auto">The next time you send #average to #(1 2 3) it it will just return the stored value, only for the instance #(1 2 3).</div><div dir="auto"><br></div><div dir="auto">I don’t think there’s any plan to support this in Cuis or the OpenSmalltalk VM, tho.</div><div dir="auto"><br></div><div dir="auto">Cheers,</div><div dir="auto">Luciano</div><div dir="auto"><br></div><div dir="auto"><br></div><div><div class="gmail_quote"><div dir="ltr" class="gmail_attr">On Fri, Dec 6, 2024 at 04:24 Mark Volkmann via Cuis-dev <<a href="mailto:cuis-dev@lists.cuis.st">cuis-dev@lists.cuis.st</a>> wrote:<br></div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left-width:1px;border-left-style:solid;padding-left:1ex;border-left-color:rgb(204,204,204)"><div dir="ltr"><div>Certainly it's not common to want to memoize a method, but I was wondering if it would be easy to do. I came up with the following that works well. I'd be interested in hearing whether there is a better approach and whether something like this is already in the base image and I just haven't found it yet.</div><div><br></div><div>I added the <font face="monospace" style="font-family:monospace;color:rgb(0,0,0)">Object</font> instance method <font face="monospace" style="font-family:monospace;color:rgb(0,0,0)">memoize:</font> which takes a block.<br>This caches previously computed values in an <font face="monospace" style="font-family:monospace;color:rgb(0,0,0)">IdentityDictionary</font><br>that is saved in <font face="monospace" style="font-family:monospace;color:rgb(0,0,0)">Smalltalk</font> which is also an <font face="monospace" style="font-family:monospace;color:rgb(0,0,0)">IdentityDictionary</font>.<br><br><font face="monospace" style="font-family:monospace;color:rgb(0,0,0)">memoize: aBlock<br>    | cache cacheKey sender valueKey |<br><br>    sender := thisContext sender.<br><br>    "Smalltalk is a SystemDictionary which is an IdentityDictionary.<br>    That is why cacheKey must be a Symbol."<br>    cacheKey := ('cache-', sender name) asSymbol.<br><br>    cache := Smalltalk at: cacheKey ifAbsentPut: [ IdentityDictionary new ].<br>    valueKey := thisContext name, sender arguments asString :: asSymbol.<br><br>    ^ cache at: valueKey ifAbsentPut: [ aBlock value ].</font><br><br>Using the <font face="monospace" style="font-family:monospace;color:rgb(0,0,0)">memoize:</font> method is demonstrated in the class method <font face="monospace" style="font-family:monospace;color:rgb(0,0,0)">average:</font> below<br>(added to any class) which takes an array of numbers.<br><br></div><div><font face="monospace" style="font-family:monospace;color:rgb(0,0,0)">average: numberArray<br>    ^ self memoize: [<br>        | sum |<br>        'computing average' print.<br>        sum := numberArray fold: [:acc :n | acc + n].<br>        sum / numberArray size.<br>    ].</font></div></div><div dir="ltr"><div><br></div><div><br></div><span class="gmail_signature_prefix">-- </span><br><div dir="ltr" class="gmail_signature" data-smartmail="gmail_signature"><div dir="ltr"><div><div dir="ltr"><div><div dir="ltr"><div dir="ltr"><div><font face="arial, helvetica, sans-serif" style="font-family:arial,helvetica,sans-serif;color:rgb(0,0,0)">R. Mark Volkmann</font></div><div><span style="font-size:12.8px"><font face="arial, helvetica, sans-serif" style="font-family:arial,helvetica,sans-serif;color:rgb(0,0,0)">Object Computing, Inc.</font></span></div></div></div></div></div></div></div></div></div>
-- <br>
Cuis-dev mailing list<br>
<a href="mailto:Cuis-dev@lists.cuis.st" target="_blank">Cuis-dev@lists.cuis.st</a><br>
<a href="https://lists.cuis.st/mailman/listinfo/cuis-dev" rel="noreferrer" target="_blank">https://lists.cuis.st/mailman/listinfo/cuis-dev</a><br>
</blockquote></div></div>