Swift Passing a member function to a function that takes an optional closure - swift

I'm trying to construct a table that contains, among other things, an optional closure. When I try to instantiate an instance of the table, passing a member function for the closure I get a compile error.
From the error msg it appears that a member function can not be converted to an optional member function. I don't see why not; an Int or other types can easily be converted to optionals.
struct Foo {
typealias Routine = (_ x: Int) -> Int
let int: Int
let aRoutine: Routine?
init(_ int: Int, _ routine: Routine? = nil) {
self.int = int
self.aRoutine = routine
}
}
class Bar {
let foo = Foo(5, doSomething) // Compile error here
func doSomething(_ x: Int) -> Int {
return x
}
}
Cannot convert value of type '(Bar) -> (Int) -> Int' to expected argument type 'Foo.Routine?' (aka 'Optional<(Int) -> Int>')

You've just discovered that member functions (a.k.a. instance methods) are curried in Swift. See Instance Methods are “Curried” Functions in Swift
Foo.doSomething(_:) isn't just a free function (a.k.a. global function). It's an instance method that has access to the instance, self. But if you just take the method as a closure directly, it doesn't know what the value of self would be.
There are several options:
If your implementation of doSomething(_:) doesn't need to access self, then you can move it out of the Foo's declaration, and declare it as a global function.
Alternatively, you can turn it into a static function by keeping it where it is and using the static modifier. This has an added benefit over a global function, in that it "organizes" your code by moving it into an appropriate namespace.
If your implementation of doSomething(_:) does need an instance to operate on, then you can access the unapplied method of that instance. Here's an example. I've added explicit type annotations for demonstration, but you should usually omit those.
let object: Bar = Bar() // an object of type Bar
let boundDoSomethingMethod: (Int) -> Int = object.doSomething // a bound method which operates on `object`
// alternatively:
let unboundDoSomethingMethod: (Bar) -> (Int) -> Int = Bar.doSomething
let boundDoSomethingMethod: (Int) -> Int = unboundDoSomethingMethod(object)

Related

Reference to generic function in Swift

In Swift, you can create a reference to a function in the form of a closure. For example:
func simpleFunc(param: Int) {
}
let simpleFuncReference = simpleFunc(param:) // works just fine
But in one case, I have a function with a generic parameter like this:
func hardFunc<T: StringProtocol>(param: T) {
}
let hardFuncReference = hardFunc(param:) // "Generic parameter 'T' could not be inferred"
To try to remove that error, I attempted to explicitly specify the type, but immediately another error comes up.
func hardFunc<T: StringProtocol>(param: T) {
}
let hardFuncReference = hardFunc(param:) // "Cannot explicitly specialize a generic function"
Is there a way I can get a reference to hardFunc as a closure?
As you already guessed, you have to help type inference out a little:
func hardFunc<T: StringProtocol>(param: T) {
}
let hardFuncReference:(String) -> Void = hardFunc(param:)
Note that you do have to specify the particular type that you're specializing on, but in this case you do it by specifying the type of the variable you're assigning the closure to.
You can't keep it generic unless you're in a generic context specifying that it's generic on the same type. So this will work too
struct Foo<T: StringProtocol> {
let hardFuncReference:(T) -> Void = hardFunc(param:)
}

Annotating the whole of a function declaration with a typealias

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.:
The Language Guide - Closures
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

Return any type from a function in Swift

I am attempting to create a function that can return any type. I do not want it to return an object of type Any, but of other types, i.e. String, Bool, Int, etc. You get the idea.
You can easily do this using generics in this fashion:
func example<T>(_ arg: T) -> T {
// Stuff here
}
But is it possible to do it without passing in any arguments of the same type? Here is what I am thinking of:
func example<T>() -> T {
// Stuff here
}
When I try to do this, everything works until I call the function, then I get this error:
generic parameter 'T' could not be inferred
is it possible to do it without passing in any arguments of the same type?
The answer is yes, but there needs to be a way for the compiler to infer the correct version of the generic function. If it knows what it is assigning the result to, it will work. So for instance, you could explicitly type a let or var declaration. The below works in a playground on Swift 3.
protocol Fooable
{
init()
}
extension Int: Fooable {}
extension String: Fooable {}
func foo<T: Fooable>() -> T
{
return T()
}
let x: String = foo() // x is assigned the empty string
let y: Int = foo() // y is assigned 0

