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 Int
s, and you can concatenate String
s, but you can't multiply String
s or concatenate Int
s. 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 switch
es 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 acceptsy
and returnsz
.
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
Swift Package Manager with Resources Compile Errors
Value of Type 'Authdataresult' Has No Member 'Uid'
Filtering Dictionary in Swift 4 Fails in Xcode, But Succeeds in Playground
Raw Value of Enumeration, Default Value of a Class/Structure, What's the Different
Swift:Program for Addition of 2 Numbers Using Closure
Updating Switfui View When Coredata Changes
How to Use Core Data Value from Picker? #Swiftui #Coredata
Swift - Creating Shadow with 2 Different Colours for Imageview
Color Ouput with Swift Command Line Tool
Swift Check If Value Is of Type Array (Of Any Type)
Self. in Trailing Swift Closures, Meaning and Purpose
Use Huge Numbers in Apple Swift
Xcode Gm: No Swift Language for Os X Command Line Tool Project
Swift: Skspritekit, Using Storyboards, Uiviewcontroller and Uibutton to Set in Game Parameters
Initializer for Conditional Binding Must Have Optional Type, Not '[String:Any]'