I've been using the FixedWidthIntger.*ReportingOverflow
methods so much to safely detect wraparound in my iterators (to return nil
on first overreach), I wonder if we can be more direct and take advantage of Swift's nil
processing.
precedencegroup CheckedMultiplicationPrecedence {
higherThan: AdditionPrecedence
lowerThan: BitwiseShiftPrecedence
associativity: none
assignment: false
}
precedencegroup CheckedAdditionPrecedence {
higherThan: RangeFormationPrecedence
lowerThan: MultiplicationPrecedence
associativity: none
assignment: false
}
infix operator *? : CheckedMultiplicationPrecedence
infix operator /? : CheckedMultiplicationPrecedence
infix operator %? : CheckedMultiplicationPrecedence
infix operator +? : CheckedAdditionPrecedence
infix operator -? : CheckedAdditionPrecedence
extension FixedWidthInteger {
/// Returns the product of the two given values, emitting `nil` in case of
/// any overflow.
@inlinable
public static func *? (lhs: Self, rhs: Self) -> Self? {
let result = lhs.multipliedReportingOverflow(by: rhs)
return result.overflow ? nil : result.partialValue
}
/// Returns the quotient of the two given values, emitting `nil` in case of
/// any overflow.
@inlinable
public static func /? (lhs: Self, rhs: Self) -> Self? {
let result = lhs.dividedReportingOverflow(by: rhs)
return result.overflow ? nil : result.partialValue
}
/// Returns the remainder of the two given values, emitting `nil` in case of
/// any overflow.
@inlinable
public static func %? (lhs: Self, rhs: Self) -> Self? {
let result = lhs.remainderReportingOverflow(dividingBy: rhs)
return result.overflow ? nil : result.partialValue
}
/// Returns the sum of the two given values, emitting `nil` in case of any
/// overflow.
@inlinable
public static func +? (lhs: Self, rhs: Self) -> Self? {
let result = lhs.addingReportingOverflow(rhs)
return result.overflow ? nil : result.partialValue
}
/// Returns the difference of the two given values, emitting `nil` in case
/// of any overflow.
@inlinable
public static func -? (lhs: Self, rhs: Self) -> Self? {
let result = lhs.subtractingReportingOverflow(rhs)
return result.overflow ? nil : result.partialValue
}
}
You can use them like:
let two, five, sixtyfour: Int8
two = 2
five = 5
sixtyfour = 64
two +? five // 7
two -? five // -3
two *? five // 10
five /? two // 2
five %? two // 1
// All of these return `nil`
sixtyfour *? five
sixtyfour /? 0
sixtyfour %? 0
Int8.min /? -1
sixtyfour +? sixtyfour
sixtyfour -? Int8.min
Instead of using them straight like the above, you'll likely use them with constructs like "guard let"
, etc. At the time the various "&???
" wrapping operators were added, were operators like the above considered to be added as counterparts?
Instead of separate precedence levels, should we let them use the existing MultiplicationPrecedence
and AdditionPrecedence
? Would we have to add overloads that take one Optional<Self>
operand, and an extension for "Optional where Wrapped: FixedWidthInteger
" to make overloads when both operands are Optional
?