ScalarArithmetic icon indicating copy to clipboard operation
ScalarArithmetic copied to clipboard

How are you auto-casting with just the = sign

Open eonist opened this issue 9 years ago • 14 comments

IN your sample code you have:

cgFloatValue = doubleValue
doubleValue = intValue
doubleValue = cgFloatValue

But I can't find the auto infer code in your src. Some sort of extension or?

eonist avatar Oct 09 '16 11:10 eonist

@eonist Sorry, it looks like the Readme is a bit dated. I was relying on the @conversion keyword pre Swift 2. It allowed for implicit conversion on assignment.

The only thing possible today, is what's defined in the test-suite(s). I'll fix the Readme once I migrate over to 3.0.

Sorry for the inconvenience.

seivan avatar Oct 10 '16 08:10 seivan

So something like this:

let someDouble:Double = 4
let someFloat:CGFloat = someDouble

Won't work in swift 3.0?

eonist avatar Oct 10 '16 10:10 eonist

Not without some Arithmetic operation, e.g addition. let someFloat:CGFloat = 0 + someInt or let someFloat:CGFloat = otherFloat + someInt or someFloat += someInt

Since we don’t got implicit conversion on assignment, the next best thing is implicit conversion through operators.

On 2016Oct10, at 12:23, Eon [email protected] wrote:

So something like this:

let someInt:Int = 4 let someFloat:CGFloat = someInt Won't work in swift 3.0?

— You are receiving this because you commented. Reply to this email directly, view it on GitHub https://github.com/seivan/ScalarArithmetic/issues/17#issuecomment-252580914, or mute the thread https://github.com/notifications/unsubscribe-auth/AADYgAiUB_sUOYo-gGH5RPXZBc13-Cpnks5qyhIlgaJpZM4KR-Yj.

seivan avatar Oct 10 '16 10:10 seivan

Right. Would be so awesome to not worry about casting Numerical types. I guess one could make an universal cast method by using inference and generics. like:

let someFloat:Float = 4
let someInt:Int = someFloat.cast()
let someDouble:Double = someFloat.cast()
let someCGFloat:CGFloat = someFloat.cast()

extension Float{
    func <T>cast()->T{
        if(T is Int){return Int(self)}
        else if(T is Double){return Double(self)}
        else if(T is CGFloat){return CGFloat(self)}
        else {fatalError("numerical type not supported")}
    }
}

Better yet. Make a protocol with an extension that every numerical type could extend. So that you only would have to write the extension once. extension Float:NumericalConversional... and extension CGFloat:NumericalConversional...etc

eonist avatar Oct 10 '16 10:10 eonist

That’s actually been on my mind. But not sure about the implications. So far I’ve resorted to + 0 just to be explicit about it. But maybe cast() is more explicit.

On 2016Oct10, at 12:53, Eon [email protected] wrote:

Right. Would be so awesome to not worry about casting Numerical types. I guess one could make an universal cast method by using inference and generics. like:

let someInt:Int = someFloat.cast() let someDouble:Int = someFloat.cast() let someCGFloat:Int = someFloat.cast()

extension Float{ func <T>cast()->T{ if(T is Int){return Int(self)} else if(T is Double){return Double(self)} else if(T is CGFloat){return CGFloat(self)} else {fatalError("numerical type not supported")} } } — You are receiving this because you commented. Reply to this email directly, view it on GitHub https://github.com/seivan/ScalarArithmetic/issues/17#issuecomment-252586257, or mute the thread https://github.com/notifications/unsubscribe-auth/AADYgECRHqfA0KOvzYFj_kV11IDqOXniks5qyhlCgaJpZM4KR-Yj.

seivan avatar Oct 10 '16 10:10 seivan

What i personally do Is:

let someCGFloat:CGFloat = 4
let someInt:Int = someCGFloat.int
let someDouble:Int = someCGFloat.double
let someString:String = someCGFloat.string

But this solution has code all over the place. But the suggested cast solution would be more centralised and easier to reason with. Thats why I stared your project , I tought you had found a way to infer types with the "=" sign. :)

eonist avatar Oct 10 '16 11:10 eonist

I am sorry, I did in Swift 1.0. But they sorta removed it, and I understand since implicit casts could be dangerous. I actually like your way better, but a casted property could work without the huge switch case you had in mind if you rely on types. I could spike up a quick idea if you’d want that.

On 2016Oct10, at 13:00, Eon [email protected] wrote:

What i personally do Is:

let someInt:Int = cgFloat.int let someDouble:Int = cgFloat.double let someString:String = cgFloat.string But this solution has code all over the place. But the suggested cast solution would be more centralised and easier to reason with. Thats why I stared your project , I tought you had found a way to infer types with the "=" sign. :)

— You are receiving this because you commented. Reply to this email directly, view it on GitHub https://github.com/seivan/ScalarArithmetic/issues/17#issuecomment-252587665, or mute the thread https://github.com/notifications/unsubscribe-auth/AADYgJqeZJdfFNrvc6yJXuXqKTsMGW1iks5qyhrDgaJpZM4KR-Yj.

seivan avatar Oct 10 '16 11:10 seivan

Yes, definitely avoid the huge if else clause with polymorphism. And just extend every Numerical type instead. If its all in one .swift class its easy enough to reason with.

eonist avatar Oct 10 '16 11:10 eonist

If you have arrays with numbers you can also do something like this:

let someFloats:[Float] = [1,2,3,4]
let someCGFloats:[CGFloat] = someFloats.cast()

extension Array{
   func cast<T:NumericConversional>() -> [T]{
      return self.map { $0.cast() }
   }
}

NOTE: NumericConversional would need to be a protocol that you add when you make the extension for each Number type. etc etc

eonist avatar Oct 10 '16 11:10 eonist

For Sequence extensions - You'd probably want to use either a flatMap or rethrow errors.

seivan avatar Oct 11 '16 09:10 seivan

Isn't flatmap used when a value can be nil? Are you thinking about numerical values that can be NaN? I can't remember but I think Int or UInt can't be NaN

eonist avatar Oct 11 '16 09:10 eonist

Yep, not to mention between unsigned and signed and such. I recall seeing optional inits. But I might be mistaken.

Sent from an iPhone on the go.

On 11 Oct 2016, at 11:18, Eon [email protected] wrote:

Isn't flatmap used when a value can be nil? Are you thinking about numerical values that can be NaN? I can't remember but I think Int or UInt can't be NaN

— You are receiving this because you commented. Reply to this email directly, view it on GitHub, or mute the thread.

seivan avatar Oct 11 '16 12:10 seivan

unsigned and signed == special cases no?

img

Anyways I usually just write for the simplest case first, if something needs more features then one could method overload... like for cases where the array items can be nil:

 func cast<T?:NumericConversional>() -> [T?]{
   return self.flatMap { $0.cast() }
 }

Also i'm not sure if flatMap handles NaN values. asserting for isNaN could be a substitute.

eonist avatar Oct 11 '16 13:10 eonist

flatMap doesnt out of the box, but you'd have assertions in there on whatever protocol you have.

seivan avatar Oct 11 '16 13:10 seivan