I've run into a somewhat weird (compile time) error that I cannot make any sense out of. The error is given for the following snippet:
/* error: type 'Int1' does not conform to protocol 'BooleanType' */
let closure1 : (inout foo: Int) -> () = {
foo -> () in
(foo<0 ? (foo = -1) : (foo = 1))
}
Error: type 'Int1' does not conform to protocol 'BooleanType'
Note that Int1 is not a typo here.
Question 1: Why am I not allowed to use a single inline if statement (with result '()'
) as the implicit return type of a void return closure?
Question 2: Out of curiosity, what is the Int1
type? (Curiously enough the same error message, Int1 ...
is given even if modifying the closure above to operate on different types in a similar manner).
Why is this of interest for me? I have a few closures that I would like to use in the anonymous form similar of closure1Anon
below, but due to this error I can't.
Details and my own (non-fruitful) investigation into the matter follow below.
As described above, the error is prompted when---within a void return closure---using a single inline if statement which includes assignments to an inout
parameter.
We can verify that result of an inline statement is the empty tuple value, ()
, consider e.g.:
var foo = -4
print((foo<0 ? (foo = -1) : (foo = 1)).dynamicType) // ()
print(foo) // -1
... so it should be OK to use as return statement for a void return closure (see e.g. the assignment-followed-by-return example closure4
below).
Below follows the erroneous closure (closure1
, closure1Explicit
, closure1Anon
) as well as five very similar/associated closures that work fine (closure2
through closure7
).
/* error: type 'Int1' does not conform to protocol 'BooleanType' */
let closure1 : (inout foo: Int) -> () = {
foo -> () in
(foo<0 ? (foo = -1) : (foo = 1))
}
/* same error */
let closure1Explicit : (inout foo: Int) -> () = {
foo -> () in
return (foo<0 ? (foo = -1) : (foo = 1))
}
let closure1Anon : (inout foo: Int) -> () = { ($0<0 ? ($0 = -1) : ($0 = 1)) }
Ok:
/* The following are all OK */
let closure2 : (inout foo: Int) -> () = {
(inout foo: Int) -> () in
(foo<0 ? (foo = -1) : (foo = 1))
} // thanks @MartinR
let closure3 : (inout foo: Int) -> () = {
foo -> () in
let _ = (foo<3 ? (foo = 1) : (foo = 2))
}
let closure4 : (inout foo: Int) -> () = {
foo -> () in
(foo<3 ? (foo = 1) : (foo = 2))
return ()
}
let closure5 : (inout foo: Int) -> () = {
foo -> () in
let bar = (foo<3 ? (foo = 1) : (foo = 2))
return bar
}
/* Error must be related to inout as the two
following closures works fine */
let closure6 : () -> () = {
() -> () in
var a = 0
return (a<0 ? (a = -1) : (a = 1))
}
var globalVar = 1
let closure7 : () -> () = {
() -> () in
(globalVar<0 ? (globalVar = -1) : (globalVar = 1))
}
I can't for the world figure out why closure1
/closure1Explicit
/closure1Anon
above yields this error. Possibly someone can shed some light on this for me?
Final note: the following seemingly similar SO thread seems non-relevant in this case:
- Type 'Int' does not conform to protocol 'BooleanType'
I'm using Swift 2.1.1 and Xcode 7.2.1.