[swift-evolution] FloatingPoint does not conform to ExpressibleByFloatLiteral

Xiaodi Wu xiaodi.wu at gmail.com
Mon Jan 15 19:51:30 CST 2018


On Mon, Jan 15, 2018 at 19:20 Nevin Brackett-Rozinsky <
nevin.brackettrozinsky at gmail.com> wrote:

> All I’m saying is the current situation seems semantically wrong. As in,
> how can a type claim to be a floating point number, if it *literally*
> cannot be represented by a floating point number?
>

Again, you can think of it that way, but what I’m saying is that
“FloatLiteral” is a misnomer: semantically, a conforming type is
specifically claiming that it is expressible by a _binary_ floating point
number.

You suggest treating a float literal as a string, but another alternative
> is to teach the compiler to handle arbitrary-length integer literals, and
> then treat a float literal as two integer literals separated by a dot.
>

You *could*, but the fractional part is encoded quite differently from the
integral part in a binary floating point value, so that would require an
inelegant conversion.

More elegantly, you could represent the literal as a fraction, where the
denominator is given as a power of the radix. There are many ways to slice
it but this is getting far afield of your original question, which is,
essentially, that given the semantics of the two protocols it’s not correct
to conform FloatingPoint to ExpressibleByFloatLiteral, and not an oversight.

In any case, is this something that would have to be done before ABI
> stability, or could it wait until after?
>

I don’t think the current protocol can go away, so any additions or
enhancements are something that can wait.

Nevin
>
>
> On Mon, Jan 15, 2018 at 7:41 PM, Xiaodi Wu <xiaodi.wu at gmail.com> wrote:
>
>> On Mon, Jan 15, 2018 at 4:24 PM, Nevin Brackett-Rozinsky via
>> swift-evolution <swift-evolution at swift.org> wrote:
>>
>>> Currently, the FloatingPoint protocol does not conform to
>>> ExpressibleByFloatLiteral, whereas BinaryFloatingPoint does.
>>>
>>> The only explanation I can find for this is a brief comment from Steve
>>> Canon
>>> <https://lists.swift.org/pipermail/swift-evolution/Week-of-Mon-20160425/015691.html>
>>> during the review of SE-0067 (Enhanced Floating Point Protocols)
>>> <https://github.com/apple/swift-evolution/blob/master/proposals/0067-floating-point-protocols.md>
>>> :
>>>
>>>
>>> On Mon, Apr 25, 2016 at 1:32 PM, Stephen Canon via swift-evolution
>>>> <swift-evolution at swift.org> wrote:
>>>>
>>>> On Apr 23, 2016, at 8:53 PM, Brent Royal-Gordon via swift-evolution
>>>>> <swift-evolution at swift.org> wrote:
>>>>>
>>>>> Any reason why FloatLiteralConvertible isn't on FloatingPoint?
>>>>
>>>>
>>>> It doesn’t make sense for non-radix-2 types; you would change bases
>>>> multiple times.
>>>
>>>
>>>
>>> I don’t have Steve’s level of floating-point expertise, but from a
>>> conceptual standpoint Swift protocols encapsulate semantics and, unless I
>>> am quite mistaken, semantically a floating-point number *can* be expressed
>>> as a floating-point literal.
>>>
>>> So, what exactly is the problem preventing such a conformance, and what
>>> would be required to fix it? Do we need to revamp how numeric literals are
>>> handled, eg. to allow arbitrary-precision integers and base-agnostic floats?
>>>
>>
>> Note that there are no types that ship with Swift itself that conform to
>> FloatingPoint but not BinaryFloatingPoint (Foundation.Decimal does not
>> conform to FloatingPoint, and cannot do so without some major
>> backwards-incompatible surgery because of how it handles subnormals,
>> infinity, NaN, and a host of other issues), so this discussion does not
>> affect most (any?) end users.
>>
>>
>> The name ExpressibleByFloatLiteral is kind of a misnomer. To conform, a
>> type must be able to convert a value from some other type that conforms to
>> _ExpressibleByBuiltinFloatLiteral, which is to say a _binary_
>> floating-point type.
>>
>> If you create a Decimal type, it *could try to conform* to
>> ExpressibleByFloatLiteral, but given `var x: Double = 0.1`, the value would
>> actually be something like 0.10000000000000001, not exactly 0.1, because
>> it'd be the decimal approximation of a _binary_ approximation to the
>> literal. This is what Steve means by "you would change bases multiple
>> times," and the result is unintuitive. The alternative is to try to convert
>> to a decimal value via the _string representation_ of the _binary
>> approximation_ to the literal, which would let you recover `0.1` but lose
>> all information as to significant digits in the original literal (i.e.,
>> "0.1" vs. "0.100"), an important piece of information for Decimal types.
>>
>> In other words, given the actual design of ExpressibleByFloatLiteral, it
>> doesn't entirely make sense for non-binary floating-point types to conform.
>>
>>
>> Yes, we can try to perform major surgery on the floating-point literal
>> protocol, or add another one, so that it's possible for non-binary types to
>> conform, and there have been proposals on this list along those lines. It
>> would appear to me that any such design would necessarily be more complex
>> and possibly slower than the existing design; at its simplest, it could
>> involve representing the literal as a string, which almost all types,
>> whether Decimal or BigInt, would expected to be able to parse anyway. But
>> that's a much larger discussion for another day. The answer to your
>> question as to why `FloatingPoint` does not refine
>> `ExpressibleByFloatLiteral` is as shown above; tl;dr: it doesn't make sense
>> to do so.
>>
>>
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://lists.swift.org/pipermail/swift-evolution/attachments/20180116/ecdddfdc/attachment.html>


More information about the swift-evolution mailing list