The good thing about these exercises is that you know about new selectors,
I didn't know there was an #allButLast and #allButLastDo:.

Regards,

Esteban A. Maringolo


On Fri, May 17, 2019 at 5:44 AM Sven Van Caekenberghe <s...@stfx.eu> wrote:

> I would make that
>
> ^ String new: gifts size * 10 streamContents: [ :stream |
>     gifts allButLastDo: [:each |
>       stream nextPutAll: each; nextPutAll: ', '].
>     stream nextPutAll: 'and '; nextPutAll: gifts last ]
>
> Your iteration is well done, clear and to the point.
>
> > On 17 May 2019, at 02:44, Richard O'Keefe <rao...@gmail.com> wrote:
> >
> > stream := WriteStream on: (String new: gifts size * "estimated size per
> gift" 10).
> > "The number after #new: is the *initial* allocation; the stream will
> reallocate it
> >  as needed."
> > gifts allButLastDo: [:each |
> >    stream nextPutAll: each; nextPutAll: ', '].
> > stream nextPutAll: 'and '; nextPutAll: gifts last.
> > ^stream contents
> > Using #allButLastDo: saves making a copy of (most of) gifts.
> > How could you find out about these things?
> >
> > You want to join some strings, so you look for a "join" method in String
> and you
> > will find
> >
> >     join: aCollection
> >       ^ self class new: (aCollection size * self size) streamContents:
> [:stream |
> >             aCollection
> >               do: [:each | stream nextPutAll: each asString]
> >               separatedBy: [stream nextPutAll: self]]
> >
> >
> > You might wonder if there is already something close to what you want,
> so you
> > might enter "commas" into Spotter.  If you did that, you would find
> > Collection>>asCommaStringAnd so that the whole thing is very nearly
> >     gifts asCommaStringAnd
> >
> > Just as the concatenation selector #, works with most kinds of sequences,
> > so building sequences up using a WriteStream works with most kinds of
> sequences.
> >
> > Let's work through a little example.  We are just going to build up the
> string
> > 'Quick' one character at a time.
> > s := ''.
> > s := s , 'Q'.   "creates a new string holding 'Q'"
> > s := s , 'u'.   "creates a new string holding 'Qu'"
> > s := s , 'i'.   "creates a new string holding 'Qui'"
> > s := s , 'c'.   "creates a new string holding 'Quic'"
> > s := s , 'k'.   "creates a new string holding 'Quick'"
> >
> > You see that building a string of n characters will actually create n
> new strings,
> > all but the last of which will be thrown away, taking O(n**2) time.
> >
> > Now let's use a stream.
> > w := WriteStream on: (String new: 4).  "Yes, I know that's too small."
> > w nextPutAll: 'Q'. "The stream now holds 'Q...' in its buffer."
> > w nextPutAll: 'u'. "The stream now holds 'Qu..' in its buffer."
> > w nextPutAll: 'i'. "The stream now holds 'Qui.' in its buffer."
> > w nextPutAll: 'c'. "The stream now holds 'Quic' in its buffer."
> > s nextPutAll: 'k'. "There is no room left in the buffer, so the stream
> allocates
> >                     a new buffer twice the size and copies the old one
> into it.
> >                     Now it has 'Quic....' and it has room.
> >                     The stream now holds 'Quick...' in its buffer."
> > s := w contents.   "We are asking for the defined elements of the buffer.
> >                     This means s := buffer copyFrom: 1 to: w position."
> >
> > You see that building a string of n characters this way requires a
> minimum of
> > two strings, the buffer and the final result.  The buffer may be
> periodically
> > resized, but growing by doubling means the average cost is still O(n).
> >
> > Let's time these to get an idea.
> > Time millisecondsToRun: [
> >       |s|
> >       s := ''.
> >       1 to: 10000 do: [:i |
> >               s := s , i printString].
> >       s size]
> > => 124
> > Time millisecondsToRun: [
> >       |w|
> >       w := WriteStream on: (String new: 10000).
> >       1 to: 10000 do: [:i |
> >               w nextPutAll: i printString].
> >       w contents size]
> > => 7
> >
> > This is exactly the reason that Java has both String and StringBuilder.
> > The tragedy of Java (well, not the only one) is that they had the example
> > of Smalltalk before them, showing very very clearly that the best way to
> > handle object to text conversion is to use #printOn: as the primitive,
> > not #printString, and they *still* went ahead and did the worse thing.
> > (Ruby has even less excuse for privileging to_s.)
> >
> > There are quite a few books about Smalltalk available as free PDFs from
> > the Pharo web site, a wonderful resource.  The Blue Book (Smalltalk-80
> > The Language and its Implementation) describes streams in Chapter 12.
> >
> >
> > On Fri, 17 May 2019 at 07:21, Roelof Wobben <r.wob...@home.nl> wrote:
> > Hello,
> >
> > Im testing all my solutions with critiz and can solve almost all
> problems,
> >
> > Only this one I cannot figure out.
> >
> > I have this code
> > (gifts allButLast
> >                 inject: ''
> >                 into: [ :str :each | str , each , ', ' ]) , 'and ' ,
> gifts last ]
> >
> > and critiz says I should use a stream .
> >
> > How can I make this work ?
> >
> > Roelof
> >
> >
>
>
>

Reply via email to