<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 Chris,</p>
<p><br>
</p>
<p>awesome idea!</p>
<p><br>
</p>
<p>Regarding the implementation: Did you run any benchmarks and how massive is the slowdown? The previous implementation used #basicAt: to avoid comparing characters (which is not fast on all platforms) and sending messages to them (in favor of inlining). I'm
 curious whether this could be avoided in the new implementation as well and how much performance could be won with that. #<span>numberOrValue also looks very slow. Maybe it would be worth providing two alternative branches depending on the type of the collection argument?</span></p>
<p><span><br>
</span></p>
<p><span>Also note that you added support for Unicode indexes in format arguments, which we decided against in the past:</span></p>
<p><span><br>
</span></p>
<p><span><span>  '{', (Character value: 16r1d7eb) asString, '}' format: (1 to: 10).</span><br>
</span></p>
<p><span><span><br>
</span></span></p>
<p><span><span>See this thread for more information: <a href="http://forum.world.st/The-Inbox-Collections-ct-851-mcz-td5102500.html" class="x_OWAAutoLink" id="LPlnk708357">http://forum.world.st/The-Inbox-Collections-ct-851-mcz-td5102500.html</a></span><br>
</span></p>
<p><span><br>
</span></p>
<p><span>By the way, you also dropped multilingual support in the error message. :-)</span></p>
<p><span><br>
</span></p>
<p><span>Best,</span></p>
<p><span>Christoph</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 commits@source.squeak.org <commits@source.squeak.org><br>
<b>Gesendet:</b> Donnerstag, 7. Juli 2022 06:22:18<br>
<b>An:</b> squeak-dev@lists.squeakfoundation.org; packages@lists.squeakfoundation.org<br>
<b>Betreff:</b> [squeak-dev] The Trunk: Collections-cmm.1016.mcz</font>
<div> </div>
</div>
</div>
<font size="2"><span style="font-size:10pt;">
<div class="PlainText">Chris Muller uploaded a new version of Collections to project The Trunk:<br>
<a href="http://source.squeak.org/trunk/Collections-cmm.1016.mcz">http://source.squeak.org/trunk/Collections-cmm.1016.mcz</a><br>
<br>
==================== Summary ====================<br>
<br>
Name: Collections-cmm.1016<br>
Author: cmm<br>
Time: 6 July 2022, 11:22:16.540715 pm<br>
UUID: 8eaa5fee-446e-4ccb-ae26-652e7a70e693<br>
Ancestors: Collections-eem.1015<br>
<br>
Let String>>#format: also support alphanumeric tokens (accessed via a Dictionary).  Backward compatibility with classic numeric tokens via a SequenceableCollection is preserved.<br>
<br>
=============== Diff against Collections-eem.1015 ===============<br>
<br>
Item was changed:<br>
  ----- Method: String>>format: (in category 'formatting') -----<br>
+ format: aCollection <br>
+        "Substitute tokens in the receiver with element values of aCollection.  The tokens are indicated in curly-braces and may be either numeric, e.g., {1}, {2}, etc. and map to a SequenceableCollection, OR, alphanumeric, e.g., {name}, {date}, etc., in which
 case aCollection should be a Dictionary.<br>
+        The values can be static or, with the specification of a Block element, dynamic.<br>
+         <br>
+        Simplest examples:<br>
+                'foo {date} bar' format: ({'date'->Date today} as: Dictionary).<br>
+ <br>
+        Dynamic calculation is allowed via Blocks.<br>
+                'foo {NOW} bar' format: ({'NOW'-> [DateAndTime now]} as: Dictionary).<br>
+ <br>
+        Backward-compatible with numeric-only #format:<br>
- format: arguments <br>
-        "Format the receiver with arguments.<br>
-        <br>
-        Simplest example:<br>
                 'foo {1} bar' format: {Date today}.<br>
+ <br>
+        Now with block support:<br>
+                'foo {1} bar' format: {[Date today]}.<br>
+         <br>
+        Complete example with escaped characters:  <br>
-        <br>
-        Complete example:<br>
                 '\{ \} \\ foo {1} bar {2}' format: {12. 'string'}.<br>
+                '\{ \} \\ foo {FOO} bar {BAR}' format: ({'FOO'->12. 'BAR'->'string'} as: Dictionary).<br>
         "<br>
+        ^ self class new: self size * 11 // 10 "ready for +10% growth"streamContents:<br>
+                        [ : output | | lastIndex nextIndex key |<br>
+                        lastIndex := 1.<br>
+                        key := WriteStream on: (String new: 10).<br>
+                        [ "stream to output until first { or \"<br>
+                        (nextIndex := self indexOfAnyOf: FormatCharacterSet startingAt: lastIndex) = 0 ] whileFalse:<br>
+                                [ nextIndex = lastIndex ifFalse:<br>
+                                        [ output next: nextIndex - lastIndex putAll: self startingAt: lastIndex ].<br>
+                                "special char hit, escape char?"<br>
+                                (self at: nextIndex) == $\<br>
+                                        ifTrue: [ "transfer the escaped character."<br>
+                                                output nextPut: (self at: (nextIndex := nextIndex + 1)) ]<br>
+                                        ifFalse:<br>
+                                                [ | nextKeyChar |<br>
+                                                "${ char, parse the key"<br>
+                                                [ nextKeyChar := self at: (nextIndex := nextIndex + 1).<br>
+                                                nextKeyChar isAlphaNumeric ] whileTrue: [ key nextPut: nextKeyChar ].<br>
+                                                nextKeyChar = $} ifFalse: [ self error: '$} expected' ].<br>
+                                                output nextPutAll: (aCollection at: key contents numberOrValue) value asString.<br>
+                                          key reset ].<br>
+                                lastIndex := nextIndex + 1 ].<br>
+                        lastIndex <= self size ifTrue:<br>
+                                [ output<br>
+                                        next: self size - lastIndex + 1<br>
+                                        putAll: self<br>
+                                        startingAt: lastIndex ] ]!<br>
-        ^ self class new: self size * 11 // 10 "+10%" streamContents: [ :output |<br>
-                | lastIndex nextIndex |<br>
-                lastIndex := 1.<br>
-                [ (nextIndex := self indexOfAnyOf: FormatCharacterSet startingAt: lastIndex) = 0 ] whileFalse: [<br>
-                        nextIndex = lastIndex ifFalse: [<br>
-                                output next: nextIndex - lastIndex putAll: self startingAt: lastIndex ].<br>
-                        (self at: nextIndex) caseOf: {<br>
-                                [ $\ ] -> [ output nextPut: (self at: (nextIndex := nextIndex + 1)) ].<br>
-                                [ ${ ] -> [<br>
-                                        "Parse the index - a positive integer in base 10."<br>
-                                        | digitValue collectionIndex |<br>
-                                        collectionIndex := 0.<br>
-                                        [ (digitValue := self basicAt: (nextIndex := nextIndex + 1)) between: 48 "$0 asciiValue" and: 57 "$9 asciiValue" ] whileTrue: [<br>
-                                                collectionIndex := collectionIndex * 10 + digitValue - 48 "$0 asciiValue". ].<br>
-                                        digitValue =  125 "$} asciiValue" ifFalse: [ self error: ('{1} expected' translated format: {$}}) ].<br>
-                                        output nextPutAll: (arguments at: collectionIndex) asString ] }.<br>
-                        lastIndex := nextIndex + 1 ].<br>
-                lastIndex <= self size ifTrue: [<br>
-                        output next: self size - lastIndex + 1 putAll: self startingAt: lastIndex ] ]!<br>
<br>
<br>
</div>
</span></font>
</body>
</html>