T, Optional<T> vs. Void, Optional<Void> - swift

// this declaration / definition of variable is OK, as expected
var i = Optional<Int>.None
var j:Int?
// for the next line of code compiler produce a nice warning
// Variable 'v1' inferred to have type 'Optional<Void>' (aka 'Optional<()>'), which may be unexpected
var v1 = Optional<Void>.None
// but the next sentence doesn't produce any warning
var v2:Void?
// nonoptional version produce the warning 'the same way'
// Variable 'v3' inferred to have type '()', which may be unexpected
var v3 = Void()
// but the compiler feels fine with the next
var v4: Void = Void()
What is the difference? Why is Swift compiler always happy if the type is anything else than 'Void' ?

The key word in the warning is "inferred." Swift doesn't like inferring Void because it's usually not what you meant. But if you explicitly ask for it (: Void) then that's fine, and how you would quiet the warning if it's what you mean.
It's important to recognize which types are inferred and which are explicit. To infer is to "deduce or conclude (information) from evidence and reasoning rather than from explicit statements." It is not a synonym for "guess" or "choose." If the type is ambiguous, then the compiler will generate an error. The type must always be well-defined. The question is whether it is explicitly defined, or defined via inference based on explicit information.
This statement has a type inference:
let x = Foo()
The type of Foo() is explicitly known, but the type of x is inferred based on the type of the entire expression (Foo). It's well defined and completely unambiguous, but it's inferred.
This statement has no type inference:
let x: Foo = Foo()
But also, there are no type inferences here:
var x: Foo? = nil
x = Foo()
The type of x (Foo?) in the second line is explicit because it was explicitly defined in the line above.
That's why some of your examples generate warnings (when there is a Void inference) and others do not (when there is only explicit use of Void). Why do we care about inferred Void? Because it can happen by accident very easily, and is almost never useful. For example:
func foo() {}
let x = foo()
This is legal Swift, but it generates an "inferred to have type '()'" warning. This is a very easy error to make. You'd like a warning at least if you try to assign the result of something that doesn't return a result.
So how is it possible that we assign the result of something that doesn't return a result? It's because every function returns a result. We just are allowed to omit that information if the return is Void. It's important to remember that Void does not mean "no type" or "nothing." It is just a typealias for (), which is a tuple of zero elements. It is just as valid a type as Int.
The full form of the above code is:
func foo() -> () { return () }
let x = foo()
This returns the same warning, because it's the same thing. We're allowed to drop the -> () and the return (), but they exist, and so we could assign () to x if we wanted to. But it's incredibly unlikely that we'd want to. We almost certainly made a mistake and the compiler warns us about that. If for some reason we want this behavior, that's fine. It's legal Swift. We just have to be explicit about the type rather than rely on type inference, and the warning will go away:
let x: Void = foo()
Swift is being very consistent in generating warnings in your examples, and you really do want those warnings. It's not arbitrary at all.
EDIT: You added different example:
var v = Optional<Void>()
This generates the error: ambiguous use of 'init()'. That's because the compiler isn't certain whether you mean Optional.init() which would be .None, or Optional.init(_ some: ()), which would be .Some(()). Ambiguous types are forbidden, so you get a hard error.
In Swift any value will implicitly convert with it's equivalent 1-tuple. For example, 1 and (1) are different types. The first is an Int and the second is a tuple containing an Int. But Swift will silently convert between these for you (this is why you sometimes see parentheses pop up in surprising places in error messages). So foo() and foo(()) are the same thing. In almost every possible case, that doesn't matter. But in this one case, where the type really is (), that matters and makes things ambiguous.
var i = Optional<Int>()
This unambiguously refers to Optional.init() and returns nil.

The compiler is warning you about the "dummy" type Void, which is actually an alias for an empty tuple (), and which doesn't have too many usages.
If you don't clearly specify that you want your variable to be of type Void, and let the compiler infer the type, it will warn you about this, as it might be you didn't wanted to do this in the first place.
For example:
func doSomething() -> Void {
}
let a = doSomething()
will give you a warning as anyway there's only one possible value doSomething() can return - an empty tuple.
On the other hand,
let a: Void = doSomething()
will not generate a warning as you explicitly tell the compiler that you want a Void variable.

Related

Using type as a value, why is the "self" keyword required here?

