On Tue, Jan 16, 2018 at 6:20 PM, Nevin Brackett-Rozinsky < nevin.brackettrozin...@gmail.com> wrote:
> On Tue, Jan 16, 2018 at 6:31 PM, Xiaodi Wu <xiaodi...@gmail.com> wrote: > >> On Tue, Jan 16, 2018 at 4:30 PM, Nevin Brackett-Rozinsky < >> nevin.brackettrozin...@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.
_______________________________________________ swift-evolution mailing list swift-evolution@swift.org https://lists.swift.org/mailman/listinfo/swift-evolution