var a: String = "1"
var b: Int = Int(a)
The example above triggers an error saying that Int needs to be unwrapped.
var a: String = "1"
var b = Int(a)
However if we dismiss the type when declared b and do the same thing, it won't trigger any error.
What is the difference between the two approach? Why the first one needs to be unwrap even though it is not declared as optional?
It is because in first example you are saying that b is of type Int and in second example since you did not make type explicit compiler sets it to Int?.
It is because Int(string) will only work if string can be interpreted as Int, so Int("3")->3 but what should it do if you say Int("text")->nil, because it is not able to parse string into a an Int
You could provide a default value if you wanted in the first example and then it would be OK.
var b: Int = Int(a) ?? 0
Related
var i: Int?
i? = 1
print(i)
I thought the above code would print 1 but actually it printed nil. As I guess, ? makes program skip i? = 1 when i is nil.
Even if I replace i? = 1 with i? += 1, it still can run and print nil
var i: Int?
i? += 1
print(i)
i? is Int? and 1 is Int but somehow + operator still works on 2 different types and passed compiler check.
Could anyone help me explain what happened? It's perfect if we can have an official document which talks about this behavior.
This is Optional Chaining as in foo?.bar = 123.
If you change the type to Int, the compiler will complain:
var i: Int
i? = 1 // Cannot use optional chaining on non-optional value of type 'Int'
From the linked reference above:
The assignment is part of the optional chaining, which means none of the code on the right-hand side of the = operator is evaluated.
You can find more info on Swift basics here.
In your example, i is an optional Int. To assign a value to it, you
var i: Int?
i = 1
If you want to calculate a new value for it, you could use optional binding using guard let of if let (the x variable in the example below) or force unwrap, as in the print() statement.
var i: Int?
i = 1
if let x = i {
i = x + 1
}
print(i!)
I can store a value in a variable of type Any quite easily, but I can't figure out how to access it.
Just plain trying to assign a to i gives me this error message:error: cannot convert value of type 'Any' to specified type 'Int'
And trying to cast it gives me this error message:
error: protocol type 'Any' cannot conform to 'BinaryInteger' because only concrete types can conform to protocols
let a: Any = 1
//this doesn't work
let i: Int = a
//this doesn't work
let i: Int = Int(a)
It doesn't work because Int doesn't have an initializer that accepts type Any. To make it work you need to tell compiler that a is actually an Int. You do this like this:
let a: Any = 1
let i: Int = a as! Int
Edit:
If you are not sure about type of a, you should use optional casting. There are many approaches.
let i1: Int? = a as? Int // have Int? type
let i2: Int = a as? Int ?? 0 // if a is not Int, i2 will be defaulted to 0
guard let i3 = a as? Int else {
// what happens otherwise
}
You can access it. It's just a.
But you can't do much beyond that. Aside from a handful of actually universal functions (print, dump, etc.), there's really not much that you can do with an Any.
There's a gradient of generality and usefulness. On one extreme is Any. It's nearly useless. It doesn't require anything of its conforming types. But as a result, it's incredibly general. Literally all types conform to it.
On the other extreme is a concrete type like Int. If you have a parameter that expects an Int, only one type of value is allowed: Int. But this specificity buys you utility. You know that this value supports being added, multiplied, converted to string, etc.
The only way to do anything useful with Any is to down-cast it with as/as?/as! into a more restricting (less general) type.
I am confused with following initialization
var in = None: Option[FileInputStream]
however what I know is that
var varName : type = _ // default value initialization
var varName : type = someValue // other than default intitalization
but what is
var in = None: Option[FileInputStream]
Please help
Thanks
This is called a type ascription and the resulting expression is called a typed expression. It, well, ascribes a type to an expression:
expr: Type
means "treat expr as if it had Type".
For example:
1
// Int
1: Float
// Float
Obviously, the expression needs to conform to the type that is ascribed to it.
The most widely used example of type ascription is probably the _* pseudo-type, which unpacks a Seq into a series of arguments:
def sumNums(nums: Int*) = nums.sum
sumNums()
//=> 0
sumNums(1)
//=> 1
sumNums(1, 2)
//=> 3
sumNums(Seq(1, 2))
// error: type mismatch;
// found : Seq[Int]
// required: Int
// sumNums(Seq(1, 2))
// ^
sumNums(Seq(1, 2): _*)
//=> 3
In your particular case, I find it questionable to ascribe a type to an expression just to get the type inferencer to infer the correct type, when you could just as well have declared the correct type to begin with:
var in: Option[FileInputStream] = None
With regards to your comments:
however what I know is that
var varName : type = _ // default value initialization
var varName : type = someValue // other than default intitalization
You can also leave out the type:
var varName = someValue
In this case, the type is inferred from the expression someValue.
var varName = _
Obviously, this cannot work: the type is inferred from the expression, but the value of the expression is inferred from the type. Therefore, this is not allowed.
Your example uses the form with inferred type:
var in = someExpression
So, the type of in is inferred from the type of someExpression.
Now, if we said
var in = None
then the type inferred for in would be None.type, i.e. the singleton type of the None object. But that doesn't make sense: why would we have a var, i.e. a variable which we can change, when we then give it a singleton type, i.e. an type which has only a single instance. So, we can re-assign in as often as we want, but we can only assign the same thing to it. That's illogical. (Well, technically, we could also assign null to it.)
And in fact, we want to be able to assign something to it, but also know whether we assigned something to it or not. That's why we use an Option in this case, and initialize it with None. So, re-interpret None as an Option, so that Scala infers the correct type:
var in = None: Option[FileInputStream]
// [name] = [value] : [type]
var in = None : Option[FileInputStream]
// can equivalently be written as:
var in: Option[FileInputStream] = None
This creates a variable of type Option[FileInputStream], with the initial value None.
To learn more about Scala's Option type, see http://www.scala-lang.org/api/current/#scala.Option
I've a placeholder object, basically in context of my application, the function carries a playload from one place to the other. I've assigned it the type Any but it's ending up in error
'Any' is not convertible to Int
I'm using Any instead of AnyObject as it can carry non object as well like tuples or closures. Any advise in the following case?
var n: Any = 4
n = n * 4
In a strongly typed language it is important to get your types right as early as possible. Otherwise you'll end up fighting the type system at every turn.
In your case, the placeholder, as you've described, needs to be Any because it is carrying arbitrary data - but n is an Int and should be declared as such.
Your code should have this feel:
func processPlaceholder (placeHolder: Any) {
if let n = placeHolder as? Int {
n = n * 4
// ...
}
else if let s = placeHolder as? String {
s = s + "Four"
// ....
}
// ...
}
If you know n is an Int you can cast it as such.
var n: Any = 4
n = n as Int * 4
n will still be of type Any, so if you want to do multiple operations you will have to cast it each time.
The other answers are perfectly right. This is just to clarify.
Yes, it's an Int under the hood. But not as far as the compiler is concerned! You have typed this thing as an Any and that's all the compiler knows. And you cannot do arithmetic operations with an Any.
If you insist on storing this thing in an Any, then you must cast down to an Int in order to use it as if it were an Int. Now the compiler will let you treat it as an Int. And it will work, too, as long as it really is an Int. (If you lie and it is not an Int, you'll crash when the program runs.)
In Swift Programming, should we need to declare datatype of the variable or will the variable change it's type based on value?
Which one is enough to declare a variable:
var MyVar: Int = 50
Or:
var Myvar = 50
var myVar: Int = 50
Or:
var myVar = 50
They are absolutely equivalent. The : Int is unnecessary because you are assigning 50 right there in the declaration, so Swift infers that this is to be an Int variable.
If you are going to assign as part of the declaration, the only time you need to supply the type is when the type is surprising. For example:
var myChar : Character = "s"
If you don't say Character, you'll get a String.
WWDC 2104 - Introduction To Swift (Session 402)
var languageName = “Swift” // inferred as String
var version = 1.0 // inferred as Double
var introduced = 2014 // inferred as Int
var isAwesome = true // inferred as Bool
Also…
var 🐸 = “Frog” // using unicode names
You should also use “let” for variables that will not change.
Type inference is one of the great parts of Swift. This means that when you assign a variable or constant, the system infers what type it should be. If for instance, you were declaring a variable before you set it, you'd need to specify its type explicitly.
var someVar: Int
someVar = 15
That way the compiler knows when it is being properly set.
You can declare a variable implicitly as:
var myVar = 50
or explicitly as:
var myVar:Int = 50
Also notice that you do not use the semi-colon ; to end the line.
Note that values are never implicitly converted to another type. If you need to convert a value to a different type, explicitly make an instance of the desired type, such as the following:
let label = "The width is "
let width = 94
let widthLabel = label + String(width)
From a complete beginner's view (mine) i see the following benefit of declaring a variable explicitly - the compiler will validate the input value - i.e. if you declare an empty variable and then update it with the wrong type value you will be prompted.
The first seems to be used only integer assignment.
I need to write code to test.
Update:
I mean,
Defined as int can not assign to string, the following is wrong:
var myVar: Int
myVar = "50"
And such is wrong:
var myVar
myVar = "50"
So, if assignment when you define a variable, use both two.
Otherwise, use:
var myVar: Int
Therefore, it is no difference between the two lists you.
Note that I changed MyVar to myVar to follow the convention.
var myVar: Int = 50
means -> message to the compiler will be.
Declare a variable called myVar that is of type(:) Int
and
var myVar = 50
will result the exact same. But here compiler will deduce the type for us. (Welcome to modern intelligent compilers). Type inference is strong feature of swift language.
Be aware that Swift is Type Safe Language