<div dir="auto">I don't much like WriteStream on: String empty.<div dir="auto">If String empty is implemented as answering a literal, and WritStream implemented to become the grown contents as it originally did in st80 and could also do in Squeak now that we have a fast become, we take the risk to modify the literal...</div><div dir="auto">String new better express our intention, we want a new substring.</div><div dir="auto">Also, contents does not necessarily answer a copy, it could answer the verbatim contents if full. So i hope that resetContents would perform the copy, but that's far from certain without seing code. We thus risk to have substrings sharing identity, and overwrite previous substring...</div><div dir="auto">Note that we can also efficiently search index of any of a character set, starting at a given index in case of byte string...</div></div><br><div class="gmail_quote"><div dir="ltr" class="gmail_attr">Le mar. 4 juin 2019 à 21:34, <<a href="mailto:commits@source.squeak.org">commits@source.squeak.org</a>> a écrit :<br></div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">Chris Muller uploaded a new version of Collections to project The Inbox:<br>
<a href="http://source.squeak.org/inbox/Collections-cmm.836.mcz" rel="noreferrer noreferrer" target="_blank">http://source.squeak.org/inbox/Collections-cmm.836.mcz</a><br>
<br>
==================== Summary ====================<br>
<br>
Name: Collections-cmm.836<br>
Author: cmm<br>
Time: 4 June 2019, 2:34:30.820747 pm<br>
UUID: 95d228d9-2fda-4e35-9665-d1daf90cbd99<br>
Ancestors: Collections-cmm.835<br>
<br>
- Move utility methods of Collection to 'utilities'.<br>
- #joinSeparatedBy: is useful even for non-SequenceableCollections.<br>
- Speed up String>>#subStrings:.<br>
<br>
=============== Diff against Collections-cmm.835 ===============<br>
<br>
Item was changed:<br>
+ ----- Method: Collection>>asCommaString (in category 'utilities') -----<br>
- ----- Method: Collection>>asCommaString (in category 'printing') -----<br>
asCommaString<br>
"Return collection printed as 'a, b, c' "<br>
+ ^ self joinSeparatedBy: ', '!<br>
- <br>
- ^String streamContents: [:s | self asStringOn: s delimiter: ', ']<br>
- !<br>
<br>
Item was changed:<br>
+ ----- Method: Collection>>asCommaStringAnd (in category 'utilities') -----<br>
- ----- Method: Collection>>asCommaStringAnd (in category 'printing') -----<br>
asCommaStringAnd<br>
"Return collection printed as 'a, b and c' "<br>
<br>
^String streamContents: [:s | self asStringOn: s delimiter: ', ' last: ' and ']<br>
!<br>
<br>
Item was changed:<br>
+ ----- Method: Collection>>asStringOn:delimiter: (in category 'utilities') -----<br>
- ----- Method: Collection>>asStringOn:delimiter: (in category 'printing') -----<br>
asStringOn: aStream delimiter: delimString<br>
"Print elements on a stream separated<br>
with a delimiter String like: 'a, b, c'<br>
Uses #asString instead of #print:."<br>
<br>
self do: [:elem | aStream nextPutAll: elem asString]<br>
separatedBy: [aStream nextPutAll: delimString]!<br>
<br>
Item was changed:<br>
+ ----- Method: Collection>>asStringOn:delimiter:last: (in category 'utilities') -----<br>
- ----- Method: Collection>>asStringOn:delimiter:last: (in category 'printing') -----<br>
asStringOn: aStream delimiter: delimString last: lastDelimString<br>
"Print elements on a stream separated<br>
with a delimiter between all the elements and with<br>
a special one before the last like: 'a, b and c'.<br>
Uses #asString instead of #print:<br>
<br>
Note: Feel free to improve the code to detect the last element."<br>
<br>
| n sz |<br>
n := 1.<br>
sz := self size.<br>
self do: [:elem |<br>
n := n + 1.<br>
aStream nextPutAll: elem asString]<br>
separatedBy: [<br>
aStream nextPutAll: (n = sz ifTrue: [lastDelimString] ifFalse: [delimString])]!<br>
<br>
Item was changed:<br>
+ ----- Method: Collection>>histogramOf: (in category 'utilities') -----<br>
- ----- Method: Collection>>histogramOf: (in category 'converting') -----<br>
histogramOf: aBlock<br>
<br>
^ self collect: aBlock as: Bag!<br>
<br>
Item was added:<br>
+ ----- Method: Collection>>join (in category 'utilities') -----<br>
+ join<br>
+ "Example: #(H e l l o W o r l d) join = 'HelloWorld'."<br>
+ ^ self joinSeparatedBy: String empty!<br>
<br>
Item was added:<br>
+ ----- Method: Collection>>joinSeparatedBy: (in category 'utilities') -----<br>
+ joinSeparatedBy: aString<br>
+ "Returns a string, which is a concatenation of each element's string representation separated by another string."<br>
+ ^ String streamContents:<br>
+ [ : stream | self asStringOn: stream delimiter: aString ]!<br>
<br>
Item was changed:<br>
+ ----- Method: Collection>>topologicallySortedUsing: (in category 'utilities') -----<br>
- ----- Method: Collection>>topologicallySortedUsing: (in category 'converting') -----<br>
topologicallySortedUsing: aSortBlock <br>
"Answer a SortedCollection whose elements are the elements of the <br>
receiver, but topologically sorted. The topological order is defined <br>
by the argument, aSortBlock."<br>
<br>
| aSortedCollection |<br>
aSortedCollection := SortedCollection new: self size.<br>
aSortedCollection sortBlock: aSortBlock.<br>
self do: [:each | aSortedCollection addLast: each]. "avoids sorting"<br>
^ aSortedCollection sortTopologically<br>
!<br>
<br>
Item was removed:<br>
- ----- Method: SequenceableCollection>>join (in category 'converting') -----<br>
- join<br>
- "Example: #(H e l l o W o r l d) join = 'HelloWorld'. "<br>
- <br>
- ^ self joinSeparatedBy: ''!<br>
<br>
Item was removed:<br>
- ----- Method: SequenceableCollection>>joinSeparatedBy: (in category 'converting') -----<br>
- joinSeparatedBy: aSeparator<br>
- "Returns a string, which is a concatenation of each element's string representation separated by another string."<br>
- <br>
- ^ String streamContents: [:stream |<br>
- self<br>
- do: [:ea | stream nextPutAll: ea asString]<br>
- separatedBy: [stream nextPutAll: aSeparator asString]]!<br>
<br>
Item was changed:<br>
----- Method: String>>subStrings: (in category 'converting') -----<br>
subStrings: separators <br>
+ "Answer an array containing the substrings in the receiver separated by the elements of separators."<br>
- "Answer an array containing the substrings in the receiver separated <br>
- by the elements of separators."<br>
| char result sourceStream subString |<br>
+ (separators isString or:<br>
+ [ separators allSatisfy:<br>
+ [ : element | element isCharacter ] ]) ifFalse: [ ^ self error: 'separators must be Characters.' ].<br>
- #Collectn.<br>
- "Changed 2000/04/08 For ANSI <readableString> protocol."<br>
- (separators isString or:[separators allSatisfy: [:element | element isCharacter]]) ifFalse:<br>
- [^ self error: 'separators must be Characters.'].<br>
sourceStream := ReadStream on: self.<br>
result := OrderedCollection new.<br>
+ subString := WriteStream on: String empty.<br>
+ [ sourceStream atEnd ] whileFalse:<br>
+ [ char := sourceStream next.<br>
+ (separators includes: char)<br>
+ ifTrue:<br>
+ [ subString isEmpty ifFalse:<br>
+ [ result add: subString contents.<br>
+ subString resetContents ] ]<br>
+ ifFalse: [ subString nextPut: char ] ].<br>
+ subString isEmpty ifFalse: [ result add: subString contents ].<br>
- subString := String new.<br>
- [sourceStream atEnd]<br>
- whileFalse: <br>
- [char := sourceStream next.<br>
- (separators includes: char)<br>
- ifTrue: [subString notEmpty<br>
- ifTrue: <br>
- [result add: subString copy.<br>
- subString := String new]]<br>
- ifFalse: [subString := subString , (String with: char)]].<br>
- subString notEmpty ifTrue: [result add: subString copy].<br>
^ result asArray!<br>
<br>
<br>
</blockquote></div>