[swift-evolution] FloatingPoint does not conform to ExpressibleByFloatLiteral

Xiaodi Wu xiaodi.wu at gmail.com
Tue Jan 16 19:06:56 CST 2018


On Tue, Jan 16, 2018 at 6:20 PM, Nevin Brackett-Rozinsky <
nevin.brackettrozinsky at gmail.com> wrote:

> On Tue, Jan 16, 2018 at 6:31 PM, Xiaodi Wu <xiaodi.wu at gmail.com> wrote:
>
>> On Tue, Jan 16, 2018 at 4:30 PM, Nevin Brackett-Rozinsky <
>> nevin.brackettrozinsky at gmail.com> wrote:
>>
>>> The thing that is “broken” here is generic programming. If I constrain
>>> something to FloatingPoint, I cannot use a float literal in calculations
>>> with it:
>>>
>>> func centimeters<T: FloatingPoint> (inches: T) -> T {
>>>
>>>     return 2.54 * inches    // Error
>>>
>>> }
>>>
>>
>> Why not constrain it to `BinaryFloatingPoint`? What other types are you
>> trying to use with this function?
>>
>
> We should not ask nor expect people to constrain their generic algorithms
> to BinaryFloatingPoint unless they are working with the radix.
>

On the contrary, I think the "currency" floating-point protocol should be
`BinaryFloatingPoint`. Having worked with `FloatingPoint` rather
extensively (or, attempted to at least), I reiterate that I find it to be a
distinctly unhelpful protocol in terms of enabling useful generic
algorithms; if we were to do anything, I'd advocate for its complete
removal before ABI stability sets in. For compatibility we would supply a
deprecated `typealias FloatingPoint = BinaryFloatingPoint`.



>
>> so that eg. a Rational type could be used. And that gives a hint as to
>>> the workaround:
>>>
>>> func centimeters<T: FloatingPoint> (inches: T) -> T {
>>>
>>>     return (254 / 100) * inches
>>>
>>> }
>>>
>>
>> Yes, you *could* do that.
>>
>
> And it seems I *will* be doing that, as long as such a workaround is
> necessary. Though it does appear to have the unfortunate cost of an extra
> division operation.
>

There should be no runtime cost when specialized.


That only works for numbers which don’t overflow the integer literals
>>> though.
>>>
>>
>> Integer literals don't overflow until 2048 bits. The following compiles
>> just fine:
>>
>> func moles<T : FloatingPoint>(particles: T) -> T {
>>   let N_A: T = 602_214_085_774_000_000_000_000
>>   return particles / N_A
>> }
>>
>
> When I write that in a playground it shows N_A as 1.67866967797794e+18.
>
> (Also, you appear to have mistakenly concatenated the standard uncertainty
> in the last 2 digits, “74”, onto the accepted value for the constant.)
>

Yes, those are typos; I was typing freehand into an email. Please adjust
the number and value of digits as necessary.



> If we want a really large or small value then we have to split it in
>>> pieces:
>>>
>>> func moles <T: FloatingPoint> (particles: T) -> T {
>>>
>>>     let avogadroNumber: T = 6_022_140_857 * 100_000_000_000_000
>>>
>>>     return particles / avogadroNumber
>>>
>>> }
>>>
>>> It would be much nicer to write “let avogadroNumber: T = 6.022140857e23”.
>>>
>>
>> You could write:
>>
>> func moles<T : FloatingPoint & LosslessStringConvertible>(particles: T)
>> -> T {
>>   let N_A = T("6.02214085774e+23")!
>>   return particles / N_A
>> }
>>
>
> …or I could write “T: FloatingPoint & ExpressibleByFloatLiteral”. I could
> even make a typealias for that. But I shouldn’t have to.
>

Sure, you could do that too. Your solution here is actually probably the
best, in that if a user wishes to conform a decimal type
to ExpressibleByFloatLiteral, your extensions would also work for that
type. I've already explained why the semantics of ExpressibleByFloatLiteral
are such that not every FloatingPoint type could conform.
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://lists.swift.org/pipermail/swift-evolution/attachments/20180116/51453822/attachment.html>


More information about the swift-evolution mailing list