I'm currently learning type as a value in functions and wrote this sample code to play around:
import Foundation
class Animal {
func sound() {
print("Generic animal noises")
}
}
func foo(_ t:Animal) {
print("Hi")
}
foo(Animal) //Cannot convert value of type 'Animal.Type' to expected argument type 'Animal'
I'm not surprised by this result. Obviously you cant pass the type itself as an argument where an instance of that type is expected. But notice that the compiler says that the argument I passed was of type Animal.Type. So if I did this, it should compile right?
func foo(_ t:Animal.Type) {
print("Hi")
}
foo(Animal) //Expected member name or constructor call after type name
This is what really confuses me a heck ton, the compiler told me it was of type Animal.Type *but after making this change it once again shows an error.
Of course I listened to the fix Swift suggests and do:
foo(Animal.self) //Works correctly
But my biggest question is: WHY? Isn't Animal itself the type? Why does the compiler require me to use Animal.self to get the type? This really confuses me, I would like for some guidance.
Self-answering, with help of comments, I was able to find out the reason:
Using .self after the type name is called Postfix Self Expression:
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.
Thus, the .self keyword is required to consider the type as a value capable of being passed as an argument to functions.

Weird optional type behaviour in swift forEach

This code works fine. It iterates my array of one Int! and prints its magnitude.
import Foundation
let x : Int! = 1
[x].forEach {i in
print(i.magnitude)
}
Output:
1
Presumably, i in the loop body is an Int or an Int!, and indeed if I ask Xcode for "quick help" on forEach it reports:
func forEach(_ body: (Int) throws -> Void) rethrows
However, if perform two statements in my forEach body, instead it fails to compile, complaining that I need to unwrap i which now has the optional type Int?.
import Foundation
let x : Int! = 1
[x].forEach {i in
print(i.magnitude)
print(i.magnitude)
}
Compile error:
Value of optional type 'Int?' must be unwrapped to refer to member 'magnitude' of wrapped base type 'Int'
And if I ask for "quick help" now I get:
func forEach(_ body: (Int?) throws -> Void) rethrows
How on earth does the number of statements I place in my loop body manage to affect the type of the loop variable?
Basically, you've elicited an edge case of an edge case. You've combined two things that are the work of the devil:
Implicitly unwrapped Optionals
Implicit type inference of closures, along with the fact that
Implicit type inference of closures works differently when the closure consists of one line (this is where the "How on earth does the number of statements" comes in)
You should try to avoid both of those; your code will be cleaner and will compile a lot faster. Indeed, implicit type inference of anything other than a single literal, like a string, Int, or Double, is a huge drag on compilation times.
I won't pretend to imitate the compiler's reasoning; I'll just show you an actual solution (other than just not using an IUO in the first place):
[x].forEach {(i:Int) in
print(i.magnitude)
print(i.magnitude)
}
Our Int type is legal because we take advantage of the single "get out of jail free" card saying that an implicitly unwrapped Optional can be used directly where the unwrapped type itself is expected. And by explicitly stating the type, we clear up the compiler's doubts.
(I say "directly" because implicit unwrappedness of an Optional is not propagated thru passing and assignment. That is why in your second example you discovered Int?, not Int, being passed into the closure.)

Swift type inference in methods that can throw and cannot

