In Swift, Can a Function Be a Type

In swift, can a function be a type?

Every function has a specific function type, made up of the parameter types and the return type of the function.

typealias FooType = (Int, String)->String

func foo(i: Int, s: String)->String {
return s + "_\(i)"
}

func bar(foo0: FooType)->String {
return foo0(100, "alpha")
}

print(bar(foo)) // alpha_100

let f:FooType = { i, s in
return s + "_\(i)"
}

print(f(200, "beta")) // beta_200

an appendix, especially for Brandon :-)

let farr:[()->Int] = [{return 1}, {return 2}, {return 3}]
for f in farr {
print(f())
/*
1
2
3
*/
}

appendix 2, for Brandon

func f1()->Int {
return 1
}
func f2()->Int {
return 2
}

let farr2:[()->Int] = [f1, f2]
for f in farr2 {
print(f())
/*
1
2
*/
}

app 3 :-)

let farr2 = [f1, f2]
for f in farr2 {
print(f())
/*
1
2
*/
}

from apple docs

Every function in Swift has a type, consisting of the function’s
parameter types and return type. You can use this type like any other
type in Swift, which makes it easy to pass functions as parameters to
other functions, and to return functions from functions. Functions can
also be written within other functions to encapsulate useful
functionality within a nested function scope.

Why casting function type as AnyObject works

Behind the scenes as AnyObject converts the casted value to an Objective-C compatible one: Int's become NSNumber, array's become NSArray, and so on. Swift-only values get wrapped within opaque SwiftValue instances.

print(type(of: test2)) // __SwiftValue

This is why adding as AnyObject makes your code compile, as the right-hand of the operator is now an object.

Do you always need to specify the type of the return value in a function?

Yes, you must always specify the return type unless the return type is Void.

It's necessary because Swift says it is required. It is a way to ensure the correct type is returned and the caller knows what type to expect. It's no different than declaring the type of any variable or function parameter.

It lets you catch many bugs at compile time and it avoids a lot of potential runtime issues.

Allow Swift function parameter to be of multiple types

You mentioned enums, which sound like an excellent fit for this use case.
You can explicitly only require the types you expect, and nothing else.
By adding a property to the enum you can then expose a UIControl property to interact as needed, without the need for down-casting (which is generally considered to be an anti-pattern).

enum Component {
case `switch`(UISwitch)
case stepper(UIStepper)

var control: UIControl {
switch self {
case .switch(let comp):
return comp
case .stepper(let comp):
return comp
}
}
}

Then ask for a Component as a parameter to the function.

func controlValueChanged(_ myComponent: Component) {
// Now you can use them as a generic UIControl
let control = myComponent.control

// ...or different behaviours for each element
switch myComponent {
case .switch(let swit):
// use the `swit`
case .stepper(let step):
// use the `step`
}
}

Having said that, if the implementations for these types are totally different anyway, it may be more clear to define two separate functions.

Function type vs functions (methods)

In the case of:

var someVariable: Int -> Int 

You're declaring a variable with a method signature accepting an Int and returning an Int. You can assign any function that complies with this method signature. You can pass this variable around and assign it like any other variable when necessary. It adds flexibility as to how you can assign your methods.

Return any type from a function in Swift

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

How to create typealias of a function type which refers to a particular function

You cannot assign a function to a typealias.

You can only assign a type.

typealias mathFunctionType = (Int, Int) -> Int

let mathFunction: mathFunctionType = { int1, int2 in
return int1 + int2
}

How to define in swift an optional variable for a function type, which can be nil?

You just have to wrap it in parentheses:

var OnClick: ((UIButton!) -> ())? = nil

Can function in Swift return different data types?

You should return the tuple type like this:

func getNumberOfRows(for section: Int) -> (Int, String) {}

Also, for convention your code, you can use typealias keyword to define name for your tuple:

typealias NumberOfRowsInfo = (row: Int, someString: String)

func getNumberOfRows(for section: Int) -> NumberOfRowsInfo {}

And get data like this:

let info = getNumberOfRows(for: section)
print("Row: \(info.row), string: \(info.someString)")

pass different struct type for a function

You can define an enum with different cases and their associated values like:

enum ABType {
case a(TypeA)
case b(TypeB)
}

so you can implement the function like:

func getData(type: ABType) {
switch type {
case .a(let objectA): print(objectA.dataArr)
case .b(let objectB): print(objectB.data)
}
}

Also, you can fill the function like:

let typeA: TypeA?
...
getData(type: .a(typeA!))
let typeB: TypeB?  
...
getData(type: .b(typeB!))


Related Topics



Leave a reply



Submit