Why Does Function Has Multiple Return Types in Swift

Why does function has multiple return types in swift?

This function actually just returns another function with Int as parameter and as return type. That does this:

(Int) -> Int

In this case this function returns one of your sub functions.


So then when you need to get result of your sub function, do it like this

chooseStepFunction(backward: true)(1)  /* returns 0 */
chooseStepFunction(backward: false)(1) /* returns 2 */

Swift function returning two different types

Edit: I'm editing this answer, because I think my old answer is mostly just leading people down the wrong road.

The ability to return one of two (completely-unrelated) types might sound like it would solve your problem, but it almost certainly does not. Swift is a statically typed language, which means that it limits what you can do to a value, depending on its type (this limitation is beneficial, because you know this will always work!).

You can multiply Ints, and you can concatenate Strings, but you can't multiply Strings or concatenate Ints. But what if you had a value that was either a hypothetical (Int || String)? What could you do with that?

  • Well you can't multiply, because what if it was a String underneath? That wouldn't make sense.

  • You couldn't concatenate it either, because what if the underlying value was an Int? That wouldn't make sense, either.

The only thing that would be allowable, is to only do those things which are supported by both Int or String. And what is that exactly? Well, you could get the description: String, and that's... about it.

The modern solution to this problem is to describe the capabilities of the result using a protocol, and to return that. Here's an example:

protocol ModeOfTransport {
func transport(cargo: String)
}

struct Car: ModeOfTransport {
func transport(cargo _: String) {
print("I'll put the light cargo in my trunk and drive it.")
}
}

struct Train: ModeOfTransport {
func transport(cargo: String) {
print("I'll put attach the heavy cargo in a new car and pull it.")
}
}

func getAppropriateModeOfTransport(cargoWeight: Int) -> ModeOfTransport {
if cargoWeight < 500 {
return Car()
} else {
return Train()
}
}

let modeOfTransport = getAppropriateModeOfTransport(cargoWeight: 1234)
modeOfTransport.transport(cargo: "Sample Cargo")

Original answer:

You can use Enumeration

You can use an enumeration with associated values to achieve the behaviour you're looking for. They're much like a nicer version of C's unions.

enum Foo { //TODO: Give me an appropriate name.
case type1(String)
case type2(Int)

static func getValue(type: String) -> Foo {
switch (type) {
case "type1": return type1("exampleString")
case "type2": return type2(56)
default: fatalError("Invalid \"type\"");
}
}
}

let x = Foo.getValue(type: "type1")

This is actually very annoying, because the only way to do anything sensible with these values it to consume them conditionally, by switching on its type and responding accordingly:

switch x {
case .type1(let string): funcThatExpectsString(string)
case .type2(let int): funcThatExpectsInt(int)
}

If you're not careful, these switches will consume your entire codebase. This is why I recommend the protocol-base approach above.

Return multiple values from a function in swift

Return a tuple:

func getTime() -> (Int, Int, Int) {
...
return ( hour, minute, second)
}

Then it's invoked as:

let (hour, minute, second) = getTime()

or:

let time = getTime()
println("hour: \(time.0)")

Swift - Function Types as Return Types

To make it clearer let's create a type alias

typealias functionWithIntParameterAndIntReturnValue = (Int) -> Int

and change chooseStepFunction to

func chooseStepFunction(backwards:Bool) -> functionWithIntParameterAndIntReturnValue {
return backwards ? stepBackward : stepForward
}

This matches exactly the signatures of both step... functions

(input: Int) -> Int

which have an Int parameter and return an Int. If you omit the parameter label you get

(Int) -> Int

The parentheses are a semantical requirement

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)")

What is the purpose of the two arrows in the user defined chooseStepFunction() in Swift?

Given:

(x) -> (y) -> z

You would read this as:

A function which accepts x and returns a function which accepts y and returns z.

So in this case, chooseStepFunction is a function that takes a bool and returns a function that takes an int and returns an int. This is right-associative, so you would read it as:

(backwards: Bool) -> ((Int) -> Int)

It's easiest to read this if you remember that the first set of parentheses (around Bool) aren't particularly special. They're just like the second set (around Int). (The parentheses aren't actually needed. (Int) -> Int is the same as Int -> Int.)

Realizing this will help when you encounter currying:

func addTwoNumbers(a: Int)(b: Int) -> Int

This is really the same as:

(a: Int) -> (b: Int) -> Int

A function that takes an int and returns a function that takes an int and returns an int.



Related Topics



Leave a reply



Submit