Programming in Kotlin: Fundamentals

Aug 9 2022 · Kotlin 1.6, Android 12, IntelliJ IDEA CE 2022.1.3

Part 3: Functions & Nullability

23. Return Data From Functions

Episode complete

Play next episode

About this episode

Leave a rating/review

See forum comments
Cinema mode Mark complete Download course materials
Previous episode: 22. Write Custom Functions Next episode: 24. Challenge: Work with Functions

Get immediate access to this and 4,000+ other videos and books.

Take your career further with a Kodeco Personal Plan. With unlimited access to over 40+ books and 4,000+ professional videos in a single subscription, it's simply the best investment you can make in your development career.

Learn more Already a subscriber? Sign in.

Heads up... You've reached locked video content where the transcript will be shown as obfuscated text.

Sometimes, you might want a variable or constant to be a result of a computation. This computation might require different data and resources and doing this directly in a variable might not be possible. For this, you do this computation inside a function, but this time around, a function that returns a value. Here's the syntax for a function that returns a value. After the closing parenthesis of the function parameters, you add the return type. Then, the last statement inside the body would be the data that is returned. This data must be preceded with the return keyword. If you followed along and built the bullseye app, you might remember writing functions like difference amount or points for current round. Both of these methods returned a value. When a function or method returns a value, once the function is called, that value can be stored or used in place. Points for current rounds calculated and returned the points for the current round and different amount subtracted the slider value from a target value and returned it. In earlier episodes, you created lots of ranges and used loops to iterate over them. But creating ranges can be done in different ways. And that's a good use case for a function. Let's create a function for ranges. You start by creating the bare bones. Enter the following code. This is the simplest version of this function. You can see it takes in two parameters, the stats and the end of the range. Then, it returns a range created with these parameters and it uses the return statements to do this. You can also see the return type of dysfunction is an IntRange, which means that this function must return an IntRange, else you'll have a compiled time error. Let's create a range using it and print out the elements using a follow loop. Add in the following code. Run the project to see the outputs. Cool, the range is printed out. You'll be printing out ranges in this episode. So, this would be a good piece of code to refactor into a function. Create a function directly below the create range function and move the code into it like so. This function has one parameter, which is the range to print. You change it from closed range to a more generic name called range. And this value is what you defined in the parameter. This makes this function reusable for different IntRanges. Also, notice that the function has no return type. But behind the scene, if a function doesn't return anything then it returns a unit by default. A unit type is the equivalent of the voyage type in Java and it simply means nothing. So the print range function returns nothing. You can add it as a return type of the print range function like so, or you can remove the entire return type as by default, units is the return type. Now, go ahead and replace the previous print code with a function like so. Now this is much better. Run the project to see the outputs didn't change. Functions represents tax or actions. There are bits of codes that do something. That action can be represented by using a verb as a function name. Print range prints the value from a range in the run panel. We have some methods from the bullseye game that uses this naming convention. The stack new game methods starts a new game while the show result methods shows the score on a popup dialog. The don't return a value, but instead just perform an action and ends its execution. When functions return a value, their names can be a noun. And if you recall the methods from bullseye, different amounts and points for current round are named for the values they return. When you call those methods, you get the amounts of all the points for the current round. Naming functions or methods for the value they return is a command convention. This is not a rule, as you can see. We didn't follow it when naming the createRange function. Even though it returned the value, its name was not a noun. The verb createRange made more sense in this case. If you're working with a team, they may have a naming convention for you to follow. If you're your own boss, how you name your functions is another stylistic decision you have to make. In either case, staying consistent can make it easier to read and reason about your code in the future. There are different types of ranges though, as we learned in the second part of this course. What if you want the range to be half open? Remember, a half open range excludes the last number in the given range. Let's add a bullion to correct range to determine if it should return a half open or closed range. Update the function to the following. You can see that it's half open parameter has a default value of false, which would be used if it don't pass in the arguments when calling the function. Notice we have to return calls and the if statement. You can improve this behavior. Since if statements are expressions you can simply return an expression year and the IDE already hints us about this. Go ahead and hover over the if statement. Then select the lift return out of if action. And your code is updated accordingly. Next, create a half open range and print it out. Run the project to see the new range printed out. And you can see that the number 10 is excluded from the range. Do note that a closed range will still return the previous range because a default value of it's half open is false. Instead of using a regular block of code with a return statement, you can turn this entire function to an expression. To do this, click on the return statement. Then, click the bulb icon and select convert to expression body. And your code updates accordingly. By using an expression the same way you use it for values and if, else, or when statements, you can return an expression for the function. And that's what you just did here. Notice that there is no return statement here. It's not needed as you have the assignment operator. You can even go one step further and remove the return type. Because, as you know, Kotlin can infer it from the expression. This is now much better than the original, right? Run the project to see the output doesn't change. But what if you wanted to return a different type of range and keep the same name of the function? This is called overloading. Let's see how it works. So overload the function to return a different type of a range, copy and paste the create range function. Then update it to the following. This function now accepts characters and creates a range of character symbols. When you use it, pass in characters instead of integers and it should work the same. Notice how when you type out the name of the function, you get two of the same functions but different parameters or return types. You have an error on the print range function and this is because it cannot print the range of characters because it was coded to print only IntRanges. However, you can overload it to work with a character range too. Copy and paste the print range function. Then updated it to the following. Run the project to see the character range. The rule of thumb for overloading functions is this. The overloaded function must have a different number of parameters or different parameter types. Do note that the return type alone is not enough to distinguish two functions. The compiler will still be able to tell the difference between these functions within a given scope. It's worth noting that overloading should be used with care. Only use overloading for functions that are related and similar in behavior just like we've done in this episode.