[PATCH] Add #join: and #join:separatedBy:

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

[PATCH] Add #join: and #join:separatedBy:

Paolo Bonzini
Respectively, instance- and class-side.  The latter does not work with
any Collections, only Sequenceable ones because it does not make much
sense to add a separator if it can end up anywhere else.

This was on my list for a while.  It conflicts with Stephen's original
implementation of #join: taking a class, but it matches other languages:

   irb(main):004:0> ['abc','def'].join
   => "abcdef"
   irb(main):005:0> ['abc','def'].join(' ')
   => "abc def"

   st> #('abc' 'def') join
   'abcdef'
   st> #('abc' 'def') join: ' '
   'abc def'

Paolo

--- orig/kernel/ArrayColl.st
+++ mod/kernel/ArrayColl.st
@@ -130,6 +130,26 @@ join: aCollection
  newInst replaceFrom: start to: (start := start + subColl size) - 1
  with: subColl].
     ^newInst
+!
+
+join: aCollection separatedBy: sepCollection
+    "Where aCollection is a collection of SequenceableCollections,
+     answer a new instance with all the elements therein, in order,
+     each separated by an occurrence of sepCollection."
+    | newInst start |
+    newInst := self new: (aCollection
+ inject: sepCollection size * (aCollection size - 1)
+ into: [:size :each | size + each size]).
+
+    start := 1.
+    aCollection
+ do: [:subColl |
+    newInst replaceFrom: start to: (start := start + subColl size) - 1
+ with: subColl]
+ separatedBy: [
+    newInst replaceFrom: start to: (start := start + sepCollection size) - 1
+ with: sepCollection].
+    ^newInst
 ! !
 
 


--- orig/kernel/SeqCollect.st
+++ mod/kernel/SeqCollect.st
@@ -55,6 +55,21 @@ streamContents: aBlock
     stream truncate.
     aBlock value: stream.
     ^stream contents
+!
+
+join: aCollection separatedBy: sepCollection
+    "Where aCollection is a collection of SequenceableCollections,
+     answer a new instance with all the elements therein, in order,
+     each separated by an occurrence of sepCollection."
+    | newInst start |
+    newInst := self new: (aCollection
+ inject: sepCollection size * (aCollection size - 1)
+ into: [:size :each | size + each size]).
+
+    aCollection
+ do: [:subColl | newInst addAll: subColl]
+ separatedBy: [ newInst addAll: sepCollection].
+    ^newInst
 ! !
 
 
@@ -596,6 +611,21 @@ join
      #('hello, ' 'world') join => 'hello, world'"
     ^self isEmpty ifTrue: [#()]
   ifFalse: [self first species join: self]
+!
+
+join: sepCollection
+    "Answer a new collection like my first element, with all the
+     elements (in order) of all my elements (which should be
+     collections) separated by sepCollection.
+
+     I use my first element instead of myself as a prototype because
+     my elements are more likely to share the desired properties than
+     I am, such as in:
+
+     #('hello,' 'world') join: ' ' => 'hello, world'"
+    ^self isEmpty
+ ifTrue: [#()]
+ ifFalse: [self first species join: self separatedBy: sepCollection]
 ! !
 
 



_______________________________________________
help-smalltalk mailing list
[hidden email]
http://lists.gnu.org/mailman/listinfo/help-smalltalk