Tuesday, July 20, 2021
There are reasons for operators
One particular area of software complexity is the degree to which unclear code can have unnoticed side effects, an effect that in his most recent blog post, Drew DeVault coins "Spooky code at a distance". Of the two example he gives its the first, of operator overloading, that I think is of greater interest and raises the question about what even the point of operators is and whether they make the code unnecessarily ambiguous.
All this is to say, do we really need them? Would it not be better to avoid mutation and to be explicit. If you want to add two numbers then call an add function. If you want to concatenate strings then call a concatenation function. If you want to define your own conditional subroutines, I guess use a lazy language, but then name them. I think its [sic] important to be explicit about the intent of code even if the behaviour is the same as it is easier for others to read and understand and will ultimately lead to fewer bugs. That seems to make sense, right?
There's a reason why languages have operators—it makes the code easier to reason about. For instance, is this bit of code:
/* Why yes, the "=" is an operator as well */ fassign(&xn1,fmul(fmul(fadd(fmul(A,yn),B),xn),fsub(1.0,xn))) fassign(&yn1,fmul(fmul(fadd(fmul(C,xn),D),yn),fsub(1.9,yn)))
xn1 = ((A * yn) + B) * xn * (1.0 - xn); yn1 = ((C * xn) + D) * yn * (1.0 - yn);
(also, spot the bug!)
Drew comes down on the “no-operator overloading” camp because he finds it harder to debug potential issues, performance or otherwise. But that's a trade-off he's willing to make—others might make the trade-off the other way. For instance, I found it much easier to implement the Soundex system in LPeg, which uses (or maybe abuses?) Lua's operator overloading capability. I traded development time (well, minus the time it took me to get used to LPeg) for a bit of runtime and potential difficulty in debugging. There is something to be said for conciseness of expression. I can't find a source for this, but I have heard that the number of lines a programmer can write per day is constant, regardless of language. The above equation is two lines of C (or really, any higher level langauge) but in assembly?
movss xmm0,[yn] mulss xmm0,[A] addss xmm0,[B] mulss xmm0,[xn] movss xmm1,[const1] subss xmm1,[xn] mulss xmm0,xmm1 movss [xn1],xmm0 movss xmm0,[xn] mulss xmm0,[C] addss xmm0,[D] mulss xmm0,[yn] movss xmm1,[const1] subss xmm1,[yn] mulss xmm0,xmm1 movss [yn1],xmm0
Eight times the lines of code, which seems about right for assembly—not hard, just tedious. I would think if Robert wants to use functions over operators, it's easy enough to just do it. I do wonder though, how long until he goes back to using operators?