3 ms·
> ... a quaternion that can print itself as either 4 numbers (raw) or 3 numbers (euler angles). Then at last you presumably have overloads that are descriptive
by thelazydogsback 7y ago
> ... a quaternion that can print itself as either 4 numbers (raw) or 3 numbers (euler angles).
Then at last you presumably have overloads that are descriptive, such as .ToRawString() and .ToEulerString(), correct? If you did a cout<<q, which one are you going to get?
Having a non-abstract base .ToString() defined in Object (and that requires no format parameters) causes the issues.
Of course you could define an enum and take it as a format, like .ToString(Format.Euler), but even if you define well-named overloads, the other .ToString() is still hanging there and probably doesn't do anything useful.
So, for most cases in most current language, my statement was probably a bit strong and should be weakened to "the framework should not assume there is one best/default way to render any Object to a string regardless of context and purpose and offer a default implementation at the top of the hierarchy".
Ultimately, however, I think the stronger argument does hold, but is not easily addressed in most languages, or at least is not addressed in any consistent to concise way across many languages.
- jcelerier 7y ago> which one are you going to get? that does not really matter as long as it is consistent. If I'm doing cout << q I'm certainly just debugging or writing to some log, am most certainly in a hurry and just want to see if I'm going to get (NaN, NaN, NaN) or not.
- smilekzs 7y agoFair enough. > the framework should not assume there is one best/default way Best, probably not. Default, I'd argue that Rust's approach of defining Display and Debug traits (interfaces) in the stdlib is reasonable. It is explicit, specific, and unambiguous. While having a trait system helps a lot, it's not hard to imagine instead of a single `ToString()` defined by Object, it has `ToDebugString()`, `ToDisplayString()`, etc..