Re "Strings are wrong", the influences on my thinking went like this.
(1) As an undergraduate, I did exercises with the Euler compiler
������ (written in Burroughs Algol) and the XPL compiler (written in XPL).
������ XPL had immutable strings, rather like AWK or Java, and a PL/I-ish
������ set of operations on them.�� Burroughs Algol didn't have strings,
������ but did have pointers, that you could use to stream through arrays.
������ It turned out to be notably easier to do tokenising in Algol than
������ in XPL.
(2) A friend of mine, while a masters student, made some pocket money
������ by writing a "batch editor" (same application domain as sed, but
������ different command set) for IBM mainframes under MVS, which he did
������ using PL/I.�� PL/I fans used to point to its string operations as
������ a good collection, but he had to fight PL/I every step of the way
������ to get the string operations he needed.�� When I met UNIX V7 on a
������ PDP-11, it took me 15 pages of C to accomplish what he needed
������ more than 50 pages of PL/I to do.�� And my editor had undo...
������ The trick was being able to make just the right text abstractions
������ that I needed.
(3) A company I worked at had a program that generated assembly code
������ for several different machines from a common specification.�� The
������ original version manipulated instructions as *trees*.�� A new hire
������ was asked to write a new generator because the old one was
������ getting harder to maintain and we wanted it faster.�� His program
������ represented instructions as *strings*.�� It turned out to be
������ slower and harder to maintain than the original.
(4) I encountered Eugene Myers' AVL DAG data structure (which quite
������ efficiently lets you maintain many versions of a large text) and
������ the Rope data structure (basically a lazy concatenation tree)
������ that accompanies the Boehm garbage collector.�� Both of them get
������ a lot of efficiency out of NOT doing concatenations.
(5) Learning Java, I found that Java had taken a bullet to the head
������ which Smalltalk had dodged, and which had been very clearly
������ explained in the coloured books.�� Consider the selectors
������ #printOn: and #printString.�� There are two ways to implement
������ them: the smart (Smalltalk) and the spectacularly stupid (Java).
������ Smart way:�� #printOn: is basic, #printString is derived.
������ Stupid way: #printString is basic and #printOn: is derived.
������ Why is this smart?�� If you are generating several MB of text
������ *in order to write it to an external sink*, then #printOn:
������ does the job very efficiently.�� But #printString not only
������ turns over large amounts of memory, giving the GC more work
������ than it really needs, it is fatally easy to fall into
������ quadratic time behaviour.
(5) There's the insufficiently famous epigram by Alan Perlis:
������ "The string is a stark data structure,
�������� and everywhere it is passed there is much duplication of process.
�������� It is a perfect vehicle for hiding information."
������ One way to understand this is that it's quite easy to put
������ information *into* a string, but it can be quite hard to get
������ it out again.�� I have even run into examples where the
������ getting-it-out-reliably part was accidentally impossible.
������ What the heck, let's take Dates as an example (not of impossibility).
������ What does '180612' mean?�� What does dateString copyFrom: 3 to: 4
������ give you?�� But aData monthNumber is hard to misunderstand.
(6) Then there's the whole scripting attack (Little Bobby Tables)
������ thing.
The rule of thumb that I use is that if you are just accepting a
datum, maybe stashing it somewhere, and eventually giving it back,
then a string is fine.�� For example, considering the huge variety
in the way people's names may be structured, strings are pretty
much the ideal way to represent them.�� You *shouldn't* be extracting
"the middle initial" because some people don't *have* one and some
people have more than one.�� (I am sick of my name being rejected as
invalid by American-designed programs that insist that a surname
cannot have an apostrophe or two capital letters.�� No Irish need
apply.)�� But if you want to process structured information, you
want to get the data out of string form and into some kind of tree
as soon as you can.�� In fact, you don't want a string form in the
first place.�� I have seen people manipulating XML with string
operations, and it's not a pretty sight.
And when we're talking about something like (REAL) object-oriented
programming in a language like Pharo, we really should be thinking
in terms of objects other than strings. For example, if we take
VMS as an example, [.FOO]BAR.TXT;1 and <.FOO>BAR.TXT.1 are the
same *filename* while they are different *strings*, and resolving
the filename relative to DSK:[ICK.ACK] isn't terribly similar to
string concatenation.�� (Alphabetic case?�� Let's not go there.)
This is precisely why there are classes like FileLocator and Path.