What is the point in returning values?

Viewed 133

I'm fairly new when it comes to C++ so bear with me. When learning about return values in functions, I was told that the proper way to write pure functions is to return a value every time. I attempted this in a small function that checks the user's age and returns whether or not they're an adult. The issue here, at least for me, is understanding the proper utilization of these return values. For example, in this code snippet here I'm returning whether or not they are an adult given their age in years.

main.h

#pragma once
#define LOG(x) std::cout << x
#define LOGCIN(x) std::cin >> x

bool check_age(int age) {
    if (age >= 18)
        return true;
    else
        return false;
}

main.cpp

#include <iostream>
#include "main.h"

bool check_age(int age);

int main() {
    int age;
    LOG("Enter your current age in years: ");
    LOGCIN(age);
    bool adult = check_age(age);
    if (adult == true) {
        LOG("You are an adult!");
    } else {
        LOG("You are not an adult!");
    }
}

However, when I rewrote this code without using return values, I got this.

main.h

#pragma once
#define LOG(x) std::cout << x
#define LOGCIN(x) std::cin >> x

void check_age(int age) {
    if (age >= 18)
        LOG("You are an adult!");
    else
        LOG("You are not an adult!");
}

main.cpp

#include <iostream>
#include "main.h"

void check_age(int age);

int main() {
    int age;
    LOG("Enter your current age in years: ");
    LOGCIN(age);
    check_age(age);
}

As you can see, the latter code choices is simpler and more compact. If code requires more lines and takes longer to write with return values, then what's even the point in using them?

3 Answers

Often the purpose of a function is not just to log something to cout but instead make a decision based on some parameters, or return a value so it can be used flexibly. An example of this would be in binary search:

while(l <= r) {
    int mid = (l+r)>>1;
    if(check(/* parameters */)) {
        //update answer
        r = mid+1;
    } else l = mid-1;
}

Of course, you could make your function edit a global variable and make decisions based off of that; but it will make the code more verbose:

while(l <= r) {
    int mid = (l+r)>>1;
    check(/* parameters */);
    if(ok /* global variable*/) {
        //update answer
        r = mid+1;
    } else l = mid-1;
}

As an additional example, it is a lot easier to write (and read):

round(a)+ceil(b)

than have these functions update global variables.

Imagine the function is provided by someone else. In that case, we may not be able to know its implementation. How does our program know whether the function succeeds or not?

Besides, sometimes we want to know some information from a function. I think that's why return values are used.

Returning a value from the function serves an important purpose - it allows you to separate the two concepts of "determine whether this person is an adult" and "print some stuff about this person".

You could imagine tons of scenarios where the program would need to know if someone was an adult without printing it to console - such as allowing them to buy alcohol, register for college, etc etc etc.

And you could also imagine that if you knew someone was an adult, there might be a ton of different ways you'd like to print that (imagine other languages, or rendering it on a webpage, or etc etc).

So by returning the value, you enable this separation of concepts which makes your code much more flexible in the future.

Maybe you don't need that for a toy example, but that's sorta beside the point when you're asking a broad design question like this.

Related