2

Let's say for academic purposes, I would prefer an expression like

someInt.asDouble

rather than the stock

Double(someInt)

Since all of the various Swift integer types conform to the IntegerType protocol AND because there seems to be a Double() initializer that fits every kind of those int types, I thought I could something like:

extension IntegerType {
    var asDouble:Double {
        return Double(self)
    }
}

This does not work. And I would like to know why? I would like to know if there is some magic that would make it work? A where maybe? Or something to do with the self reference?

The error I get in the console of the playground I tried in this reads:

Playground execution failed: /var/folders/2k/6y8rslzn1m95gjpg534j7v8jzr03tz/T/./lldb/41416/playground37.swift:31:10: error: cannot invoke initializer for type 'Double' with an argument list of type '(Self)'
                return Double(self)
                       ^
/var/folders/2k/6y8rslzn1m95gjpg534j7v8jzr03tz/T/./lldb/41416/playground37.swift:31:10: note: overloads for 'Double' exist with these partially matching parameter lists: (Double), (UInt8), (Int8), (UInt16), (Int16), (UInt32), (Int32), (UInt64), (Int64), (UInt), (Int), (Float), (Float80), (String), (CGFloat), (NSNumber)
                return Double(self)
Travis Griggs
  • 21,522
  • 19
  • 91
  • 167
  • If you were a compiler, how would you find out which version is correct? it is impossible. there is a lot of similar questions around. our problem is to understand that swift it type safe language .... – user3441734 Nov 11 '15 at 18:32
  • `Int` is the thing that holds the value. Not one of the protocols it conforms to. – R Menke Nov 11 '15 at 19:17
  • @RMenke Does that mean that a Protocol Extension cannot refer to `self`? – Travis Griggs Nov 11 '15 at 19:23

1 Answers1

3

All IntegerType types can be promoted to IntMax, and IntMax can be converted to Double.

extension IntegerType {
    var asDouble: Double {
        return Double(self.toIntMax())
    }
}

As you suggest, this is not a particularly useful thing to do (Double(x) is the correct syntax), but it may be useful for other problems.

I would continue stdlib's pattern if I were going to create this. The pattern is toX() rather than asX:

extension IntegerType {
    func toDouble() -> Double {
        return Double(self.toIntMax())
    }
}

See also toOpaque() and toUIntMax(). as suggests a simple reinterpretation of the type without copying, and a var suggests that it's a property of this value. That's not what's happening. You're actually converting it to a different value, stored in a different format, that may not even be equal. (For large integers, there may be rounding errors such that x != Int(x.toDouble()).)

It's worth also reading Trying to extend IntegerType (and FloatingPointType); Why can't all Int types be converted to NSTimeInterval, which discusses the problem further, along with why similar features can be dangerous unless done with great care.

Community
  • 1
  • 1
Rob Napier
  • 286,113
  • 34
  • 456
  • 610
  • @Rob Napier excelent !! really very useful answer !! – user3441734 Nov 12 '15 at 12:34
  • @Rob Napier how to deal with FloatingPointType ?? – user3441734 Nov 12 '15 at 13:36
  • See http://stackoverflow.com/questions/33620967/trying-to-extend-integertype-and-floatingpointtype-why-cant-all-int-types-be/33657549#33657549. This whole approach is pretty useless, since `Double(x)` is by far the better solution in this case, and I give the better solution for `NSTimeInterval` at the bottom of the linked answer. But in theory, it could be useful for some other thing that exceeds its danger. (I explain the dangers in the linked answer as well.) – Rob Napier Nov 12 '15 at 14:43
  • @Rob Napier i need 'generic' version of math functions. in standard library there are, for example, round(Double), round(Float) .... it is fine for me first convert everything to Double, but i have no idea how. does exist something similar to .toIntMax() for FloatingPointType ??? – user3441734 Nov 13 '15 at 15:07
  • See the previously linked question (final paragraph above). I provide a `TimeIntervalConvertible` protocol there. `DoubleConvertible` would be identical. I also explain why converting to `Double` isn't the same as converting to `IntMax`, so some care must be taken. – Rob Napier Nov 13 '15 at 16:37