[swift-evolution] [Re-Review] SE-0104: Protocol-oriented integers
Ben Cohen
ben_cohen at apple.com
Wed Feb 22 10:01:16 CST 2017
There is another option to avoid the extra types, which is to stop trying to force the disambiguation through argument labels, accept an ambiguous call and have the context disambiguate:
// compilation error: ambiguous
let x = i.multiplied(by: j)
// unambiguously overflow-checked
let (y,overflow) = i.multiplied(by: j)
// unambiguously full-width
let z: DoubleWidth = i.multiplied(by: j)
Ambiguity is bad when you want to distinguish between the “usual one” versus other more specialized versions. So if you really had a regular trapping `adding`, but then also wanted to accommodate the overflow-reporting version when a user explicitly requests it, then the argument label is a clear win. This is a slightly bogus example though, because we explicitly don’t have things like `adding`, we have a `static +` instead. Where the disambiguation is needed is instead between two less common variants as described above.
> On Feb 21, 2017, at 11:51 AM, Joe Groff via swift-evolution <swift-evolution at swift.org> wrote:
>
> For the review, Dave asked me to raise a design question on his behalf, since he's on vacation. There are places where the proposal introduces one-case types as a labeling mechanism to distinguish different operations with otherwise the same argument names, for instance:
>
> public enum ReportingOverflow { case reportingOverflow }
>
> protocol Number {
> func adding(_ other: Self) -> Self
> }
>
> protocol FixedWidthInteger: BinaryInteger {
> func adding(_ other: Self, _: ReportingOverflow) -> (partialValue: Self, overflow: ArithmeticOverflow)
> }
>
> This introduces an otherwise useless type (for which we need to emit metadata, provide documentation for, list in reference documentation and code completion, etc.) and turns the compiler's job of choosing among these operators into an overload resolution problem rather than a simpler name lookup problem. In other places, particularly when a type imported from Cocoa has multiple nullary initializers, we already use the convention of a Void-typed labeled argument, which would look like this:
>
> protocol FixedWidthInteger: BinaryInteger {
> func adding(_ other: Self, reportingOverflow: Void) -> (partialValue: Self, overflow: ArithmeticOverflow)
> }
>
> The call syntax is less aethestically pleasing, no doubt (`adding(5, reportingOverflow: ())`), but that's arguably a problem we should address at the language level given that we already have APIs that look like that. The tradeoff of ugly syntax, which we can potentially beautify over time, in return for less "stuff" in the standard library, which we can't get rid off once the dylib is burned into billions of user devices, is worth considering.
>
> -Joe
> _______________________________________________
> swift-evolution mailing list
> swift-evolution at swift.org
> https://lists.swift.org/mailman/listinfo/swift-evolution
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://lists.swift.org/pipermail/swift-evolution/attachments/20170222/2c67259d/attachment.html>
More information about the swift-evolution
mailing list