[erlang-questions] Strings as Lists
Thu Feb 14 20:25:21 CET 2008
On Feb 13, 2008, at 8:02 PM, Richard A.O'Keefe wrote:
> On 13 Feb 2008, at 12:41 pm, Kevin Scaldeferri wrote:
>> Hold on... lists aren't really a particular convenient or efficient
>> data structure for working with strings.
> For some people they are.
>> First off, I append to
>> strings a lot more than I prepend to them.
> I take this to mean that you do stuff like
> S0 = ~0~,
> S1 = S0 ++ ~1~,
> Sn = Sn_1 ++ ~n~
No, certainly not one character at a time. But I frequently build up
an HTML document or some report piece by piece.
> perhaps in a loop. Right, this is not efficient. But it is
> inefficient in programming languages with more conventional
> It is O(n**2).
No, in a decent string implementation it is O(n).
> For example,
> x = ""
> for (i = 1; i <= 100000; i++) x = x "a"
> just took 30.5 seconds in awk on my machine, 62.2 seconds in Perl,
> and a massive
> 631 seconds in Java.
You either have a very old perl, a very slow machine, or have
implemented it quite badly:
% time perl -le 'my $x = ""; $x .= "a" for 1..100_000; print length $x'
perl -le '...' 0.02s user 0.00s system 89% cpu 0.024 total
even faster (but even less realistic, and not really the same
% time perl -le 'my $x = "a" x 100_000; print length $x'
perl -le '...' 0.00s user 0.00s system 85% cpu 0.006 total
>> Yeah, I could work with
>> reversed strings, but that's a hack to deal with using the wrong data
> No, it has to do with the fact that appending on the right is O(n)
> whether one uses lists or arrays. Arguably, you should be using the
> right data type THE RIGHT WAY. Can you provide an example of your
Someone else explained how C++ strings/vectors handle this. Perl uses
essentially the same strategy.
>> Plus, I probably prefix match more often than suffix matching
>> (although this is less lopsided than append vs. prepend). Of course,
>> I also like to do substring matching and regular expressions quite a
>> bit, and Boyer-Moore is definitely more efficient with arrays than
> The Boyer-Moore algorithm requires space proportional to the alphabet
> The Unicode alphabet size is enormous (last time I looked there were
> 100 000 characters defined).
If you use UTF-8 encoded strings, you can use Boyer-Moore unmodified
(matching at the level of bytes, rather than characters). For a fixed
width encoding, you can also work with bytes, but you'll have to take
the character width into account when considering how to slide.
> Unicode substring matching is
> definitely nasty,
> given that, for example, you would like (e,floating acute) to match
> é, and
> the Boyer-Moore algorithm assumes a unique encoding of any given
> which Unicode does not even begin to have. Then there are fun things
> U+0028 is the code for the "(" character, but if I see a "(" and go
> for it, I might have to look for a U+0029 instead,
Indeed, Unicode is really a PITA like this, but I don't think a list
representation makes this magically go away, either. In fact, in your
example with combining characters, you need to be able to backtrack,
which is more awkward and less performant on lists than arrays. But,
if you disagree, I think this would be a very interesting sort of
benchmark to do. Currently, Erlang appears to perform quite awfully
on anything to do with strings:
Now, most of these conflate string handling and file I/O, so it could
be that file I/O is more of the problem. Or maybe they are badly
implemented. Since you (and many on this list) are concerned highly
with Unicode string handling, I think it would be quite interested to
design a benchmark of that. Perhaps something that did substring (or
regexp) matching on a large number of candidate strings. Perhaps
Erlang would do better. Certainly I'd expect it to be much less code
than C/C++ (although that's practically a given). I'd be very
interested to compare to Perl's Unicode strings, or Java.
>> It's probably worth noting that none of the languages which are
>> considered _good_ for working with strings (AFAIK) use a list
> Not really. Perl is normally "considered _good_ for working with
> but it is pretty much hopeless at building strings by concatenation.
I hope I've demonstrated above that this claim is false.
More information about the erlang-questions