"Can't" is very different from "can, but is very ugly."
Most of the "problems" with Ruby that are often quoted are the result of bad programming and management decisions. Ruby puts a lot of power into the hands of the programmer (not as much as IO [the langauge]) and with great power comes...flexible re-factoring! Thankfully, it should be easy to re-factor the offending code, send a note to the programmer about what you changed and why and chalk it up to a learning experience.
Sufficiently typed languages make re-factoring very easy.
If you are having a hard time debugging your Ruby, you are doing it wrong.
As for ActiveSupport's littering of Object, meh. Rails really changes Ruby. If you stick to the Rails way, then it shouldn't cause a problem in Rails projects, and it isn't a problem outside of rails projects. Don't like it? Well, there are plenty of good Ruby alternatives for the web (Sinatra!!! Also, merrrrrrrrrrrrb,) and you don't have to have everything in one app.
1) If ugliness isn't a concern, I can do everything I need to do in C++. Arguments in favor of ugliness don't get a pass just because they happen to support your favored language.
2) What does "sufficiently typed" mean? This sounds suspiciously like a tautology: "re-factoring is easy when you've written code that's easy to re-factor."
3) The "you're doing it wrong" response is zero-content. Prove that we're doing it wrong.
1) I never said it wasn't a concern. In fact, I emphasized the important difference between can't and what translates to "shouldn't" in most circumstances.
2) I apologize if i was vague. I was trying to be concise. The nature of a "Type" is not a fixed thing. Some languages are said to be strongly-typed, some are said to be weakly-typed. Some languages are type-safe, others are not. If we were to simply draw a line and suggest that one end approaches absolute Typeness and the other approaches absolute untypeness, then sufficiently typed were to mean the lowest point along this line that supports the goal. In this instance, we are talking about re-factoring. So, you may say that my argument sounds circular: "refactoring is easy when you use a language in which refactoring is easy." However, the important point that I am making is that ruby's amount and implementation of Type is what facilitates its ease of refactoring. In particular, I have found its features of reflection, its implementation of polymorphism ("duck typing"), and its hooks into the Type system (look at Object, Module, Class and Method for more info) to be particularly helpful. Also, because there is not too much typedness, we don't have to worry about sending data of a new/different type to a function as long as it satisfies the assumptions that the function makes about it (which can be inferred by a number of techniques.) Delegator and Forwardable are also pretty nifty. One of the least appreciated tricks is calling .dup on an instannce of Class (that is, an object that represents a class definition, not an instance of a class,) but thankfully it is rarely necessary. -- You need to use it when you want to a) inherit from Foo and still b) have 'super' refer to the implementation in Foo's parent class.
3) I suppose the above might give some clues into my favorite debugging techniques. If you'd like me to go further in depth, contact me via email, my name @gmail.com I didn't think the details were salient to this discussion.
Edit: c++ makes some of the worst decisions wrt supporting the notion of Type, in syntax and in features. That being said, Bjarn is still one of my favorite authors and learning C++ was a great entre into OO for me.
That's a great article. I will attempt to use more precise terms in the future.
To clarify my previous post: I intended "strong" typing to mean increasing restriction of what you can do in order to provide more guarantees about runtime behavior, and "weak" typing, the opposite.
So you really meant "static" and "dynamic", referring to type-checkers, which are completely independent of "strength" (which is commonly used to imply soundness).
Ironically, all dynamic type-checkers are more sound (by definition, they check all types at runtime) than most ancient static type-checkers that just do naive structural compile-time checks, allow casts, and mainly exist to specify size.
No, how did you infer that from what I wrote? A dynamic type system, as you pointed out, may be better at enforcing restrictions than a static one. The notion of 'strength' that I was talking about is separate from the enforcement mechanism.
Some questions that pop into my mind when i consider type systems are:
1) What are the criteria that a datum must fulfill in order to be considered of type Foo?
2) How is this to be determined?
3) Why would I ever need to know this?
1 & 3 impact the strong-weak continuum, number 2 does not. The less that type impacts allowed (at run or compile time) operations (#3), the weaker the type system. Note that you often can implement the manipulation of metadata in your language if your language does not already provide these features.
As for #1, the more stringent the criteria, the more 'strong' the given language's type system. A very weakly typed language may have no mechanism of checking for type (in such a language, the type system may only be used internally to the object for things like method resolution.) The criterion for being of a particular type may be 1) the datum supports all operations defined for a particular type 2) the datum supports all operations defined for a particular type that are used in the current execution scope 3) the datam has the name of the type in a list of types that it claims to be 4) the datum is at least as large as the size of the given type .. and many more ..
In the context of re-factoring, the less frequently type is checked and the less rigorous the criteria when it is checked, the more opportunity for type substitution (and thus more flexibility) we have.
Most of the "problems" with Ruby that are often quoted are the result of bad programming and management decisions. Ruby puts a lot of power into the hands of the programmer (not as much as IO [the langauge]) and with great power comes...flexible re-factoring! Thankfully, it should be easy to re-factor the offending code, send a note to the programmer about what you changed and why and chalk it up to a learning experience.
Sufficiently typed languages make re-factoring very easy.
If you are having a hard time debugging your Ruby, you are doing it wrong.
As for ActiveSupport's littering of Object, meh. Rails really changes Ruby. If you stick to the Rails way, then it shouldn't cause a problem in Rails projects, and it isn't a problem outside of rails projects. Don't like it? Well, there are plenty of good Ruby alternatives for the web (Sinatra!!! Also, merrrrrrrrrrrrb,) and you don't have to have everything in one app.