The problem: repeated code
Imagine a student who has to write the same three lines on a whiteboard three times. The direct way to do this in a program is to write each println out three times, nine statements in total:
println("This is Andy")
println("Andy made a mistake")
println("Andy suffers the consequences")
println("This is Andy")
println("Andy made a mistake")
println("Andy suffers the consequences")
println("This is Andy")
println("Andy made a mistake")
println("Andy suffers the consequences")
That is manageable for three copies. Now picture 100 copies of ten lines, or a request to change the name in every one of them. The program grows with each repetition, and every change has to be made in every copy. A copy you forget leaves the program inconsistent.
The fix: write it once, call it many times
A function packages the lines under a name. You write the lines once, in the body, and run them with a call each time you need them:
fun printMessage() {
println("This is Andy")
println("Andy made a mistake")
println("Andy suffers the consequences")
}
fun main() {
printMessage()
printMessage()
printMessage()
}
Both programs print the same nine lines, but the function version is shorter and it scales. Three more repetitions cost three more lines of the form printMessage(), not nine copied println statements. If the student's name changes to Mike, you edit the three lines inside the function, and every call picks up the change.
That is the main reason functions exist: they remove duplication, and so there is one place to read, test and fix each piece of logic. A second reason is that a name documents the intent. A reader who sees printMessage() knows what the line does without reading its body.
Kotlin details
- Defining isn't running. The definition only stores the body. Nothing prints until a call such as
printMessage()executes it. - Each call runs the full body. Three calls give three complete sets of output, always starting at the first line of the body.
- No return type is written. A function with a block body and no declared return type returns
Unit, Kotlin's "nothing useful". You don't write it for functions that only print. - Calls go inside functions. The snippets above put the calls in
main. In this lesson they go inmainFunction.
The lesson's exercise, step by step
The starter code has a comment where the function goes, and a mainFunction that already prints Sorry, I didn't hear you between two comments. The task is to write one function and call it twice, with the extra line coming between the two calls.
- Define
introduceYourselfunder the first comment, withfun, empty parentheses and braces. It takes no input and returns nothing, so no return type is needed. - Print the first line inside it,
My name is Andy. - Print the second line,
I code in Python, on the next line of the body. Both introduction lines now live in one place. - Call
introduceYourself()inmainFunctionunder the first comment. This is the first introduction. - Call it again under the last comment, after the
Sorry, I didn't hear youline. The two lines print a second time without being typed again.
// Function goes here:
fun introduceYourself() {
println("My name is Andy")
println("I code in Python")
}
fun mainFunction() {
// Introduce yourself the first time:
introduceYourself()
println("Sorry, I didn't hear you")
// Introduce yourself again:
introduceYourself()
}
Run through main, this code prints:
My name is Andy
I code in Python
Sorry, I didn't hear you
My name is Andy
I code in Python
The text of the second line is part of what the lesson checks, so it must match exactly, even though the program is written in Kotlin.
Common mistakes
- Forgetting the second call. The output then ends after
Sorry, I didn't hear you. - Calling before the apology line. Both calls must be placed on either side of that
println, so the output order is introduction, apology, introduction. - Leaving out the parentheses.
introduceYourselfwithout()is not a call, and the compiler rejects it. - Copying the two
printlnlines intomainFunctioninstead. The output might match, but the point of the lesson, a single place for the introduction, is lost.
Key takeaways
- A function lets you write a block of code once and run it as many times as you need.
- Changing the function body changes every call.
- Name a function after what it does, so that calls read like instructions.