I tried searching around for what this is
[]()
But I'm not really sure. In a playground, I did this:
var test = [Int]();
test.append(1);
test.append(2);
If I leave off the () and do
var test = [Int];
test.append(1);
test.append(2);
It still looks like an array of Ints to me. What is the difference?
Type() means "call init()" - i.e., make a new instance of Type.
[Int] is a type, like String. [Int] means "array-of-Int".
String() makes a new empty String instance. [Int]() makes a new empty array-of-Int instance.
You can declare a variable as being of type array-of-Int. Or you can make and assign a new array-of-Int instance. Which is what you are doing here:
var test = [Int]()
But you cannot assign a type to a variable without further syntax. Thus, this is illegal:
var test = [Int]
EXTRA for experts
You can say:
var test = [Int].self
That does assign the type to the variable! That is unlikely to be what you want here, because now you have no array; you have a type, itself, as object!!
[Type] is syntactic sugar for Array<Type>, so it represents the array type, which is a generic struct, and for which you specify the type of elements it holds (Int in this example)
So the difference between:
[Int]
and
[Int]()
is the same as for
Array<Int>
and
Array<Int>()
The first is just a type, which you can use when declaring a variable or a function parameter.
The second invokes the parameterless constructor on that type, i.e. creates an instance of that type.
Related
I have an array that holds integer values. And I have defined it like so:
#State private var numbers: Array = []
the array is updated as the user uses the app. At a certain point, I need to find the sum of all the values in the array. Here is what I tried to do:
let sumOfNum = numberz.reduce(0, +)
However, this is giving me the following error on the plus(+) symbol:
Cannot convert value of type '(Int) -> Int' to expected argument type '(Int, Any) throws -> Int'
Not sure what the problem is. Any help or guidance would be appreciated.
Your issue is probably your Array declaration. You should declare is as an array of Int instead of an array of Any.
So your array declaration should be
#State private var numbers: [Int] = []
I'm new to Swift and I just saw this declaration:
var completionHandlers = [(String) -> Void]()
As far as I know, this line is declaring an array of closures of type (String) -> Void, but I'm not sure of what the parentheses mean there.
[MyType]() is just syntactic sugar for Array<MyType>(), which itself is syntactic sugar for Array<MyType>.init(). It initializes an empty array of MyTypes.
It gets its own special syntax because Array is such a common data type.
Dictionary also has syntactic sugar in the style of [String: MyType](), for example.
The parenthesis is a way of calling the initialiser.
This is equivalent to:
var completionHandlers: [(String) -> Void] = []
Another way you will see it is:
var completionHandlers: [(String) -> Void] = .init()
You see it when initialising empty collections because if, for example you had:
var someVariable = ["hello", "world"]
The compiler would be able to infer the type of someVariable to be [String] because it knows the type of the contents. but You can't initialise an empty array like this because there is no information about the type. so [(String) -> Void]() is a way of providing the type to the empty initialiser.
The general recommendation in Swift is to use Type Inference where the type of the variable is inferred from it's initial value:
let intVariable = 3
let stringVariable = "Hello"
//etc
The style of code in your question follows this.
But in some cases with more complex types this can slow down the compiler, so many people are more explicit with their variable declarations.
let intVariable: Int = 3
let stringVariable: String = "Hello"
It's a matter of taste (and argument).
I want my struct to be created with sequence object using type inference. like:
var words: Buffer = ["generics", "ftw"] // type should be Buffer<String>
so I created a struct like this
struct Buffer<Element> {
init<S>(_ s: S) where Element == S.Element, S : Sequence {
}}
I just wrote code like above for testing generic init.
the code works when I create a struct like this:
var words = Buffer(["generics", "ftw"])
but I can't create a struct like this:
var words: Buffer = ["generics", "ftw"]
or
var words: Buffer<String> = ["generics", "ftw"]
the compiler complains me:
contextual type 'Buffer' cannot be used with array literal
I think I gave enough information to compiler as:
hey compiler, you'll gonna receive a Sequence. and the Element I mentioned is Sequence's Element.
what am I missing?
To use the syntax sugar, you have to adopt the ExpressibleByArrayLiteral protocol, which will make your struct able to be initialized using an array literal.
extension Buffer: ExpressibleByArrayLiteral {
typealias ArrayLiteralElement = Element
init(arrayLiteral: Element...) {
self.init(arrayLiteral)
}
}
After adding this extension, code like
var words: Buffer = ["generics", "ftw"]
or
var words: Buffer<String> = ["generics", "ftw"]
will compile.
Note that this does not mean that words is an array, although it is initialized with an array literal. If you assign the words variable to a variable that is of the Array type, your code will not compile, and vice versa. Also, note that if you don't infer the type Buffer in the variable declaration, it will be inferred as Array, so you must include Buffer in the variable decleration.
Is there any easy way to tell what class an instance variable is in a Swift? In the JVM-based languages that I'm used to, you can do something like println(value.class) to get it's class.
Is there something equivalent in Swift?
The closest thing I can find in the docs is the ability to do "type checking" with the is <Class> keyword but that only helps me guess a little bit.
I've run into a few situations in playing around where I thought I had one type of class, but actually had another and didn't know how to know for sure.
Use type.self to return a type that can be passed into a method that accepts a type-level argument. For example, UILabel.self can be passed to the isKindOfClass method call. The string representation of the class can be found via dynamicType.description():
var label = UILabel()
println(label.dynamicType.description())
println(label.isKindOfClass(UILabel.self))
Swift-3
var label = UILabel()
println(type(of: label).description())
Output UILabel true
Here's a bit more background -- there are two expressions to be aware of: the postfix self expression and the dynamic type expression. From the docs:
Postfix Self
A postfix self expression consists of an expression or the name of a
type, immediately followed by .self. It has the following forms:
expression.self
type.self
The first form evaluates to the value of the expression. For example,
x.self evaluates to x.
The second form evaluates to the value of the type. Use this form to
access a type as a value. For example, because SomeClass.self
evaluates to the SomeClass type itself, you can pass it to a function
or method that accepts a type-level argument
Dyamic Type Expression
A dynamicType expression consists of an expression, immediately
followed by .dynamicType. It has the following form:
expression.dynamicType
The expression can’t be the name of a type. The entire dynamicType
expression evaluates to the value of the runtime type of the
expression.
As of beta 6 _stdlib_getTypeName gets the mangled type name of a variable. Paste this into an empty playground:
import Foundation
class PureSwiftClass {
}
var myvar0 = NSString() // Objective-C class
var myvar1 = PureSwiftClass()
var myvar2 = 42
var myvar3 = "Hans"
println( "TypeName0 = \(_stdlib_getTypeName(myvar0))")
println( "TypeName1 = \(_stdlib_getTypeName(myvar1))")
println( "TypeName2 = \(_stdlib_getTypeName(myvar2))")
println( "TypeName3 = \(_stdlib_getTypeName(myvar3))")
The output is:
TypeName0 = NSString
TypeName1 = _TtC13__lldb_expr_014PureSwiftClass
TypeName2 = _TtSi
TypeName3 = _TtSS
Ewan Swick's blog entry helps to decipher these strings:
e.g. _TtSi stands for Swift's internal Int type.
Mike Ash has a great blog entry covering the same topic.
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