[Newbies] Remove trailing spaces of aString
David T. Lewis
lewis at mail.msen.com
Sat Apr 28 15:12:23 UTC 2012
On Sat, Apr 28, 2012 at 10:14:04AM +0200, H. Hirzel wrote:
> On 4/28/12, David T. Lewis <lewis at mail.msen.com> wrote:
> > I'll note that 'trimRight' is a poorly considered change in Pharo.
> > A name like 'withoutTrailingBlanks' implies making a copy of the
> > original string, but with the trailing blanks removed. That is of
> > course exactly what the method is supposed to do. But the name
> > 'trimRight' implies an operation on the receiver itself, as in
> > "trim something from the right of this string". This is not at all
> > what you want, and it is not what the method actually does either.
> > Smalltalk makes it very easy to make changes like this, but this
> > also makes it quite important to think about the meaning of the
> > names used for your methods and classes.
> > It is also important to use some common sense when changing the
> > names of methods that other people may be using. It is often the
> > case that you will not know about all of the people who may be
> > using your classes and methods, so changing their names carelessly
> > can have unintended side effects. This was the case for me with
> > the 'trimRight' name change, which caused a number of annoying
> > problems for a package that I maintain.
> Thank you for this clarification, Dave.
> A follow up question: How did you deal with this to make code work in
> Pharo and Squeak?
> Which coding pattern did you use?
There are a couple of approaches that can be used. I have not
yet addressed the problem with trimRight (which affects CommandShell
when running under the latest Pharo). I'm not sure that there are
any "good" ways to address the issue, but here are a couple of
approaches that would work.
One approach is to just re-implement the needed functionality as
a private method in your own package, so the new method might
be something like MyClass>>withBlanksTrimmed: aString. This is
a dangerous approach in this case though, because it requires your
private method to know something about strings and characters, and
it might break at some time in the future when someone makes an
improvement to String, or when someone tries to use MyClass with
a string encoded with Arabic characters.
A second approach is to use a runtime test to figure out what
selector to use. In this case, if we know that most imags implement
#withBlanksTrimmed, but one variant has decided to use #trimRight
instead, we can do something like this:
myString := 'this is a test '.
(myString respondsTo: #trimRight)
ifTrue: [ "this is probably a recent Pharo image"
myString perform: #trimRight ]
ifFalse: [ "this is how it works for everybody else "
myString perform: #withBlanksTrimmed]
Note that #perform is used to send the message. This allows you
to compile the method on either Squeak or Pharo regardless of whether
#trimRight is implemented in your image.
A similar approach can be used for classes, so you can write things
Smalltalk at: #FooClass ifPresent: [ :fooClass | fooClass new ]
If you are writing a large package that needs to deal with issues like
this, it is a good idea to isolate the differences in a compatability
layer that permits your package to run on various images, and localizes
the differences in the compatibility package. An excellent example of
this is the Grease package that is used with Seaside (and others) to
allow Seaside to run on a wide range of platforms and images.
Of course the best approach of all is to not make unnecessary changes
to well-known method names in the first place. That avoids the problem
of a minor "improvement" in a core package leading to compatibility
hacks in the packages that depend on it. But often you will have no
control over this, so the solution is to work around the problem as
described above, or rely on a compatability layer such as Grease.
More information about the Beginners