looking for answers to exercises in Squeak book Ch 2.

Bijan Parsia bparsia at email.unc.edu
Fri Apr 27 03:24:20 UTC 2001


On Thu, 26 Apr 2001 txporter at mindspring.com wrote:

> As a new Squeaker, I am slowly making my way through Mark's book on Squeak.
> 
> At the end of chapter 2, there are some exercises, specifically No. 3:
> Write a piece of workspace code [...] to do the following:
> (a) Replace all vowels in the string 'Squeak' with dashes.

Like others, I'll presume that returning a new string is kosher.

> (b) Compute the average of a set of integers in an array.
> 
> I did this like so, but think it is more like "procedural-language
> speak' and not Smalltalk.

I'm not sure that the issue is primarily procedural vs. OO (as others have
said), but Smalltalky vs. transliterated other language :)

>  Anyone have any more elegant solutions?  I particularly do not like
> the use of the aCount variable. 

As others have pointed out, at least implicitly, #do is a pretty blunt
instrument. Much joy comes from mastering the enumeration protocal,
especially the *ect: methods--#detect:, #select:, #collect:, #reject:,
#inject:into:, the combos such as #select:thenCollect: and the
"withIndex:" wonders, an so on. Each one is worth learning, and one
quickly becomes adept at using them. Manical giggling is optional, but
hard to avoid.

The *key* thing, when dealing with string, is to remember that they're
collections, indeed, that they are Arrays. So, not only are the a
bazillon useful methods in String, and not only, should you peek up the
hierachy to see what *other* groovey methods there are, but it's often
useful to stop *thinking* of them as strings and treat them just as
collections.

Which means, and I don't *think* anyone else has brought this up yet, and
which is the whole justifiction for this note, you get to use
STREAMS! with them!

And if that's not cause for estatic excitment, well then, uh, you have a
much more interesting life than me!

Here's one example:
	| strm |
	strm := (ReadWriteStream with: 'Squeak') reset.
	[strm atEnd] whileFalse: [strm peek isVowel 
					ifTrue: [strm nextPut: $-]
					ifFalse: [strm next]].
	strm contents.	

This will modify the orginal string (with the negative consequence for the
string literal that Andrew noted). But you can use #do: to iterate over
the string:
	String streamContents: [:strm | 
		'Squeak' do: [:chr |
			chr isVowel
				ifTrue: [strm nextPut: $-]
				ifFalse: [strm nextPut: chr]]].

(String>>streamContents: is *wonderful* for using WriteStreams to build up
strings. Saves some bookkeeping lines.)

(You could also setup a ReadStream on the string. Useful if you need to
make decisions based on looking ahead, etc.)

Now, this is nasty compared to the #collect: varient, but it has a *huge*
advantage...you can replace the vowels with strings instead of just
characters. 

E.g., if you replace the ifTrue: block with:
	[strm nextPut: $-; nextPut: $|]

or the more idomatic:
	[strm nextPutAll: '-|']

you'll get:
	'Sq-|-|-|k'

(Properly managed, streams are generally more speedy for concatenation.)

Cheers,
Bijan Parsia.





More information about the Squeak-dev mailing list