This was a controversial change and there are still many people who are not entirely comfortable with it. The starting point is that people do not really often expect or want x^2
and x^-1
to be pow(x, 2)
and pow(x, -1)
, respectively. Rather, people want x^2
to be syntax for x*x
and x^-1
to be a syntax for 1/x
. These can both generally be implemented much more efficiently than calling a general power function—but in completely different ways. With sufficiently clever optimizations (constant propagation + power reduction), one can potentailly optimize pow(x, 2)
into x*x
but it would be even better if we didn’t have to do such a clever optimization in the first place. It’s been a fairly common and successful strategy in the design of Julia to arrange things so that you can get great performance in a straightforward way without need for clever optimizations instead of trying to make the optimizers smarter. So what this design does is it causes x^n
where n
is a literal integer value to call Base.literal_pow(x, Val(n))
, which allows us to specialize the syntax on individual literal values like 2 or -1. This allow us to make x^2
actually mean x*x
instead of needing to try to optimize it to that. It also allows us to make negative literal exponents work without introducing a type instability in the general ^
function. And indeed, we used to get regular complaints from new users that 2^-1
doesn’t return 0.5
as they would expect, instead giving them a domain error because of the negative exponent. There are good reasons for it but users don’t care about involved language design reasons, they just want it to work. A way to think about this is that ^2
is its own operator, as is ^3
and ^-1
, and so on. Hopefully that helps.
9 Likes