Hi friends!
We have talked about exponentiation before, but the lack of an exponentiation operator that some users expect to exist has apparently been causing head-scratching diagnostics. After some discussion, it's apparent to me that one of the best ways to diagnose this specifically when operands of suitable type are used is to make a placeholder function. As that would end up actually adding an operator to the standard library, requiring Evolution approval, this gives us occasion to confirm the desire spelling of that operator and its precedence group.
I hope the pitch is...uncontroversial:
Exponentiation operator and precedence group
- Proposal: SE-NNNN
- Authors: Xiaodi Wu
- Review Manager: TBD
- Status: Awaiting review
- Implementation: apple/swift#36041
Introduction
We propose the addition of **
as the exponentiation operator, assigned to a precedence group named ExponentiationPrecedence
that is higher than MultiplicationPrecedence
.
Swift-evolution thread: [this one]
Motivation
Exponentiation facilities are currently available in Swift by importing the C standard library (via Darwin
on Apple platforms or Glibc
on Linux, or via Foundation
). Additionally, protocol-based additions to floating-point types were proposed for addition to the standard library in SE-246, which is currently available as a separate library, Swift Numerics. As in C, all of these functions are named pow
.
In many other programming languages, exponentiation is denoted by the operator ^
or **
. Currently, no such operator exists in the Swift standard library, although its inclusion has long been discussed. With SE-77, the exponentiation precedence group to which bitwise shift operators belong was renamed BitwiseShiftPrecedence
, anticipating a bifurcation in the operator hierarchy where true exponentiation is assigned its own precedence group higher than multiplication but unordered relative to bitwise shift operators.
Pending incorporation of exponentiation into the standard library, anecdotal evidence suggests sufficient attempts to use the **
operator which could justify the addition of a customized diagnostic.
What's required to provide such a tailored diagnostic that will guide users to the correct spelling pow
is either (a) a hardcoded compiler routine; or (b) an unavailable, shadowable placeholder func **
in the standard library with the message: "use 'Foundation.pow' instead". The latter option has advantages in allowing the fullest set of diagnostics to be emitted for the rest of the expression in question because the operator itself would exist; however, such an operator would need to be assigned to some precedence group, either a definitive one or a magical placeholder.
Proposed solution
We propose to settle the spelling, precedence, associativity of the exponentiation operator in this proposal. The addition of actual exponentiation facilities is covered by SE-246, and is deliberately left out of the scope of this proposal.
Settling the spelling of the operator facilitates not only superior diagnostics pending the addition of exponentiation to the standard library itself, but it also permits third-party libraries to vend implementations of the operator without each having to define the operator or its precedence group, which could lead to clashes with one another if a user imports more than one mathematical library with such definitions.
Detailed design
We propose to use the spelling **
, which is one of the two well-precedented spellings of this operator. The choice is made rather simple as we cannot repurpose the other well-precedented spelling, ^
, since it is already a standard library operator (for a bitwise operation) which is assigned a precedence not suitable for exponentiation.
We propose that the precedence group to which **
will be assigned should be spelled ExponentiationPrecedence
, in line with the spelling of MultiplicationPrecedence
and AdditionPrecedence
.
ExponentiationPrecedence
would be higher-than MultiplicationPrecedence
, as users expect based on mathematical tradition. Further, based on mathematical tradition and as precedented in other languages, ExponentiationPrecedence
would be right-associative, so that x ** y ** z
is equivalent to x ** (y ** z)
and not (x ** y) ** z
.
Note that this design fulfills the promise of SE-77 in permitting
ExponentiationPrecedence
to be deliberately unordered relative toBitwiseShiftPrecedence
; this allows Swift to require parentheses in the rare cirumstance that bitwise shift operators are used adjacent to exponentiation operators.
By analogy with other mathematical assignment operators, we would also add the exponentiation assignment operator **=
with AssignmentPrecedence
.
Source compatibility
As Swift permits end users to shadow standard library operator declarations and even to assign them to custom precedence groups, this proposal will not affect source compatibility.
Effect on ABI stability
This proposal is intended to have no implications for ABI stability. Any placeholder func **
will be annotated as unavailable and emitted into clients, so that they have no ABI footprint.
Effect on API resilience
This proposal introduces an operator and its assigned precedence group as public API. By taking these changes through the Evolution process now, we ensure that a precedence group and operator appropriate for actual use are in place which will not need to be removed in the future as mathematical facilities in the standard library are filled out. Library authors benefit in being able to define implementations of this operator without having to vend potentially clashing operator definitions.
Alternatives considered
One alternative is not to add these operators at this point in time, leaving diagnostics to be implemented solely in the compiler. We feel that the design here offers a superior outcome in terms of diagnostic quality with a minimal addition of code, with the principal drawback that it requires the Swift community to expend effort in reviewing the proposed operator now rather than later. However, as the intention is to settle a permanent spelling for exponentiation, the effort is not wasted for a merely ephemeral change.
Acknowledgments
Thanks to @varungandhi-apple for thoughtful discussion on possibilities for improving exponentiation operator diagnostics.