A more interesting question would be, in my opinion, what is the use case for this operator? Is there any particular code that it would make better? Standard library provides a family of xxxReportingOverflow methods.
Operators are useful in that you can combine them into more complex expressions. But with this particular operator, the return type is quite different and so the result of ?/ should immediately be processed (unwrapped, pattern matched, etc.) somehow.
if let result = x ?/ y {
...
}
does not look much better than
if x.dividedReportingOverflow(by: y).overflow {
...
}
These methods, in fact, have one useful property that returning Optional doesn't, they don't lose information, since the partial result is returned along with the overflow flag.
Besides:
extension BinaryInteger {
public static func ?/ (lhs: Self, rhs: Self) -> Self? {
let (overflow, result) = lhs.dividedReportingOverflow(by: y)
return overflow ? nil : result
}
}
implementation seems to be quite trivial (unless, of course, I'm missing something), and will not benefit much from being implemented in the standard library.
Awhile back I suggested the idea of adding throws! and throws? to the language and this was one of the motivating cases. Basically, it would allow you to have a function throw, but instead of requiring the user to type try! or try? (respectively), the compiler would add it for you if needed.
Thus, in this case, the division operator would be marked throws! giving it the current behavior of trapping when used normally. However, if you wanted it to be failable in a particular case, then you would write:
try? (a / b) //This is failable
If you wanted it to throw an error on failure, you would write:
try (a / b) //This throws on failure
As you can see, this lets you choose a default behavior for error handling that can be overridden where desired.
It is useful for much more than just operators, but I find it a particularly compelling use case. I would really like to be able to wrap a section of calculation and then catch any exceptions that happen within it. In something like a spreadsheet, it usually doesn't really matter where in the calculation there was a failure, but I would like to be able to sort by the type of error so I can report it to the user. I would also like the option of being able catch the error instead of having to guard against it crashing in each step of the calculation (which leads to hard to read/maintain code).
Would this be an acceptable solution to the motivating problem for this thread?
Hmm, I don't think I'd like it. First, this is my personal opinion, I would be against of throws! and try! because it introduces even more options to the user to abuse force cast behavior, this is simply wrong and dangerous. I've seen too much of such ugly code and would be against of opening even more doors for that. Then I think retroactively making existing API throw errors is a huge breaking change, not even speaking of the verbosity it adds with all it's required try and do { } catch {}.
Failable operators on the other hand serve a simple thing, they fail for undefined mathematical or impossible operations like division by zero or over-/underflows. This solution is simple like Bool.toggle() and is fairly consistent to failable initializer added to numeric types (SE-0080) to be able to fail instead of trapping when casting. You can always recover using if let or ?? operator.
Division is very different for floating-point types and integer types. If this idea of a "failing operator" works well with your own mental model of arithmetic, as you've demonstrated, it's easy to implement for yourself.
You could even separate this idea into its own library and see if it gains broad traction in the Swift community. But I really don't see how this unfamiliar concept would benefit from being a part of the standard library, which is deliberately meant to be small, especially as an operator (which is terser and less discoverable than ordinary methods).