In our last article we learned how to create functions and pass data into them. But functions can also send data back โ they do some work and return the result. That's what makes them truly powerful. ๐ง
๐ค Returning Values from Functions
To return a value from a function you need two things:
- An arrow
->followed by the data type before the opening brace โ telling Swift what type of data will come back - The
returnkeyword to actually send the data back
Here's a simple example โ rolling a dice:
func rollDice() -> Int {
return Int.random(in: 1...6)
}
let result = rollDice()
print(result)
The -> Int tells Swift "this function will send back an integer". The return keyword sends the actual value back to wherever the function was called.
Now we can call rollDice() anywhere in our app and always get a random number between 1 and 6! If we later want to use a 20-sided dice, we change it once in the function โ and every place that calls it automatically gets the new behaviour. โ
โ ๏ธ Important: When you promise Swift your function returns a value, Swift holds you to it. If you forget to return something your code won't even build โ Swift makes sure you always keep your promise!
๐ค A Real Example โ Comparing Strings
Let's try something more interesting. Do two strings contain the same letters regardless of order? So "abc" and "cab" should return true because they both have the same letters โ just shuffled.
Here's how we can solve it:
func areLettersIdentical(string1: String, string2: String) -> Bool {
let first = string1.sorted()
let second = string2.sorted()
return first == second
}
Breaking it down:
- Takes two
Stringparameters - Returns a
Boolโ eithertrueorfalse - Sorts both strings alphabetically using
.sorted() - Compares them โ if they match, returns
true
So "abc".sorted() becomes "abc" and "cab".sorted() also becomes "abc" โ they match! ๐
We can actually simplify this โ skip the temporary constants and compare directly:
func areLettersIdentical(string1: String, string2: String) -> Bool {
return string1.sorted() == string2.sorted()
}
Same result, less code! ๐ธ
โ The Pythagorean Theorem
Remember this from school? The hypotenuse of a right-angled triangle equals the square root of the sum of the other two sides squared.
In Swift:
func pythagoras(a: Double, b: Double) -> Double {
let input = a * a + b * b
let root = sqrt(input)
return root
}
let c = pythagoras(a: 3, b: 4)
print(c) // 5.0
Swift has sqrt() built in โ we just pass it a number and it gives back the square root. Here:
-
a * a + b * bโ9 + 16โ25 -
sqrt(25)โ5.0โ
๐งน Skipping the return Keyword
Here's something really clean about Swift โ when your function contains only one line of code, you can drop the return keyword entirely:
// With return
func rollDice() -> Int {
return Int.random(in: 1...6)
}
// Without return โ exactly the same!
func rollDice() -> Int {
Int.random(in: 1...6)
}
Same for the Pythagorean theorem:
func pythagoras(a: Double, b: Double) -> Double {
sqrt(a * a + b * b)
}
And the letter comparison:
func areLettersIdentical(string1: String, string2: String) -> Bool {
string1.sorted() == string2.sorted()
}
All three do exactly the same thing as before โ just cleaner! โจ
๐ง Expressions vs Statements โ Why This Works
To understand when you can skip return โ you need to know the difference between expressions and statements:
Expressions โ code that resolves to a single value:
5 + 8 // resolves to 13
"hello".sorted() // resolves to "aehllo"
Int.random(in: 1...6) // resolves to a number
true && false // resolves to false
Statements โ code that performs an action but doesn't become a value:
let name = "Naruto" // creates a variable โ not a value itself
if score > 80 { } // performs a check โ not a value itself
for i in 1...10 { } // performs a loop โ not a value itself
The rule is simple:
โ One expression in your function โ you can skip
return
โ Statements or multiple lines โ you must usereturn
๐ if as an Expression
Swift is smart enough to let if act as an expression too โ as long as each branch returns a value directly:
// โ
This works โ each branch is a single expression
func greetNinja(name: String) -> String {
if name == "Itachi" {
"The greatest ninja who ever lived."
} else {
"Hello, \(name)!"
}
}
But this doesn't work โ because one branch creates a variable instead of returning directly:
// โ This doesn't work
func greetNinja(name: String) -> String {
if name == "Itachi" {
"The greatest ninja who ever lived."
} else {
let greeting = "Hello, \(name)!" // โ statement, not expression!
return greeting
}
}
You can even assign the result of an if directly to a constant:
func greetNinja(name: String) -> String {
let response = if name == "Itachi" {
"The greatest ninja who ever lived."
} else {
"Hello, \(name)!"
}
return response
}
This is similar to the ternary operator we learned earlier:
func greetNinja(name: String) -> String {
let response = name == "Itachi" ? "The greatest ninja who ever lived." : "Hello, \(name)!"
return response
}
Both do the same thing โ the if version is just more readable for complex conditions! ๐ธ
๐ช Using return to Exit Early
There's one more use of return worth knowing โ even in functions that don't return a value, you can use return by itself to exit the function immediately:
func attemptMission(chakraLevel: Int) {
if chakraLevel < 50 {
print("Not enough chakra! Mission aborted.")
return // exit the function right here!
}
print("Mission starting!")
print("Deploying jutsu...")
print("Mission complete! โ
")
}
attemptMission(chakraLevel: 30)
// prints: Not enough chakra! Mission aborted.
attemptMission(chakraLevel: 80)
// prints: Mission starting! โ Deploying jutsu... โ Mission complete!
This is called an early return or guard clause โ checking conditions at the top and exiting immediately if something isn't right. It keeps your code clean and avoids deeply nested if statements! ๐ช
๐งฉ Putting It All Together
// Roll a custom dice
func rollDice(sides: Int) -> Int {
Int.random(in: 1...sides)
}
// Check if ninja names are anagrams
func areNamesAnagrams(name1: String, name2: String) -> Bool {
name1.lowercased().sorted() == name2.lowercased().sorted()
}
// Calculate battle power
func battlePower(attack: Double, defense: Double) -> Double {
sqrt(attack * attack + defense * defense)
}
// Greet based on rank
func greetByRank(name: String, rank: String) -> String {
if rank == "Hokage" {
"Welcome back, Lord \(name)! ๐"
} else {
"Greetings, \(name) of the \(rank) rank!"
}
}
// Using them all
print(rollDice(sides: 20))
print(areNamesAnagrams(name1: "listen", name2: "silent")) // true
print(battlePower(attack: 3, defense: 4)) // 5.0
print(greetByRank(name: "Naruto", rank: "Hokage"))
Output:
14
true
5.0
Welcome back, Lord Naruto! ๐
๐ Wrap Up
- Use
-> Typeto tell Swift what your function returns - Use
returnto send the value back - When your function has one expression โ skip
returnentirely - Expressions resolve to a value โ statements perform actions
-
ifcan act as an expression when each branch returns directly - Use
returnalone to exit a function early even when there's no return value
Return values transform functions from simple code organizers into powerful building blocks that can calculate, compare, and produce results you can use anywhere in your app! ๐ช
Next up we'll look at returning multiple values using tuples. See you there! ๐
Top comments (1)
You are explaining very well, thank you๐โค๏ธ๏ฝกโ โโ โฟโ โโ ๏ฝก