DEV Community

Gamya
Gamya

Posted on

Swift Functions โ€” Returning Values and When to Skip the Return Keyword ๐Ÿ“ค

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 return keyword 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)
Enter fullscreen mode Exit fullscreen mode

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
}
Enter fullscreen mode Exit fullscreen mode

Breaking it down:

  • Takes two String parameters
  • Returns a Bool โ€” either true or false
  • 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()
}
Enter fullscreen mode Exit fullscreen mode

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
Enter fullscreen mode Exit fullscreen mode

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)
}
Enter fullscreen mode Exit fullscreen mode

Same for the Pythagorean theorem:

func pythagoras(a: Double, b: Double) -> Double {
    sqrt(a * a + b * b)
}
Enter fullscreen mode Exit fullscreen mode

And the letter comparison:

func areLettersIdentical(string1: String, string2: String) -> Bool {
    string1.sorted() == string2.sorted()
}
Enter fullscreen mode Exit fullscreen mode

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
Enter fullscreen mode Exit fullscreen mode

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
Enter fullscreen mode Exit fullscreen mode

The rule is simple:

โœ… One expression in your function โ†’ you can skip return
โŒ Statements or multiple lines โ†’ you must use return


๐Ÿ”€ 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)!"
    }
}
Enter fullscreen mode Exit fullscreen mode

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
    }
}
Enter fullscreen mode Exit fullscreen mode

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
}
Enter fullscreen mode Exit fullscreen mode

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
}
Enter fullscreen mode Exit fullscreen mode

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!
Enter fullscreen mode Exit fullscreen mode

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"))
Enter fullscreen mode Exit fullscreen mode

Output:

14
true
5.0
Welcome back, Lord Naruto! ๐Ÿƒ
Enter fullscreen mode Exit fullscreen mode

๐ŸŒŸ Wrap Up

  • Use -> Type to tell Swift what your function returns
  • Use return to send the value back
  • When your function has one expression โ€” skip return entirely
  • Expressions resolve to a value โ€” statements perform actions
  • if can act as an expression when each branch returns directly
  • Use return alone 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)

Collapse
 
technogamerz profile image
The Lazy Girl (โ โ—•โ แด—โ โ—•โ โœฟโ )

You are explaining very well, thank you๐Ÿ˜Šโค๏ธ๏ฝกโ โ—•โ โ€ฟโ โ—•โ ๏ฝก