Comp 110 Functions with (non-void) Return Types

Functions with non-void Return Types

In functions that have non-void return types (dont worry, we'll cover "void" later), a value is returned by the function when we call it. We know a function has a non-void return type by looking for a return type in the first line of the function definition or a return statement in the body of the function. Here's an example:

let fun = (): number => { // 'number' indicates the return type is number 
    return 110; // this is the return statement
};

In our function declaration after the parentheses and colon we see the word number, which is the return type. 

Another clue that this is a non-void function is that in the body, the statement return 110; means that this function will return the number value 110. Void functions will not include a return statement.

Key points about return

  • When a function is evaluated, once the computer hits a return statement, execution of the function ends and the specified value is returned. Any code within the function after the return statement will not be evaluated.
  • Only one return statement is evaluated during any one function call.
  • The return type declared in the first line of the function must be the same as the data type of what is actually being returned from within the body of the function.

Examples of non-void functions and their return statements used incorrectly:

// Does not return a number:
let a = (): number => {
  return "Hello!";
};

// "Hello!" will not be printed
// once a function 'returns,' the function stops executing! 
// no other code in the function body will execute!
let b = (): number => {
    return 2;
    print("Hello!");
};

// The second return will never be reached, 
// because 1 was already returned:
let c = (): number => {
    return 1;
    return 2;
};

// The non-void function does not have a return statement:
let d = (): number => {
    print(4);
};

How it works

When we call a function, the computer drops a bookmark there and jumps into the definition of the function it called. It does whatever we tell it in the function body and reaches the return statement. Once the computer hits a return it takes the value from the return statement and goes back, or returns, to the place of the bookmark. Here, it substitutes the function call with the value it brought back! Seeing this in action with an example will help it make more sense:

import { print } from "introcs";
 
export let main = async () => {
        let myFavCourse = makeCourse("COMP", 110);
        print("The best course at Carolina is: " + myFavCourse);
};

let makeCourse = (name: string, level: number): string => {
        let course = name + level;
        return course;
};
 
main();

We've got a lot going on here! This little program starts out with the import statement and the main function. 

After that, we see the definition for the makeCourse function. In this function, we declare the return type to be string. Within the function body, we see the statement return course;. The type of what we're returning (the value stored in course) matches the return type we specified since course is the result of concatenating name and level so its type is also string.

Note: until a function is called (even main()), we only need to acknowledge the function definitions...we dont really care about the function body until a function is called and that code is actually executed!

When this program runs, the computer processes what we've got with the import statement first, then it sees the definition of the main function, and then it sees the definition of the makeCourse function. 

Next, the computer calls main(). This sends it into main's function body, which includes a call to the makeCourse function using arguments "COMP" and 110. At this function call, the computer drops a bookmark and heads on to the makeCourse function. 

There, the computer uses the arguments to make the string for the course variable, which it then returns. The computer brings the value of course, which is "COMP110", back with it into main where the bookmark was left, and drops this value there. So, myFavCourse is initialized with "COMP110". The last step in the program is to use this string in the print statement, then we're done!

Usefulness

Functions that return are great for when we need to go through a lot of steps to get a value that we want to use in our code somewhere. Calling a non-void function tells the computer to head over to the function definition, do everything, and come back with the result once it's done. This is nice if we're doing complicated math or trying to combine a bunch of data in some way. We won't have to worry about all the little steps each time we need the value. Instead, we can tell the computer to go do the hard work for us and come back with the result, which we can then use as we keep going in our program.