Swift "Is" Operator with Type Stored in Variable

Swift is operator with type stored in variable

It means that is operator cannot be used with variables on the right side?

Correct. The right side of is must be hard-coded at compile-time.

If you don't need polymorphism and your types are class types, you can use === to compare the dynamicType of an instance with a class type. That's the only way you're going to get a type-in-a-variable on the right side of something in pure Swift.

Casting to a type held in a variable

Swift (currently) requires the Type assignment at compile time. You can do some things like this, but you will need to write a converter for each type combination you want to use, e.g:

func convertType(from item: Int) -> Float {
return Float(item)
}

var item: Float = convertType(from: 1)

I would caution going down this road and try and get used to Swift's way of doing things. If you absolutely need it you should be able to use some generic functions with a protocol like FloatConvertable to handle this more simply.

Swift Is Type Check Operator

The type of the reference dog is Animal. Thus you can hand it to api that uses Animals. But the actual type behind the dog reference will be Dog. thus you can test for the actual type using is and you can (down)cast to the actual type using as

Assigning operator function in variable

You cannot do this:

var operation = *

But, you CAN do this:

var operation:(Int, Int) -> Int = (*)

operation(4,2) // -> 8

Because * has many overloaded types:

func *(lhs: UInt32, rhs: UInt32) -> UInt32
func *(lhs: Int32, rhs: Int32) -> Int32
func *(lhs: UInt64, rhs: UInt64) -> UInt64
func *(lhs: Int64, rhs: Int64) -> Int64
func *(lhs: UInt, rhs: UInt) -> UInt
func *(lhs: Int, rhs: Int) -> Int
func *(lhs: Float, rhs: Float) -> Float
func *(lhs: Double, rhs: Double) -> Double
func *(lhs: Float80, rhs: Float80) -> Float80

we have to explicitly specify which one.

Type casting with type in variable

No. The type cast is a compile time thing. It lets the compiler know what methods are available and how to do the linking.

You can use Mirror to gather information about your object at runtime, but it looks like invoking methods dynamically can still only be done on classes derived from NSObject.

Can I use a function stored in a variable as operator in Swift?

The best I can come up with is something like:

infix operator <-> {} // define the operator <->

func <-> (lhs:Int, rhs:Int) -> Int {
return arrowFunction(lhs, rhs)
}

let arrowFunction : (Int, Int) -> Int = (+)

println("\(2 <-> 7)")

Can I make a Swift data type infix operator?

You could do this with generics:

struct MyStruct<T>
{
var someNum: T
}

You can then explicitly state the dataType you wish to use by specifying the type on creation: let a = MyStruct<Int>(someNum: 4).

One thing Swift does that makes this all absolutely beautiful is derive the data type from the constructor, so you can also just do this:

let intStruct   = MyStruct(someNum: 4)
let floatStruct = MyStruct(someNum: 5.0)

Swift: send type as argument and compare a variable's type with it

As the other answers have eluded to, you cannot use meta-types with is. However, a nicer solution would be to simply use generics. This will allow Swift to infer the type you pass into the function, allowing you to write it as:

protocol Base : class {
var value: Int { get set }
}

class ObjectTypeA: Base {
var value: Int = 0
}
class ObjectTypeB: Base {
var value: Int = 1
}

var objects: [Base] = [ObjectTypeA(), ObjectTypeB()]

func updateElements<T:Base>(ofType type: T.Type, withValue value: Int) {
objects.filter{ $0 is T }.forEach{ $0.value = value }
}

updateElements(ofType: ObjectTypeB.self, withValue: 10)

You'll also want to make your Base protocol class bound (: class) in order to allow Swift to treat Base typed instances as reference types (allowing you to do $0.value = value).

Your previous code of:

var object = $0
object.value = value

would have worked for reference types, but not for value types – as object here is simply a copy of $0, so any mutations won't be reflected in the array. Therefore you should annotate your protocol to make it clear that your protocol isn't designed to be used with value types.

If you do want to be able to handle value types, you may want to consider using map instead:

func updateElements<T:Base>(ofType type: T.Type, withValue value: Int) {
objects = objects.map {
var object = $0
if object is T {
object.value = value
}
return object
}
}

Why Int and Float literals are allowed to be added, but Int and Float variables are not allowed to do the same in Swift?

In case of var sum = 4 + 5.0 the compiler automatically converts 4 to a float as that is what is required to perform the operation.
Same happens if you write var x: Float = 4. The 4 is automatically converted to a float.

In second case, since you have explicitly defined the type of the variable, the compiler does not have the freedom to change is as per the requirement.

For solution, look at @Fabio 's answer



Related Topics



Leave a reply



Submit