On Tue, Dec 8, 2009 at 2:32 AM, Don <[email protected]> wrote: > Based on everyone's comments, this is what I have come up with: > > -------------------- > x ^^ y is right associative, and has a precedence intermediate between > multiplication and unary operators.
Is that consistent with math? I think in math they usually write (-1)^n with parens. See for example the sin power series here: http://en.wikipedia.org/wiki/Power_series What's the rationale for going against math here? > * The type of x ^^ y is the same as the type of x * y. Like it. > * If y == 0, x ^^ y is 1. Need to mention what happens when x is also 0. > * If both x and y are integers, and y > 0, x^^y is equivalent to > { auto u = x; foreach(i; 1..y) { u *= x; } return u; } > * If both x and y are integers, and y < 0, an integer divide error occurs, > regardless of the value of x. This error is detected at compile time, if > possible. Can you explain why you think that's necessary? Seems like going too far towards a nanny compiler for no particularly good reason. The fact that 2^^-1 isn't particularly useful doesn't make it particularly error prone. No more so than integer division when the person meant floating point division. I just find it unexpected that a language would single out exponentiation for this kind of treatment. > * If either x or y are floating-point, the result is pow(x, y). > -------------------- > Rationale: > (1) Although the following special cases could be defined... > * If x == 1, x ^^ y is 1 > * If x == -1 and y is even, x^^y == 1 > * If x == -1 and y is odd, x^^y == -1 > ... they are not sufficiently useful to justify the major increase in > complexity which they introduce. Hmm, I'm not so sure about that. I saw examples of this being used even in the small sampling of search results from Python and Fortran code that I looked at. Many mathematical constructs are defined as having a leading sign of (-1)^^n (like the sin series formula linked above). > In all other cases, a negative exponent > indicates an error; it should be rewritten as (cast(real)x) ^^ y. Making > these cases errors makes everything much simpler, and allows the compiler to > use range propagation on the value of y to detect most exponentiation errors > at compile time. (If those cases are legal, the compiler can't generate an > error on x^^-2, because of the possibility that x might be 1 or -1). I didn't see this error as adding much value when there was nothing clearly lost from it. But here you're showing there is a real price to pay for this nanny compiler behavior. To me that makes the error clearly not worth the price of admission. I also think that since 0^0 and 0^-1 and such are mathematically undefined, careful users of opPow will already have to put some if() check before blindly doing an x^^y. Instead of if(x!=0 || y!=0) x^^y; the people who care can just change the check to if(x!=0 || y>0) x^^y; Doesn't changing that one operator there doesn't seem like an undue burden upon those who are careful checkers of their values. > Also note that making it an error leaves open the possibility of changing it > to a non-error later, without breaking code; but going from non-error to > error would be more difficult. I think it's pretty clear that the error goes too far right now without taking a wait-and-see stance. --bb
