Pocket Studio Academy
HomePart 11.8

Functions — naming a recipe

Free lesson10 min read·4 questions

A function gives a name to a block of steps so you can run it whenever you like, from anywhere, without writing it out again. Everything you build from Part 3 onwards is functions calling functions.

The same six lines, in four places

Imagine a dice game. When a player wins you want to print a little banner:

kotlin
1println("*******")
2println("YOU WIN")
3println("*******")

Fine — until you need the same banner in four places. Now the same three lines exist four times. Change the stars to hyphens and you have four edits to make, and you will forget one.

There is a better move: give those three lines a name.

kotlin
1fun banner() {
2  println("*******")
3  println("YOU WIN")
4  println("*******")
5}

Now anywhere in the program you write banner() and all three lines run. Four places, one definition. Change it once and every use changes with it.

Think of it like this

Think about a recipe card.

Nobody writes "crack two eggs, add milk, whisk, heat the pan…" in the middle of a shopping list. They write "make pancake batter" and keep the details on a card in a drawer.

That is a . The name on the card is the function's name. The steps on the back are its body. Getting the card out and following it is the function.

And notice what the card buys you. You can follow it on Tuesday and again on Friday without rewriting anything. You can hand it to somebody else. And when you improve the recipe, every future pancake improves — because there is only one card.

Making one

kotlin
1fun greet() {
2  println("Hello!")
3}

Four pieces, left to right:

  • fun — the keyword that says "a function starts here".
  • greet — the name. Same rules as any other name, and by convention it starts with a verb, because a function does something.
  • () — the round brackets. Empty for now; Lesson 1.9 fills them.
  • { ... } — the body: the steps that run when it is called.

To run it, write its name with brackets:

kotlin
1fun main() {
2  greet()
3  greet()
4}

That prints Hello! twice. The brackets are how Kotlin knows you mean do it now rather than just naming it.

Note

You have been writing a function since Lesson 1.1. main is one — the particular function Kotlin looks for and calls when you press Run. Functions you define outside main go above or below it, at the top level of the file; both work.

Handing something in

A function that always does exactly the same thing is limited. Give it a and the same recipe works on different values:

kotlin
1fun greet(name: String) {
2  println("Hello, $name!")
3}

name: String says: this function needs one piece of information, it is called name inside the body, and it must be a String. Now the must supply one:

kotlin
1greet("Ada")
2greet("Grace")

The value you hand over is an . Two words for two sides of the same handover: the parameter is the slot in the definition, the argument is the value at the call.

Leave the argument out and Kotlin says No value passed for parameter 'name'. Hand over the wrong kind and it says Type mismatch. The on the parameter is a contract, and both sides are held to it.

Handing something back

So far our functions have done things. Often you want one to work something out and give you the answer:

kotlin
1fun double(n: Int): Int {
2  return n * 2
3}

The : Int after the brackets is the — a promise about what comes back. Inside, return is the word that actually hands it over, and it ends the function immediately: nothing after a return runs.

Now double(21) is not an instruction, it is a value. You can use it anywhere a number belongs:

kotlin
1println(double(21))
2val total = double(5) + double(10)

If a function returns nothing, you write no return type at all. Kotlin quietly calls that type ; you will see the word in error messages, and now you know what it means: "nothing useful comes back".

Tip

When the whole body is one expression, Kotlin lets you drop the brackets and the return entirely:

kotlin
1fun double(n: Int) = n * 2
2fun isEven(n: Int) = n % 2 == 0

These are called single-expression functions. They are extremely common in real Kotlin, and the return type is inferred — though writing it out is still allowed, and helps on anything non-obvious.

Why bother?

Beyond avoiding repetition, functions do three quieter things that matter more as programs grow:

  1. They name an idea. isEven(n) says what it means. n % 2 == 0 makes the reader work it out. The code becomes the documentation.
  2. They give you one place to fix things. A bug in a function is one bug. The same code copied five times is five bugs, and you will fix four.
  3. They keep their mess to themselves. Names declared inside a function vanish when it ends — that is again. A function cannot accidentally trample a name used somewhere else.

Aim for functions that do one thing and are named after that thing. If the name needs the word "and", it is probably two functions.

A complete program, stepped through

Try it in Pocket Studio
  1. Open Pocket Studio, tap Projects, open KotlinLab, then open Lab.kt.
  2. Select everything in the file — including fun main() itself this time — and delete it.
  3. Type in the whole fifteen-line program from the walkthrough above. greet and double go above main, at the left-hand edge, not inside it.
  4. Tap Run. The Output panel should show Hello, Ada!, Hello, Grace!, 42, Total: 30.
  5. Add a third call, greet("you"), and run again. One new line, no new logic.
  6. Now shorten double. Replace all three of its lines with the single line fun double(n: Int) = n * 2 and run. Identical output.
  7. Break it on purpose: delete the return word from double (if you put the long version back) and run. Read A 'return' expression required in a function with a block body.
  8. Break it a second way: change greet("Ada") to just greet() and run. Read No value passed for parameter 'name'. Put it back.
Error Doctor5 common errors
e: A 'return' expression required in a function with a block body ('{...}')
MeansThe function promises a return type after its brackets, but at least one path through the body ends without returning anything.
FixAdd a return to every route out of the function — including inside every branch of an if. Or, if it genuinely returns nothing, delete the : Int promise.
e: No value passed for parameter 'name'
MeansThe function requires an argument and the call did not give one.
FixPut a value in the brackets: greet("Ada"). Lesson 1.9 shows how to give a parameter a default so the caller may leave it out.
e: Too many arguments for public final fun greet(): Unit defined in root package
MeansYou passed something to a function that takes nothing. Unit in that message just means "this function returns nothing".
FixEmpty the brackets at the call, or add a parameter to the definition if the function really should accept a value.
e: Type mismatch: inferred type is String but Int was expected
MeansThe argument is the wrong kind — text where a number was required, usually "5" instead of 5.
FixRemove the quote marks, or convert with .toInt() if the value genuinely arrives as text.
e: Unresolved reference: dubble
MeansNo function by that name exists. Kotlin checks the spelling of a call exactly as it checks a name.
FixCheck the spelling and the capitals. Also check the function is defined at the top level of the file, not accidentally nested inside another function's brackets.
Recap
  • A names a block of steps so you can it from anywhere, as often as you like, without repeating yourself.
  • fun name() { ... } defines one; name() runs it. main is the one Kotlin runs for you.
  • A is the slot in the definition; the is the value you hand over at the call. Kotlin checks the of each.
  • A after the brackets promises what comes back, and hands it over — ending the function immediately. No return type means : nothing comes back.
  • Single-expression functions drop the brackets: fun double(n: Int) = n * 2.
  • Aim for one job per function, and name it after that job.
  • Next: parameters get much more comfortable — default values so callers can leave things out, and named arguments so a call reads like a sentence.