As you may know, Swift can infer types from usage. For example, you can have overloaded methods that differ only in return type and freely use them as long as compiler is able to infer type. For example, with help of additional explicitly typed variable that will hold return value of such method.
I've found some funny moments. Imagine this class:
class MyClass {
enum MyError: Error {
case notImplemented
case someException
}
func fun1() throws -> Any {
throw MyError.notImplemented
}
func fun1() -> Int {
return 1
}
func fun2() throws -> Any {
throw MyError.notImplemented
}
func fun2() throws -> Int {
if false {
throw MyError.someException
} else {
return 2
}
}
}
Of course, it will work like:
let myClass = MyClass()
// let resul1 = myClass.fun1() // error: ambiguous use of 'fun1()'
let result1: Int = myClass.fun1() // OK
But next you can write something like:
// print(myClass.fun1()) // error: call can throw but is not marked with 'try'
// BUT
print(try? myClass.fun1()) // warning: no calls to throwing functions occur within 'try' expression
so it looks like mutual exclusive statements. Compiler tries to choose right function; with first call it tries to coerce cast from Int to Any, but what it's trying to do with second one?
Moreover, code like
if let result2 = try? myClass.fun2() { // No warnings
print(result2)
}
will have no warning, so one may assume that compiler is able to choose right overload here (maybe based on fact, that one of the overloads actually returns nothing and only throws).
Am I right with my last assumption? Are warnings for fun1() logical? Do we have some tricks to fool compiler or to help it with type inference?
Obviously you should never, ever write code like this. It's has way too many ways it can bite you, and as you see, it is. But let's see why.
First, try is just a decoration in Swift. It's not for the compiler. It's for you. The compiler works out all the types, and then determines whether a try was necessary. It doesn't use try to figure out the types. You can see this in practice here:
class X {
func x() throws -> X {
return self
}
}
let y = try X().x().x()
You only need try one time, even though there are multiple throwing calls in the chain. Imagine how this would work if you'd created overloads on x() based on throws vs non-throws. The answer is "it doesn't matter" because the compiler doesn't care about the try.
Next there's the issue of type inference vs type coercion. This is type inference:
let resul1 = myClass.fun1() // error: ambiguous use of 'fun1()'
Swift will never infer an ambiguous type. This could be Any or it could beInt`, so it gives up.
This is not type inference (the type is known):
let result1: Int = myClass.fun1() // OK
This also has a known, unambiguous type (note no ?):
let x : Any = try myClass.fun1()
But this requires type coercion (much like your print example)
let x : Any = try? myClass.fun1() // Expression implicitly coerced from `Int?` to `Any`
// No calls to throwing function occur within 'try' expression
Why does this call the Int version? try? return an Optional (which is an Any). So Swift has the option here of an expression that returns Int? and coercing that to Any or Any? and coercing that to Any. Swift pretty much always prefers real types to Any (and it properly hates Any?). This is one of the many reasons to avoid Any in your code. It interacts with Optional in bizarre ways. It's arguable that this should be an error instead, but Any is such a squirrelly type that it's very hard to nail down all its corner cases.
So how does this apply to print? The parameter of print is Any, so this is like the let x: Any =... example rather than like the let x =... example.
A few automatic coercions to keep in mind when thinking about these things:
Every T can be trivially coerced to T?
Every T can be explicitly coerced to Any
Every T? can also be explicitly coerce to Any
Any can be trivially coerced to Any? (also Any??, Any???, and Any????, etc)
Any? (Any??, Any???, etc) can be explicitly coerced to Any
Every non-throwing function can be trivially coerced to a throwing version
So overloading purely on "throws" is dangerous
So mixing throws/non-throws conversions with Any/Any? conversions, and throwing try? into the mix (which promotes everything into an optional), you've created a perfect storm of confusion.
Obviously you should never, ever write code like this.
The Swift compiler always tries to call the most specific overloaded function is there are several overloaded implementations.
The behaviour shown in your question is expected, since any type in Swift can be represented as Any, so even if you type annotate the result value as Any, like let result2: Any = try? myClass.fun1(), the compiler will actually call the implementation of fun1 returning an Int and then cast the return value to Any, since that is the more specific overloaded implementation of fun1.
You can get the compiler to call the version returning Any by casting the return value to Any rather than type annotating it.
let result2 = try? myClass.fun1() as Any //nil, since the function throws an error
This behaviour can be even better observed if you add another overloaded version of fun1 to your class, such as
func fun1() throws -> String {
return ""
}
With fun1 having 3 overloaded versions, the outputs will be the following:
let result1: Int = myClass.fun1() // 1
print(try? myClass.fun1()) //error: ambiguous use of 'fun1()'
let result2: Any = try? myClass.fun1() //error: ambiguous use of 'fun1()'
let stringResult2: String? = try? myClass.fun1() // ""
As you can see, in this example, the compiler simply cannot decide which overloaded version of fun1 to use even if you add the Any type annotation, since the versions returning Int and String are both more specialized versions than the version returning Any, so the version returning Any won't be called, but since both specialized versions would be correct, the compiler cannot decide which one to call.

Are there any possible explicit uses of instances (values) of empty tuples (), i.e., of instances of typealias 'Void'?

Question:
Are there any possible explicit uses for the empty tuple (), as a value (and not as a type) in Swift 2.x?
I know that these empty tuples can be used in the standard sense to define void functions. When I mistakenly defined a variable with a empty tuple value var a = () (of type ()), I started wondering if these empty tuple values can be used in some context. Does anyone know of such an application?
Example: possible application with array and optionals?
As an example, we can create an optional array of empty tuples that, naturally, can only hold either nil or ():
/* Optionals */
var foo: ()? = ()
print(foo.dynamicType) // Optional<()>
var arr : [()?] = [foo]
for i in 2...8 {
if i%2 == 0 {
arr.append(nil)
}
else {
arr.append(foo)
}
}
print(arr) // [Optional(()), nil, Optional(()), ... ]
With the small memory footprint of empty tuple, this could seem neat for micro-memory-management for a "boolean nil/not nil", but since type Bool have the same small footprint, I can't really see any direct use here, even in the (unlike) scenario that we really need to go bit-low optimization on our operations.
Perhaps I'm just chasing my own tail with some narrow unusable applications, but anyway: are there any possible explicit uses for these void () beings (as instances, not types)?
There are lots of places that () can be useful when playing around with "CS" problems, which often have the form "implement X using Y even though you really already have X." So for instance, I might say, implement Set using Dictionary. Well, a Dictionary is a Key/Value pair. What should the type of the Value be? I've actually seen this done in languages that have Dictionaries but not Sets, and people often use 1 or true as the value. But that's not really what you mean. That opens up ambiguity. What if the value is false? Is it in the set or not? The right way to implement Set in terms of Dictionary is as [Key: ()], and then you wind up with lines of code like:
set[key] = ()
There are other, equivalent versions, like your Optional<()>. I could also implement integers as [()] or Set<()>. It's a bit silly, but I've done things like that to explore number theory before.
That said, these are all almost intentionally impractical solutions. How about a practical one? Those usually show up when in generic programming. For example, imagine a function with this kind of form:
func doThingAndReturn<T>(retval: T, f: () -> Void) -> T {
f()
return retval
}
This isn't as silly as it sounds. Something along these lines could easily show up in a Command pattern. But what if there's no retval; I don't care about the return? Well, that's fine, just pass a () value.
func doThing(f: () -> Void) {
doThingAndReturn((), f: f)
}
Similarly, you might want a function like zipMap:
func zipMap<T, U>(funcs: [(T) -> U], vals: [T]) -> [U] {
return zip(funcs, vals).map { $0($1) }
}
This applies a series of functions that take T to values of type T. We could use that even if T happens to (), but we'd have to generate a bunch of () values to make that work. For example:
func gen<T>(funcs: [() -> T]) -> [T] {
return zipMap(funcs, vals: Array(count: funcs.count, repeatedValue: ()))
}
I wouldn't expect this to come up very often in Swift because Swift is mostly an imperative language and hides its Void in almost all cases. But you really do see things like this show up in functional languages like Scala when they bridge over into imperative programming.
Suppose you have two functions overloading the same name:
func foo()
func foo() -> Int
The first doesn't return anything, the second returns some kind of value. Attempting to call either of these will in most cases get you a compiler error about ambiguity.
foo()
let a = foo()
You'd think that the compiler would know that the first call unambiguously refers to the first function, because it assumes no return value. But in actuality, the return type of a function with no declared return type is Void, or (). So the first call is actually more like this:
let _ = foo()
And absent a type annotation for the discarded lvalue, the compiler can't infer which foo to call. You can use explicit type annotations to disambiguate:
let b: Void = foo()
let c: Int = foo()
Okay, it's not a very great or common use case for Void, because it's a situation you'd tend to avoid getting into in the first place. But you asked for a use... and it is a use of () as a value and not just a type, because you can retrieve it from b after assignment (for all the good that does you).
Just beware, when you look deeply into the Void, the Void also looks into you. Or something like that.

What does $T0 mean in Swift?

When programming in Swift, sometimes I see error messages containing $T0, $T1, $T2, etc. It seems like they have something to do with closures.
This code works fine:
let test = { (argument: Int) in
println("Argument is \(argument)")
}
test(42)
Xcode's autocomplete tells me that the type of test is (Int) -> (), so the return type appears to be inferred.
But if I add a return statement to the closure:
let test = { (argument: Int) in
println("Argument is \(argument)")
return
}
test(42)
I get an error saying:
error: cannot convert the expression's type '(Int) -> (Int) -> $T0' to type '(Int) -> (Int) -> $T0'
What does $T0 mean?
$T0 refers to an anonymous, or unknown type, generally speaking, if you see it, it means that the type inference failed and you can eliminate the problem by being more specific about typing.
In the specific case you refer to, the issue is that the compiler currently has problems resolving types for closures, particularly when they have return statements and no explicit type. To get your example to work (maybe you want a return in the middle of a block) you can be explicit about the return type:
let test = { (argument: Int) -> Void in
println("Argument is \(argument)")
return
}
(Note: apparently Swift 1.2 fixes several major classes of similar bugs)