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?
Of course, “T: FloatingPoint” is an overconstraint in this example, as what
I actually want is “T: OrderedField”
This approach was considered during revision of integer protocols and
rejected. You could make your own protocol to which your types of interest
then conform, if you're so interested.
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.
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
}
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
}
···
On Tue, Jan 16, 2018 at 4:30 PM, Nevin Brackett-Rozinsky < nevin.brackettrozinsky@gmail.com> wrote:
On Tue, Jan 16, 2018 at 3:39 PM, Chris Lattner <clattner@nondot.org> wrote:
On Jan 15, 2018, at 11:01 PM, Xiaodi Wu via swift-evolution < >> swift-evolution@swift.org> wrote:
> - Can we change the semantics? Maybe, but I doubt
ExpressibleByFloatLiteral can be outright replaced. You're not the first to
wonder about how to design an alternative protocol. Dig through the
archives and you'll find some existing ideas. My two cents: The main
alternative base in question here is 10. However, decimal storage formats
and binary storage formats share so little in common that any initializer
common to both will be extremely unwieldy for one or both formats.
Personally, somewhere down the road, I'd rather see Decimal64/128 become
standard library types (already working on it), DecimalFloatingPoint become
a standard library protocol, and `0.1` become a "decimal literal" (with
Float, Double, Float80, and Decimal64/128 all conforming) as distinct from
a "float literal" that we could then restrict to hexadecimal (?and binary)
floating-point literals (and maybe rename accordingly).
If we were motivated to fix this (and I’m not :-), then I think the best
path forward would be to rename ExpressibleByFloatLiteral to something like
ExpressibleByBinaryFloatLiteral. This would allow the introduction of a
new ExpressibleByDecimalFloatLiteral with a different initializer
requirement.
I’m not motivated to fix this, because there is nothing actively broken
by the current state of things. With the current name we can still
introduce a ExpressibleByDecimalFloatLiteral someday in the future. The
two names will be a little odd, but given the cost of changing it at this
point, that seems perfectly acceptable.
-Chris