In Swift, what's the difference between calling UINavigationController() vs UINavigationController.init()?

In Swift, what's the difference between calling UINavigation() vs UINavigation.init()? They both seem to return valid instance of UINavigationController.
UINavigationController() and UINavigationController.init() are the exact same thing. You can verify this by typing both into a Playground and then option-clicking on them. Both bring up the documentation for the same initializer.
The Swift convention is to use just the type name (without .init).
For some given type (e.g. UINavigationController), there is no difference between a call to UINavigationController() or UINavigationController.init(), but the latter syntax can (without the () call) be useful when referencing an initializer of some given type, say Foo, in contexts where we want to make use of a closure (or reference to a closure) which is to have
zero or more arguments, and
return type Foo,
e.g., (Int, Double) -> Foo. In these contexts, using the syntax Foo.init may prove useful: rather than explicitly letting a closure repeatedly call a known initializer (piping the closure's arguments to the initializer), we may use (a reference to) the initializer direcly as the closure instead. If there's no ambiguity in the argument of the initializers of Foo, a reference to Foo.init in some given closure type context will resolve, using type inference, to the correct initializer.
E.g., consider the following example
struct Foo {
let foo: Int
// (Int) -> Foo
init(foo: Int) {
self.foo = 2*foo
}
// (Int, Int) -> Foo
init(foo: Int, bar: Int) {
self.foo = foo + bar
}
// () -> Foo
init() {
self.foo = 42
}
}
let arr = [1, 2, 3]
let fooArr1 = arr.map { Foo(foo: $0) }
let fooArr2 = arr.map(Foo.init)
/* map operation expects a single argument of type (Int) -> Foo,
which we generally supply as a trailing closure. In this context,
Swift can, without ambiguity (since we have none, is this example),
find the correct overload among the initializers of Foo */
print(fooArr1.map { $0.foo }, fooArr2.map { $0.foo }) // [2, 4, 6] [2, 4, 6]
let emptyTupArr = [(), (), ()]
let fooArr3 = emptyTupArr.map(Foo.init) // inferred to be the '() -> Foo' initializer
print(fooArr3.map { $0.foo }) // [42, 42, 42]
From Apple docs, you use init when you are subclassing the controller. It looks like without passing a value to the unit function, it just returns a standard UINavigationController
https://developer.apple.com/reference/uikit/uinavigationcontroller

Add default value to inout parameter using Swfit

In Swift 2 it is possible to do the following:
class SomeType {
static let singletonInstance = SomeType()
func someFunction(var mutableParameter: SomeType = SomeType.singletonInstance) {
...
}
}
However in Swift 3 the var keyword will be removed for function parameters in favour of inout. I have not been able to achieve the same result as the above using the inout keyword.
class SomeType {
static let singletonInstance = SomeType()
func someFunction(inout mutableParameter: SomeType = SomeType.singletonInstance) {
...
}
}
Instead I receive an error of "Default argument value of type 'SomeType' cannot be converted to type 'inout SomeType'"
My question is whether it is possible to use inout with default value?
The two keywords you're talking about, inout and var, are very different.
From Apple Documentation:
In-out parameters are passed as follows:
When the function is called, the value of the argument is copied.
In the body of the function, the copy is modified.
When the function returns, the copy’s value is assigned to the original argument.
Therefore you can't give a default value to an inout parameter, as it would make the inout property completely useless.
What you can do is receive a normal (constant) parameter with a default value, and declare a new var with the same name this way (code from the Swift Evolution's Removing var from Function Parameters Proposal, with the addition of the default parameter):
func foo(i: Int = 5) {
var i = i
// now you can change i as you'd like
}
Anyone who needs a default inout parameter may consider such solution:
class SomeType {
static let singletonInstance = SomeType()
func someFunction(inout mutableParameter: SomeType) {
...
}
// Declare function without 'mutableParameter':
func someFunction() {
someFunction(SomeType.singletonInstance)
}
}
When you specify the default value for the parameter, the Swift compiler automatically generates a function without the parameter, for you. In this solution we do it manually.
You could create a second function signature to "emulate" a default value
func foo() {
var v: Int = 0 // your default value
foo(bar: &v)
}
func foo(bar: inout Int) {
// do stuff
}