By "module system", I mean a way to handle namespacing.
I checked a few facts out, and it's actually less bad than I thought. The main problem I see is that it doesn't warn you of collisions when including modules. But if you catch a collision yourself, you can resolve it.
About throw/catch and raise/rescue. First, why have throw/catch and not have it do what it does in every single other langage? I guess this is debatable.
Secondly, a problem with throw/catch is that there is no "clean" way to know if you exited via a throw or normally (the hackish way involves a boolean variable). I guess you could argue that it isn't the intended use. I'm missing this because of the following point.
My real grief with raise/rescue is that it acts exactly like Java's throw/catch, while it could be so much more. Why couldn't we throw arbitrary objects? And pass arbitrary objects to rescue, which would have a special method (lets call it "catches?(e)") that would check if the objects "matches" a thing that was thrown. Exception classes would have this as a class method, and it would match its own instances.
This, incidentally, is exactly how the ruby case statement works. In that case, the special method is "===". So that's an inconsistency in the langage right there I'd say. Or at the very least, a missed opportunity.
So ok, maybe not "mistakes" if that's too strong of a word for you. But "things that should change"? Definitely.
1. You shouldn't be including modules without knowing what you're including.
2. throw/catch isn't an exception handling system. You do have a clean way to know whether you exited via throw or normally; see http://rubylearning.com/blog/2011/07/12/throw-catch-raise-re... for details (it's a nice little summary). The problem is that you seem to think that throw/catch is for exception handling because everyone else uses those terms for exceptions.
My understanding is that throw/catch (while used less often) is cheaper to set up than begin/raise/rescue/ensure/end.
3. raise/rescue does behave like Java's throw/catch in that it's explicitly for exception handling. As far as throwing arbitrary objects, let me share a beauty from C++:
try
{
throw 0;
}
catch (...) // The only thing that catches 0.
{
}
C++ doesn't restrict what objects can be thrown. It's a horrendous disaster for the language. Exceptions—including stack unwinding, etc.—are hideously expensive (and they're worse in Java with checked/unchecked exceptions) and should be used only for the worst possible things.
You want raise/rescue to work like throw/catch. If you want that, use throw/catch and save raise/rescue for real exception handling. Or even ignore both of them.
I think that what you've described are neither mistakes, inconsistencies, missed opportunities, or things that should change.
4. I didn't use an argument from ad hominem. I carefully deconstructed the argument on technical merits and noted that these sorts of arguments come from ignorance—of which I have in spades on many topics. I also noted that it is harder to swallow the arrogance that deems arguments from ignorance as "mistakes". Both of these statements are factual.
True story: like many people who discovered Ruby after having used a number of different languages, I had substantive amounts of ignorance about why the language was what it was. In 2002—having just picked up the language, I suggested that nil should act like NULL in SQL (e.g., only tested through special case handling). This was ignorance. It was also arrogance to suggest this for a language that at the time I had been using for less than a month.
I thought I argued the point very well and looking at the follow-ups, it wasn't as bad as I remembered, but the proposal wasn't very…Rubyish. (Going back through to find a few other examples, I found this gem <http://blade.nagaokaut.ac.jp/cgi-bin/scat.rb/ruby/ruby-talk/...; and I can think of several cases, including the original PDF::Writer, where I had to do just that.)
It is harder to correct a problem of arrogance than a problem of ignorance. The person who wrote the original list was both ignorant (new to Ruby, to be expected, and explicitly Not A Problem) and arrogant (labelling them as mistakes with Ruby as opposed to decisions/behaviours that weren't understood). There's a lot that I don't understand about Python, but I am (at this point, past 40) no longer so arrogant that I declare the explicit self or the way that len(x) is implemented to be mistakes in the design of the language (even though I think they are warts that make Python much less pleasant for me to use).
About throw/catch and raise/rescue. First, why have throw/catch and not have it do what it does in every single other langage? I guess this is debatable.
Secondly, a problem with throw/catch is that there is no "clean" way to know if you exited via a throw or normally (the hackish way involves a boolean variable). I guess you could argue that it isn't the intended use. I'm missing this because of the following point.
My real grief with raise/rescue is that it acts exactly like Java's throw/catch, while it could be so much more. Why couldn't we throw arbitrary objects? And pass arbitrary objects to rescue, which would have a special method (lets call it "catches?(e)") that would check if the objects "matches" a thing that was thrown. Exception classes would have this as a class method, and it would match its own instances.
This, incidentally, is exactly how the ruby case statement works. In that case, the special method is "===". So that's an inconsistency in the langage right there I'd say. Or at the very least, a missed opportunity.
So ok, maybe not "mistakes" if that's too strong of a word for you. But "things that should change"? Definitely.
Also, ad hominems are lame.