But in all seriousness that's pretty much antithetical to zig's goals regarding explicitness.
But in all seriousness that's pretty much antithetical to zig's goals regarding explicitness.
But I wound up being convinced that on balance it was a good thing. But I was able to inculcate a culture that operator overloading should be restricted to the creation of user arithmetic types.
Not allowing the overloading of unary *, &, and dot also help discourage non-arithmetic overloading.
Because operators "should not be function calls"?
That would make zig unusable on soft float/soft div architectures, or would have to get rid of / for division and operators for floats.
But I would also assume add() is inlined and not be a function call in a sane language/compiler, so the explicitness even falls apart from the start.
Odin proved it that it can be made efficiently while keeping sanity
And vec2 + vec2 can probably be unambiguously translated to assembly code while mat4 * mat4 is an other story. In most cases it should be a function call, and not a trivial one, with SIMD it can be relatively fast but still several orders of magnitude slower than 1 + 1. (we're talking about more than 500 scalar-equivalent operations)
And unfortunately, from my experience, if you let people (especially new coders) use this kind of powerful syntactic sugar they tend to ignore the performance characteristics because it look so simple and basic, like if the CPU had a special instruction to multiply two 4x4 matrices.
I prefer when the function call is explicit, it is a bit more cumbersome to write, but there is less hidden complexity.
you hide and obfuscate basic operations with functions, that's worse, specially when you have to chain arithmetic operations, with functions it becomes ugly and unreadable
This is exactly the point.
Neither is dividing floats, especially not on a softfloat & softdiv architecture. And yet, Zig is perfectly OK with you using division between 2 floats. Why does it get to insert expensive function calls behind operators but I can't?
Zig also lets you do remainder division for floats, which is also not a "basic operation." It's slower even then taking the sqrt of a float! Zig then also has specialized operators like saturating addition, which also isn't a "basic operation"
And then Zig also has `*` for array multiplication and `++` for array concatenation. Those are compile-time only, but still deviates from "basic operations only" territory surely. And also Zig overloads `||` to allow for the merging of enums (sorry, "error sets"), rather than only being a boolean OR.
Matrix multiplication are “basic operations” in the sense that you use them as the basic block of your algorithms, and in code using such blocks you really appreciate having a simple operator for those instead of littering your formula with functions calls (which is basically writing your formulas in Polish notation, not the most legible way to write formulas …)
why? operator overloading doesn't help you solve any problems. you can have the readability with methods which are named appropriately.
operator overloading seems so powerful and useful until you realize one day that it only changes the appearance of things, and makes no difference whatsoever to anything you are actually doing.
https://dlang.org/phobos/std_checkedint.html
where operator overloading is used to create variations on integer types, like specifying the behavior when overflow happens.
Besides, `a + b / (c * d)` is far more readable than `add(a, div(b, mul(c, d)));
You can though, just implement the relevant typeclass.
Not only that, but you can straight up shadow existing operators.
Just because people misuse operator overloading doesn't mean it should be removed from the language.
Also function overloads should never be allowed, either. After all, that's not explicit and the only thing that ever matters is being obsessively explicit for the sake of being explicit. How can I possibly tell what `min(a, b)` is going to do if function overloads or templates or macros exist?!? UNREADABLE!
I think at this point it's pretty well established that operator overloading is a net-good, and languages that don't have it end up with far more bugs than languages that do. Or they come up with arbitrary nonsense rules on why some types are allowed to have it but not your types you dirty filthy casual. Looking at you, Java, where the Integer class is allowed to overload operators but BigInteger isn't. Which, then again, is something Scala and Kotlin immediately completely reversed.