[Issue 8672] %% operator

d-bugmail at puremagic.com d-bugmail at puremagic.com
Sun Sep 16 16:09:31 PDT 2012


http://d.puremagic.com/issues/show_bug.cgi?id=8672



--- Comment #3 from bearophile_hugs at eml.cc 2012-09-16 16:10:21 PDT ---
(In reply to comment #1)
> Adding a new operator for an incredibly rare operation is not justified.

It's not incredibly rare, I use it all the time in Python (it's the default
one!) and I used to use it in Delphi often, and I use a function to do it in D,
so in practice I use it much more often than the C-style one. It's rare in C/D
programs just because C did a wrong design decision, and this is the built-in
:-) Programmers usually stick with what's offered to them by the language,
often even it's not good. This is also why programmers sometimes switch to
newer/better languages: to have a whole new set of _better_ defaults/features.


> A library function should be used for this, if it matters at all, and I am not
> convinced it does.
> 
> As Don pointed out to me, there is no "mathematical" definiton of modulus.

This enhancement request refers to the Python one...


> And
> as http://en.wikipedia.org/wiki/Modulo_operation makes clear, there is no
> consistent definition of it in programming languages, with four different
> definitions of it in use, not including "implementation defined" ones.

Making it "implementation defined" makes it nearly useless, killing code
portability. Even C99 designers have understood this.

Most languages use one of two versions. D uses one of those two, and Python the
other two. Ada has both (and I think Ada doesn't have any other ones).


> To say one version of modulus is "bug prone" and the other is not, is itself
> erroneous.
> 
> There is simply no getting around the fact that the programmer needs to be
> aware of what result he is trying to achieve with negative numbers.

While this is generally right, in my opinion in this case this is not true.

Despite Python not being C, it doesn't break C99 "compatibily" randomly: Python
designers have put the currently used modulus preferring it over the C99
version. And I believe they have done the right choice.


The topic was discussed a bit in this thread:
http://forum.dlang.org/thread/k05nqv$2s3v$1@digitalmars.com

There I have shown an example, reduced from a larger program. This little
function has to look for the next true value in a circular array 'data', before
or after a given starting index, according to a int 'movement' variable that is
allowed to be only +1 or -1:


This is Python code, it correctly performs the wrap-around in all cases:


def find_next(data, index, movement):
     assert movement == 1 or movement == -1
     while True:
         index = (index + movement) % len(data)
         if data[index]:
             break
     return index

#         0      1      2      3      4     5
data = [False, False, False, False, True, False]
print find_next(data, 5, -1) # OK, prints 4
print find_next(data, 0, -1) # OK, prints 4


The D code doesn't work, because of the C %:


size_t findNext(in bool[] data, size_t index, in int movement)
pure nothrow in {
     assert(movement == 1 || movement == -1);
} body {
     do {
         index = (index + movement) % data.length;
     } while (!data[index]);
     return index;
}

void main() {
     import std.stdio;
     //              0      1      2      3      4     5
     const data = [false, false, false, false, true, false];

     writeln(findNext(data, 5, -1)); // OK, prints 4
     writeln(findNext(data, 0, -1)); // not OK
}


To make the D code work, you first of all have to be aware of the C99 semantics
of moduls, and then you have to introduce a workaround, with longer code. In
Python the code works naturally even when numbers are negative.

Using the D built-in % operator is a landmine, it's safe for unsigned integers.
For signed integers that can be negative you have to take extra care. So you
are of course true "the programmer needs to be aware", but the same phrase is
true for everything. Being not bug-prone means the programmer needs to be less
aware, needs to keep in mind a smaller number of things to produce correct
code.

In the end I understand that adding a new operator is asking a lot, so a
library function is enough. But I don't agree that the built-in modulus
operator is "good enough".

-- 
Configure issuemail: http://d.puremagic.com/issues/userprefs.cgi?tab=email
------- You are receiving this mail because: -------


More information about the Digitalmars-d-bugs mailing list