[swift-evolution] protocol-oriented integers (take 2)

Dave Abrahams dabrahams at apple.com
Tue Jan 31 22:15:19 CST 2017


on Tue Jan 31 2017, Xiaodi Wu <xiaodi.wu-AT-gmail.com> wrote:

> On Tue, Jan 31, 2017 at 2:53 PM, Max Moiseev <moiseev at apple.com> wrote:
>
>> Hi Brent,
>>
>> Thanks a lot for your suggestions! After having discussed them with Dave,
>> we came up with the following design that I personally like a lot.
>>
>> enum Overflowing { case .withOverflow }

I really dislike “Overflowing”; it seems to imply that there *will* be
overflow.  How about

  enum ReportingOverflow { case .reportingOverflow }

>> 
>> enum FullWidth { case .fullWidth }
>>
>> protocol FixedWidthInteger {
>>   func adding(_ other: Self, _: Overflowing) -> (partialValue: Self,
>> overflow: ArithmeticOverflow)
>>   func subtracting(_ other: Self, _: Overflowing) -> (partialValue: Self,
>> overflow: ArithmeticOverflow)
>>   func multiplied(by other: Self, _: Overflowing) -> (partialValue: Self,
>> overflow: ArithmeticOverflow)
>>   func divided(by other: Self, _: Overflowing) -> (partialValue: Self,
>> overflow: ArithmeticOverflow)
>>
>>   func multiplied(by other: Self, _: FullWidth) -> DoubleWidth<Self>
>>   func dividing(_ other: DoubleWidth<Self>, _: FullWidth) -> (quotient:
>> Self, remainder: Self)
>> }
>>
>>
>> Call sites would look like:
>>
>> x.multiplied(by: y, .withOverflow) and x.multiplied(by: y, .fullWidth)
>>
>> a little different for the division:
>>
>> x.divided(by: y, .withOverflow) and y.dividing(x, .fullWidth)
>>
>> Note the inverse-ness of `dividing`, but the lack of the argument label
>> makes it quite natural.
>>
>
> This is an improvement in many ways, I think. However `.fullWidth` vs.
> `DoubleWidth` seems less than ideal. 

IMO .fullWidth is an improvement over .DoubleWidth, at least for
multiplication.  The latter just repeats type information, where the
former tells you something about *how* the operation is to be performed.

> I get that you can't reuse `DoubleWidth` for the single-case enum, but
> still.
>
> Now that * and &* no longer used the `multiplied(by:)` spelling, is there a
> reason not to take advantage of overloading on the return value for these
> very specialized methods?
>
> ```
> protocol FixedWidthInteger {
>   typealias OverflowFlagging = (partialValue: Self, overflow:
> ArithmeticOverflow)
>   func multiplied(by other: Self) -> OverflowFlagging
>   func multiplied(by other: Self) -> DoubleWidth<Self>
> }
> ```
>
> You'd then write `x.multiplied(by: y) as OverflowFlagging` and
> `x.multiplied(by: y) as DoubleWidth`

It's too subtle, IMO, and any place that type context is available to
disambiguate the result, it 

             x.multiplied(by: y)

will look like it should be rewritten as

             x * y

> With respect to `dividing` vs `divided`, IMO it'd be a tricky name,
> especially for non-English speakers. The "ed/ing" rule has these suffixes
> used pretty interchangeably to indicate a non-mutating operation, depending
> on the vagaries of the English language, but we've never had an "ed" and an
> "ing" used for completely different things on the same type, as far as I'm
> aware. Why not move the `dividing` version to DoubleWidth, where it can be
> a proper `divided(by:)`?

Max and I discussed this; I'll let him answer.


-- 
-Dave


More information about the swift-evolution mailing list