Nice reply Richard - do you ever post any of these in a blog - the one below would be a great one to point to from Exercism...
> On 6 Mar 2019, at 12:48, Richard O'Keefe <[email protected]> wrote: > > As someone else already pointed out, the standard way to copy > part of any array-like sequence is > aSequence copyFrom: firstIncludedIndex to: lastIncludedIndex > > How could you have found this by yourself? > > From the background, either > Click-select Tools-select Playground > or hold Ctrl down while typing OW (for Open Workspace). > In the new Playground/workspace, type > String > then Ctrl-B. You now have a five-pane browser open on > String. > > About half way down the third panel on the top you will see > converting > copying > displaying > Click on copying. > > Guess what? You WON'T see anything that looks relevant! > Maybe it's in an ancestral class. So look at the buttons > under the top row of panes: > All packages Scoped view | Flat Hier | Inst side Class side | ... > Hier looks promising. Click it. > > Now in the second pane you will see > ProtoObject > Object > Collection > SequenceableCollection > ArrayedCollection > String > ... > Select the parent class, ArrayedCollection. > Nope, nothing promising there either! > Select the grandparent class, SequenceableCollection. > And now the 'copying' method category has quite a few > potentially interesting methods, including #copyFrom:to:. > > There are four other related methods that I would argue > are in the wrong category: > allButFirst > allButFirst: count > allButLast > allButLast: count > are in the 'accessing' category. > > If you want something a bit more flexible, > you could add > drop: d take: t > "Discard the first |d| elements of the receiver if d >= 0. > Discard the last |d| elements of the receiver if d <= 0. > Return the first |t| elements of the result if t >= 0. > Return the last |t| elements of the result if t <= 0. > The result is the same kind of collection as the receiver." > |lb ub n| > n := self size. > d abs >= n ifTrue: [^self copyEmpty]. > d < 0 > ifTrue: [lb := 1. ub := n + d] > ifFalse: [lb := d+1. ub := n]. > ub - lb + 1 <= t abs ifFalse: [ > t < 0 > ifTrue: [lb := ub + t + 1] > ifFalse: [ub := lb + t - 1]]. > ^self copyFrom: lb to: ub > > Now I would like to suggest that you not use anything like this > *directly*. Go back to the Playground, and evaluate > > String with: (Character codePoint: 256) <Ctrl-P> > > The answer is 'Ā'. Pharo supports Unicode. Now try > > String with: $A with: (Character codePoint: 16r0304) > > In Pharo, the result looks like A followed by a separate > macron, but when it's pasted into HTML it displays > correctly as 'Ā'. Pharo doesn't *quite* support Unicode. > If it did, the two strings with different lengths and no > codepoint in common would display exactly the same. > > The Unicode standard finds it necessary to distinguish > between characters, glyphs, graphemes, grapheme clusters, > codepoints, and a couple of other things. A Smalltalk > String is a sequence of *codepoints*, not a sequence of > "characters". There is no upper bound on the number of > codepoints that may be needed to encode one "character" > as the end user sees it, and from there on it gets > *complicated*. > > For over 20 years, it hasn't really made sense to think > of a string as a simply indexed sequence of characters. > Integer indices are a useful implementation-level detail > for remembering bounds from some "higher level" matching > technique, but are much less useful than you might expect. > > > > > > > > On Wed, 6 Mar 2019 at 12:00, Craig Johnson <[email protected] > <mailto:[email protected]>> wrote: > Hi All, > > > > I was trying to figure an elegant way to slice strings (Python style), and > came up empty. > > > > What is the simplest way to copy characters between positions 4 and 8 from a > string in Pharo? > > > > Craig >
