TE
TechEcho
Home24h TopNewestBestAskShowJobs
GitHubTwitter
Home

TechEcho

A tech news platform built with Next.js, providing global tech news and discussions.

GitHubTwitter

Home

HomeNewestBestAskShowJobs

Resources

HackerNews APIOriginal HackerNewsNext.js

© 2025 TechEcho. All rights reserved.

A rant about Ruby 1.9 String encoding

86 pointsby dboydabout 15 years ago

14 comments

pilifabout 15 years ago
Rants about strings and character sets that contain words of the following spirit are usually neither correct nor worth of any further thought:<p><pre><code> &#62; It's a +String+ for crying out loud! What other &#62; language requires you to understand this &#62; level of complexity just to work with strings?! </code></pre> clearly the author lives in his ivory tower of english language environments where he is able to say that he "switched to UTF-8" without actually really have done so because the parts of UTF-8 he uses work exactly the same as the ASCII he used before.<p>But the rest of the world works differently.<p>Data can appear in all kinds of encodings and can be required to be in different other kinds of encodings. Some of those can be converted into each other; some Japanese encodings (Ruby's creator is Japanese) can't be converted to a unicode representation for example.<p>Also, I'm often seing the misunderstanding that "Unicode" is a string encoding. It's not. UTF-(8|16) is. Or UCS2 (though that one is basically broken because it can't represent all of Unicode).<p>Nowadays, as a programming language, you have three options of handling strings:<p>1) pretend they are bytes.<p>This is what older languages have done and what ruby 1.8 does. This of curse means that your application has to keep track of encodings. Basically for every string you keep in your application, you need to also keep track what it is encoded in. When concatenating a string of encoding a to another string you already have that is in encoding b, you must do the conversion manually.<p>Additionally, because strings are bytes and the programming language doesn't care about encoding, you basically can't use any of the built-in string handling routines because they assume each byte representing one character.<p>Of course, if you are one of these lucky english UTF-8 users, getting data in ASCII and english text in UTF-8, you can easily "switch" your application to UTF-8 by still pretending strings to be bytes because, well, they are. For all intents and purposes, your UTF-8 is just ASCII called UTF-8.<p>This is what the author of the linked post wanted.<p>2) use an internal unicode representation<p>This is what Python 3 does and what I feel to be a very elegant solution if it works for you: A String is just a collection of Unicode code points. Strings don't worry about encoding. String operations don't worry about it. Only I/O worries about encoding. So whenever you get data from the outside, you need to know what encoding it is in and then you decode it to convert it to a string. Conversely, whenever you want to actually output one of these strings, you need to know in what encoding you need the data and then encode that sequence of Unicode code points to any of these encodings.<p>You will never be able to convert a bunch of bytes into a string or vice versa without going through some explicit encoding/decoding.<p>This of course has some overhead associated with it, as you always have to do the encoding and because operations on that internal collection of unicode code points might be slower than the simple array-of-byte-based approach.<p>And whenever you receive data in an encoding that cannot be represented with Unicode code points and whenever you need to send out data in that encoding, then, you are screwed.<p>This is a defficiency in the Unicode standard. Unicode was specifically made so that it can be used to represent every encoding, but it turns out that it can't correctly represent some Japanese encodings.<p>3) Store an encoding with each string and expose the strings contents and the encoding<p>This is what ruby 1.9 does. It combined methods 1 and 2: It allows you to chose whatever internal encoding you need, it allows you to convert from one encoding to the other and it removes the need to externally keep book of every strings encoding.<p>You can still use the languages string library functions because they are aware of the encoding and usually do the right thing (minus, of course, bugs)<p>As this method is independent of the (broken?) Unicode standard, you would never get into the situation where just reading data in some encoding makes you unable to write the same data back in the same encoding as in this case, you would just create a string using this problematic encoding and do your stuff on that.<p>Nothing prevents the author of the linked post to use ruby 1.9's facility to do exactly what python 3 does (of course, again, ignoring the Unicode issue) by internally keeping all strings in, say, UTF-16. You would transcode all incoming and outgoing data to and from that encoding. You would do all string operations on that application-internal representation.<p>A language throwing an exception when you concatenate a Latin 1-String to a UTF-8 string is <i>a good thing</i>! You see: Once that concatenation happened by accident, it's really hard to detect and fix.<p>At least it's fixable though because not every Latin1-String is also a UTF-8 string. But if it so happens that you concatenate, say Latin1 and Latin8 by accident, then you are really screwed and there's no way to find out where Latin1 ends and Latin8 begins.<p>In todays small world, you <i>want</i> that exception to be thrown.<p>Conclusion<p>What I find really amazing about this complicated problem of character encoding is the fact that nobody feels it's complicated because it usually just works - especially method 1 described above that has constantly being used in years past and also is very convenient to work with.<p>Also, it still works.<p>Until your application leaves your country and gets used in countries where people don't speak ASCII (or Latin1). Then all these interesting problems arise.<p>Until then, you are annoyed by every of the methods I described but method 1.<p>Then, you will understand what great service Python 3 has done for you and you'll switch to Python 3 which has very clear rules and seems to work for you.<p>And then you'll have to deal with the japanese encoding problem and you'll have to use binary bytes all over the place and have to stop using strings altogether because just reading input data destroys it.<p>And then you might finally see the light and begin to care for the seemingly complicated method 3.<p>Sorry for the novel, but character encodings are a pet-peeve of mine.
评论 #1213841 未加载
halostatueabout 15 years ago
I know nothing about the author, but there are some statements made that suggest that the author hasn't had to deal with the wild-and-woolly reality of encodings out there in a lot of extant data. One only <i>wishes</i> that all data were UTF-8.<p>What Ruby 1.9 gets absolutely right is that its String implementation is completely encoding agnostic (by which I <i>specifically</i> mean that it doesn't force your data to be encoded in a particular way). There are encodings for which there is no safe UTF-8 roundtrip (you can successfully convert the data to UTF-8 nicely, but when you convert back to UTF-8 to that encoding, you won't get the original input back; you'll get a slightly different output).<p>Rubyists in Japan don't have the luxury of dealing with Unicode all the time; they still get lots of data in ShiftJIS and other encodings. (The same is true of Rubyists elsewhere, but since US-ASCII is a proper subset of UTF-8, most folks don't know the difference; Win1252 is a pain in the ass, though.) If you have to do ANY work with older data formats, you curse languages that force you to use UTF-8 all the time instead of letting you work with the native data.<p>Most developers don't think about i18n nearly enough in any case; there's a lot more to worry about that simply using Unicode doesn't solve for you. Even the developers of Ruby have to worry about the fact that LATIN SMALL LETTER E WITH ACUTE (U+00E9) is the same as LATIN SMALL LETTER E (U+0065) COMBINING ACUTE ACCENT (U+0301); it doesn't begin to address the capitalization of 'ß' ('SS', which isn't necessarily reversible) or that in Turkish 'ı' capitalizes to 'I', but 'i' capitalizes to 'İ'. Don't EVEN get me started on number formatting...<p>EDIT: Added the last paragraph.
评论 #1162730 未加载
评论 #1162577 未加载
评论 #1163469 未加载
tenderloveabout 15 years ago
Dealing with string encoding is sometimes a PITA. But I think as English speakers, we are usually sheltered from the problem because most programming languages are English centric. I'd like to hear opinions from people who don't speak English.<p>If you think the way 1.8 handles (or doesn't handle) encoding is just fine, try things you typically do, but with a different language.<p>For example:<p><pre><code> ruby -ryaml -e'p YAML.dump("こんにちは!")' </code></pre> You might also try things like inserting in to a database, parsing documents, etc.<p>IMO, not having an encoding associated with some text sucks if you're a non-english speaker.
评论 #1162739 未加载
pkulakabout 15 years ago
I agree. I'd say a good 5% of development time on a new Ruby 1.9 project of mine has been spent dealing with strings. I've taken to the idea that as long as _everything_ is UTF-8, then I'll be okay, but good luck enforcing that! Especially since the whole word seems to default to ASCII, while actually _using_ multi-byte chars anyway. I think I've got it now, but no, not really. It just works on my development machine. On my server, where it actually counts, I'm getting garbage where I should be getting an accent. I've spend two days now just trying to figure out how to debug something like that!
harpastumabout 15 years ago
This "rant" is just a part of an effort by the author to catalog the behavior of strings in ruby 1.9. You can see the whole project here: <a href="http://github.com/candlerb/string19" rel="nofollow">http://github.com/candlerb/string19</a><p>The main (runnable) documentation file is here: <a href="http://github.com/candlerb/string19/blob/master/string19.rb" rel="nofollow">http://github.com/candlerb/string19/blob/master/string19.rb</a>
alextgordonabout 15 years ago
It seems the most obvious solution is to store strings in a standard encoding (say UTF-8) and to always convert strings to it at the time of their creation. Is there a technical reason why Ruby doesn't do this?
评论 #1162429 未加载
评论 #1162487 未加载
评论 #1162505 未加载
评论 #1162447 未加载
评论 #1162440 未加载
评论 #1162469 未加载
评论 #1163494 未加载
评论 #1162437 未加载
mtarnovanabout 15 years ago
Having given up porting a medium-sized Rails application to Ruby 1.9 just last week I though I'd share some of my experience. Ruby 1.9's String implementation is fine, but will require lots of changing to existing code. Rails 2.3.5 is definitely _not_ ready for Ruby 1.9 and UTF-8. For example some regexps in helpers are not encoding aware, rack 1.0.1 which is required by 2.3.5 doesn't play nicely with encodings and many more small and annoying problems (template encoding for example; the app I was porting mostly uses HAML which supports Ruby 1.9's string encodings in the latest versions; but no luck for the few erb templates)<p>All in all, this is a huge transition which will take a while to propagate through the hole Rails stack.
vegaiabout 15 years ago
My sup (on ruby 1.9) just <i>crashed</i> on me because I dared to try to write a mail with UTF8 in it.<p>This is not a trivial screwup! This is the sort of screwup that should make everybody who's using that wretched platform think thrice before continuing to use it.
smallpaulabout 15 years ago
I believe that Python, Java, C#, Objective-C and Javascript <i>all</i> have the same basic approach to this problem. The Ruby way is better for handling some Japan-specific problems. But that's at the cost of making life harder and less predictable for everyone else.<p>It's a pretty straightforward tradeoff. Of course people who are not Japanese will naturally be upset to pay a cost in complexity for a feature of benefit primarily to a programmers from a single country. Non-Japanese Ruby programmers will just have to decide whether their solidarity with Japanese programmers outweighs their personal and collective inconvenience.
AdamNabout 15 years ago
It seems like this would be a problem on Python as well, no?
评论 #1162430 未加载
kuleabout 15 years ago
He has posted some alternatives too<p><a href="http://github.com/candlerb/string19/blob/master/alternatives.markdown" rel="nofollow">http://github.com/candlerb/string19/blob/master/alternatives...</a><p>The first suggestion seems like the logical solution to me however I don't need to deal with this stuff on a day-to-day basis...
old-greggabout 15 years ago
Extrapolating, the same rant applies to all duck-typed languages: the number of possible outcomes for a=b+c explodes depending on types and contents of a,b and c, therefore his first assumption about one dimensional space is incorrect.<p>This is why most C++ teams prohibit their members to overload operators.
评论 #1163334 未加载
评论 #1163161 未加载
rueabout 15 years ago
AOL. 1.9's encoding support feels thoroughly wrong to me.
vegaiabout 15 years ago
"even Ruby's creators, who are extremely bright people"<p>There's a hidden "it turns out that" in this sentence.