My goal is to use a typealias as a one-word reminder “attached” to a function declaration. Say,
typealias VoidToVoid = () -> ()
I can use the type alias when stating the expected type of a closure, thus
let f : VoidToVoid = { return }
assert(f is VoidToVoid)
However, this does not seem the most usual way of declaring functions. I was hoping for a way to tell the reader that a function declared like f′ below, should be of type VoidToVoid, and using that name.
(But without the reader having to infer, or to think, or to wait for the compiler to tell him or her about the type. Aggravating the situation, the compiler cannot know the type alias name I had wanted with f′ and will likely output messages stating the bare type, not the alias.)
func f′() : VoidToVoid { // tentative syntax
return
}
Can I get there at all?
Edit: There are two ends at which the type alias is to be used. At one end, this is now possible:
func giveMeAClosure(_ f: VoidToVoid) {
f()
}
At the other end, being VoidToVoid is implicit:
func canBeGivenAsClosure() {
// ...
}
That is, where canBeGivenAsClosure is declared, it is true but not obvious that there is a connection between the two ends through VoidToVoid. This is different from the let case, which can have "VoidToVoid" as its type annotation.
Closures are unnamed closure expressions, which is why we may use a function type typealias to specify the type of the closure, even for closures that have a non-empty argument list.
typealias VoidToVoid = () -> ()
typealias IntToVoid = (Int) -> ()
// unnamed closure expressions
let f: VoidToVoid = { print("foo") }
let g: IntToVoid = { print($0) }
Note here that f and g in these exaples are not functions: they are simply immutable properties that holds references to (the backing storage of) the unnamed closures specified at the time of their declaration.
A function, one the other hand, is a special case of a closure; a closure with a name. Moreover, any function with a non-empty argument list needs to supply in internal (and optionally) and external parameter names in its declaration. A function type typealias, however, may not contain argument labels for its parameter names:
typealias IntToVoid = (a: Int) -> ()
/* Error: function types cannot have argument
label 'a'; use '_' instead */
This means that a function type typealias can't possible be used a substitute for the combined parameter and return type declaration part of a function (not even in the () -> () case).
For details, see e.g.:
Closures
...
Global and nested functions, as introduced in Functions, are actually special cases of closures. Closures take one of three forms:
- Global functions are closures that have a name and do not capture any values.
- Nested functions are closures that have a name and can capture values from their enclosing function.
- Closure expressions are unnamed closures written in a lightweight syntax that can capture values from their surrounding context.
On another note, you may naturally test the type of a given function to some existing function type typealias.
typealias VoidToVoid = () -> ()
typealias IntToVoid = (Int) -> ()
func f() -> () {}
func g(_ a: Int) -> () { _ = a }
print(f is VoidToVoid) // true
print(g is IntToVoid) // true
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With