🌱 Beginner's Guide lesson 6 of 12

Functions

As programs grow, you'll notice yourself writing the same few lines over and over. A function lets you write them once, give them a name, and then use that name whenever you need them. It's like teaching the computer a new word.

Your first function

rupamun means function. Here's one that prints a little banner:

[ try-it.sts ]
bongSlanhOun "banner";
rupamun banner() {
    jongyeytha "*~*~*~*~*~*~*~*";
}

banner();
jongyeytha "  WELCOME!";
banner();
[ what it prints ]
*~*~*~*~*~*~*~*
  WELCOME!
*~*~*~*~*~*~*~*

There are two separate steps here:

  1. Defining the function: rupamun banner() { ... } teaches steav2 what banner means. On its own, this doesn't run anything.
  2. Calling the function: banner(); actually runs the code in its block. We called it twice, so the banner appears twice.

The round brackets () after the name are how you call a function. Leave them off and steav2 won't run it.

Parameters: giving a function some input

A function becomes much more useful when you can hand it some information to work with. These inputs are called parameters, and they go inside the brackets:

[ try-it.sts ]
bongSlanhOun "greet";
rupamun greet(name: Ahsor) {
    jongyeytha "Hello, " + name + "! Nice to meet you.";
}

greet("Dara");
greet("Mealea");
greet("Vuthy");
[ what it prints ]
Hello, Dara! Nice to meet you.
Hello, Mealea! Nice to meet you.
Hello, Vuthy! Nice to meet you.

name: Ahsor means "this function takes one input, called name, and it must be text". Each time we call greet, the value in the brackets (called an argument) gets put into the name box for that call.

Unlike variables, parameters always need their type written out. steav2 can't guess, because the function hasn't been called yet when it's defined.

A function can take several parameters, separated by commas:

[ try-it.sts ]
bongSlanhOun "stars";
rupamun stars(count: LekKut, symbol: Ahsor) {
    akthe line = "";
    somhab (akthe i: LekKut = 0; i < count; i += 1) {
        line += symbol;
    }
    jongyeytha line;
}

stars(3, "*");
stars(5, "<3");
[ what it prints ]
***
<3<3<3<3<3

morvenh: giving an answer back

So far our functions print things. Often you want a function to work something out and hand the answer back, so you can use it in the rest of your program. That's called returning a value, and morvenh means return:

[ try-it.sts ]
bongSlanhOun "square";
rupamun square(x: Lek) -> Lek {
    morvenh x * x;
}

jongyeytha square(4);
akthe big = square(12);
jongyeytha big;
jongyeytha square(3) + square(4);
[ what it prints ]
16
144
25

The -> Lek after the brackets says "this function gives back a Lek". The arrow is like the answer coming out of a machine. morvenh x * x; works out x * x and sends it back to wherever the function was called, so square(4) turns into 16.

morvenh also stops the function straight away, even in the middle. That's handy for decisions:

[ try-it.sts ]
bongSlanhOun "biggest";
rupamun biggest(a: Lek, b: Lek) -> Lek {
    ber (a > b) {
        morvenh a;
    }
    morvenh b;
}

jongyeytha biggest(3, 9);
jongyeytha biggest(10, 2);
[ what it prints ]
9
10

If a > b, the first morvenh sends back a and the function is done: the last line never runs.

steav2 checks your functions too

Because every parameter has a type, steav2 can check every call before running anything:

[ x_x broken on purpose ]
bongSlanhOun "wrong input";
rupamun double(x: LekKut) -> LekKut {
    morvenh x * 2;
}
jongyeytha double(2.5);
[ what it prints ]
[line 5] Error at '2.5': '2.5' isn't a whole number, it can't be a LekKut

It also notices if you promise an answer but might not give one:

[ x_x broken on purpose ]
bongSlanhOun "missing answer";
rupamun half(x: Lek) -> Lek {
    ber (x > 0) {
        morvenh x / 2;
    }
}
jongyeytha half(10);
[ what it prints ]
[line 2] Error at 'half': 'half' returns LekThom but can reach the end without a morvenh

(Remember, Lek is another name for LekThom.) What should half(-4) give back? We never said! Adding a morvenh at the very end fixes it.

Functions calling functions

Functions can call other functions, and that's how big programs get built: out of small, simple pieces that each do one job well.

[ try-it.sts ]
bongSlanhOun "party";
rupamun pizzasNeeded(people: LekKut) -> LekKut {
    // each pizza feeds 3 people, round up
    morvenh (people + 2) / 3;
}

rupamun report(people: LekKut) {
    jongyeytha people + " guests need " + pizzasNeeded(people) + " pizzas";
}

report(3);
report(10);
report(25);
[ what it prints ]
3 guests need 1 pizzas
10 guests need 4 pizzas
25 guests need 9 pizzas

Why bother with functions at all?

  • Less repetition: write the code once, use it everywhere.
  • Fewer bugs: fix a mistake in one place and it's fixed everywhere.
  • Easier to read: pizzasNeeded(people) says what it does. (people + 2) / 3 makes you think.

Your turn

  1. Write a function celsiusToFahrenheit(c: Lek) -> Lek that returns c * 9 / 5 + 32, and print the result for 0, 37 and 100. Hint: water boils at 212 degrees Fahrenheit.
  2. Write isEven(n: LekKut) -> Boolean, using the trick from the Loops lesson. Hint: morvenh (n / 2) * 2 == n;
  3. Change report above so it says 1 pizza instead of 1 pizzas. Hint: a ber inside report.

Solution for exercise 1:

[ try-it.sts ]
bongSlanhOun "temperatures";
rupamun celsiusToFahrenheit(c: Lek) -> Lek {
    morvenh c * 9 / 5 + 32;
}
jongyeytha celsiusToFahrenheit(0);
jongyeytha celsiusToFahrenheit(37);
jongyeytha celsiusToFahrenheit(100);
[ what it prints ]
32
98.6
212
  • steav2♡ help
  • Y2K✓ ready
  • wasminside
  • .stsvalid

best viewed at 1024x768 ☆ made with ♡ ☆ the reference is steav2's own docs