<div dir="ltr">On Fri, Mar 31, 2017 at 3:45 AM, Brent Royal-Gordon via swift-evolution <span dir="ltr"><<a href="mailto:swift-evolution@swift.org" target="_blank">swift-evolution@swift.org</a>></span> wrote:<br><div class="gmail_extra"><div class="gmail_quote"><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left-width:1px;border-left-style:solid;border-left-color:rgb(204,204,204);padding-left:1ex"><div style="word-wrap:break-word"><div><span class="gmail-"><blockquote type="cite"><div>On Mar 30, 2017, at 2:56 PM, David Hart via swift-evolution <<a href="mailto:swift-evolution@swift.org" target="_blank">swift-evolution@swift.org</a>> wrote:</div><br class="gmail-m_1811294965817828968Apple-interchange-newline"><div><div style="word-wrap:break-word"><div><p style="box-sizing:border-box;margin-top:0px;margin-bottom:16px;color:rgb(36,41,46);font-family:-apple-system,blinkmacsystemfont,'segoe ui',helvetica,arial,sans-serif,'apple color emoji','segoe ui emoji','segoe ui symbol';font-size:16px;background-color:rgb(255,255,255)">The current protocols <code style="box-sizing:border-box;font-family:sfmono-regular,consolas,'liberation mono',menlo,courier,monospace;font-size:13.600000381469727px;padding:0.2em 0px;margin:0px;background-color:rgba(27,31,35,0.0470588);border-top-left-radius:3px;border-top-right-radius:3px;border-bottom-right-radius:3px;border-bottom-left-radius:3px">ExpressibleByInteger<wbr>Literal</code> and <code style="box-sizing:border-box;font-family:sfmono-regular,consolas,'liberation mono',menlo,courier,monospace;font-size:13.600000381469727px;padding:0.2em 0px;margin:0px;background-color:rgba(27,31,35,0.0470588);border-top-left-radius:3px;border-top-right-radius:3px;border-bottom-right-radius:3px;border-bottom-left-radius:3px">ExpressibleByFloat<wbr>Literal</code> are simple and work well but don't support arbitrary precision literal values. Replacing those protocols is a non-goal as they provide a simple interface for work well for most cases.</p></div></div></div></blockquote></span><div>Honestly, I don't think I agree with this. I see no particular reason to like our current protocols; they break down as soon as your type gets larger than the largest standard library integer/float type, which undermines one of their main use cases.</div></div></div></blockquote><div><br></div><div>Right. I think the existing ones should, if at all possible, be revised to support arbitrary precision literal values--or at least very, very large precision literal values (as it can be argued that, even for a BigInt, the ability to specify a value of arbitrarily many digits as a _literal_ would be rarely used).</div><div> </div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left-width:1px;border-left-style:solid;border-left-color:rgb(204,204,204);padding-left:1ex"><div style="word-wrap:break-word"><div><div></div><div>I've been toying with a different approach in my head for a few weeks. The `BinaryInteger` protocol contains the concept of a `words` collection, which expresses any integer type as a collection of `UInt`s containing a signed two's-compliment representation of the integer. That means any `BinaryInteger` already contains code to handle a `words` collection. If we made this more exposed in some way, then `ExpressibleByIntegerLiteral` could leverage that conformance.</div><div><br></div><div>One approach would be to extract the `words` collection into a higher-level protocol:</div><div><br></div><div><span class="gmail-m_1811294965817828968Apple-tab-span" style="white-space:pre-wrap">        </span>protocol BinaryIntegerSource {</div><div><span class="gmail-m_1811294965817828968Apple-tab-span" style="white-space:pre-wrap">                </span>associatedtype Words: Collection where Iterator.Element == UInt</div><div><span class="gmail-m_1811294965817828968Apple-tab-span" style="white-space:pre-wrap">                </span>var words: Words { get }</div><div><span class="gmail-m_1811294965817828968Apple-tab-span" style="white-space:pre-wrap">        </span>}</div><div><br></div><div>Then we could modify `BinaryInteger` to accept this:</div><div><br></div><div><span class="gmail-m_1811294965817828968Apple-tab-span" style="white-space:pre-wrap">        </span>protocol BinaryInteger: BinaryIntegerSource {</div><div><span class="gmail-m_1811294965817828968Apple-tab-span" style="white-space:pre-wrap">                </span>...</div><div><span class="gmail-m_1811294965817828968Apple-tab-span" style="white-space:pre-wrap">                </span>init<T : BinaryIntegerSource>(<wbr>_ source: T)</div><div><span class="gmail-m_1811294965817828968Apple-tab-span" style="white-space:pre-wrap">                </span>...</div><div><span class="gmail-m_1811294965817828968Apple-tab-span" style="white-space:pre-wrap">        </span>}</div><div><br></div><div>And introduce a new `IntegerLiteral` type which is a `BinaryIntegerSource`, but not a `BinaryInteger` (so you can't do arithmetic with it):</div><div><br></div><div><span class="gmail-m_1811294965817828968Apple-tab-span" style="white-space:pre-wrap">        </span>struct IntegerLiteral: <wbr>BinaryIntegerSource {</div><div><span class="gmail-m_1811294965817828968Apple-tab-span" style="white-space:pre-wrap">                </span>associatedtype Words = …</div><div><span class="gmail-m_1811294965817828968Apple-tab-span" style="white-space:pre-wrap">                </span>var words: Words { … }</div><div><span class="gmail-m_1811294965817828968Apple-tab-span" style="white-space:pre-wrap">        </span>}</div><div><br></div><div>And now, you can say something like:</div><div><br></div><div><span class="gmail-m_1811294965817828968Apple-tab-span" style="white-space:pre-wrap">        </span>struct Int128: ExpressibleByIntegerLiteral {</div><div><span class="gmail-m_1811294965817828968Apple-tab-span" style="white-space:pre-wrap">                </span>fileprivate var _value: DoubleWidth<Int64></div><div><span class="gmail-m_1811294965817828968Apple-tab-span" style="white-space:pre-wrap">                </span></div><div><span class="gmail-m_1811294965817828968Apple-tab-span" style="white-space:pre-wrap">                </span>init(integerLiteral value: IntegerLiteral) {</div><div><span class="gmail-m_1811294965817828968Apple-tab-span" style="white-space:pre-wrap">                        </span>_value = DoubleWidth(value)</div><div><span class="gmail-m_1811294965817828968Apple-tab-span" style="white-space:pre-wrap">                </span>}</div><div><span class="gmail-m_1811294965817828968Apple-tab-span" style="white-space:pre-wrap">        </span>}</div><div><br></div><div>And everything ought to do what it's supposed to. You could still use a different type if you didn't need anything larger than, say, `Int`. I don't believe this would require any changes to the compiler; `IntegerLiteral` could conform to `_<wbr>ExpressibleByBuiltinIntegerLit<wbr>eral`, which would allow it to represent integers up to the current limit of 1024 bits + 1 sign bit.</div><div><br></div><div>(There are a few similar approaches we could take, like exposing an `init(words:)` constructor in `BinaryInteger` and having the `IntegerLiteral` behave as a `Words` collection, but all of them basically involve bootstrapping into `BinaryInteger` through the `Words` type.)</div><div><br></div><div>I *think* that the not-yet-implemented `BinaryFloatingPoint.init<<wbr>Source: BinaryFloatingPoint>(_<wbr> value: Source)` initializers could be leveraged in a similar way—create a `BinaryFloatingPointSource` protocol and a `BinaryFloatLiteral` type that conforms to it—but I'm less certain of that because I don't really understand how this universal float conversion is supposed to work. Plus, the universal float conversion is still just a TODO comment right now.</div></div></div></blockquote><div><br></div><div>Hmm, I wonder if less is more.</div><div><br></div><div>First, we will soon have DoubleWidth types in the stdlib, which I would hope means that they will be useable out of the box as integer literal types. This would cover a lot of use cases, I'd imagine, as it would trivially get you 128-bit and 256-bit types. Though they might be less efficient for arithmetic, they should be perfectly suitable for initializing a value from a literal.</div><div><br></div><div>For larger than 256 bits, could we not recover almost all of the benefits by exposing Int2048 as an integer literal type? Given that Float80 has not been abused, I don't think it's the case that offering Int2048 means people will reach for it to do arithmetic when a smaller type will do.</div><div><br></div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left-width:1px;border-left-style:solid;border-left-color:rgb(204,204,204);padding-left:1ex"><div style="word-wrap:break-word"><div><div></div><div>(This would leave non-binary floats in the lurch, but we're pretty much doing that already—try initializing `Decimal` through its `ExpressibleByFloatLiteral` conformance sometime and you'll see what I mean. I would support changing its name to `<wbr>ExpressibleByBinaryFloatLitera<wbr>l`.)</div></div></div></blockquote><div><br></div><div>This is actually one of the greatest deficiencies I see in `ExpressibleByFloatLiteral`. Here, I would disagree with you and say that I'd like to see `ExpressibleByFloatLiteral` improved precisely because of its very poor functionality for `Decimal`. IMO, while saying that floating point literals are only meant to work in binary would mean that the current design is "correct," it's unfortunate and unjustifiable that `0.1` doesn't mean 0.1.</div><div><br></div><div>Honestly, I'd even prefer to allow `String` as a floating point literal type (because after all that's what Decimal is really doing under the hood) than to just give up on this aspect of float literals altogether. I don't have a good answer here but I would hate to see this opportunity lost to fix the deficiency for real.</div><div><br></div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left-width:1px;border-left-style:solid;border-left-color:rgb(204,204,204);padding-left:1ex"><div style="word-wrap:break-word"><div><div>These leave our current integer and floating-point literal size limits (1025-bit signed integers and 80-bit floats) in place, but those are implementation details and could be changed. In practice, I very much hope the compiler will try to optimize initialization from literals aggressively.</div></div><span class="gmail-HOEnZb"><font color="#888888"><div><br></div><div>
<span class="gmail-m_1811294965817828968Apple-style-span" style="border-collapse:separate;font-variant-ligatures:normal;font-variant-east-asian:normal;line-height:normal"><div><div style="font-size:12px">-- </div><div style="font-size:12px">Brent Royal-Gordon</div><div style="font-size:12px">Architechies</div></div></span>
</div>
<br></font></span></div><br>______________________________<wbr>_________________<br>
swift-evolution mailing list<br>
<a href="mailto:swift-evolution@swift.org">swift-evolution@swift.org</a><br>
<a href="https://lists.swift.org/mailman/listinfo/swift-evolution" rel="noreferrer" target="_blank">https://lists.swift.org/<wbr>mailman/listinfo/swift-<wbr>evolution</a><br>
<br></blockquote></div><br></div></div>