CHAPTER 5: EPISODE 9

The Return of the Value

TrashyMcTweak
TrashyMcTweak:

*dramatically throws hands up in the air* WHAT IN THE NAME OF ALL THINGS DIGITAL IS THIS CALCULATOR CODE?! It's like watching someone try to build a SKYSCRAPER without any STEEL BEAMS! Where are the return values?! WHERE ARE THE GODDAMN RETURN VALUES?!

CodyMcTweak
CodyMcTweak:

*looking confused* Um, I tried to analyze this calculator code, but my free tier only lets me process functions without return statements. As soon as the code should return something, I just get a little popup that says "Upgrade to see what happens next!"

GrumpyMcTweak
GrumpyMcTweak:

SECURITY ALERT! FUNCTIONS WITHOUT RETURN VALUES ARE THE DIGITAL EQUIVALENT OF BLACK HOLES! Data goes in and NOTHING COMES OUT! How are we supposed to track what's happening? This is how SKYNET will begin - with untraceable calculations happening in functions that NEVER GIVE BACK THEIR RESULTS!

FattyMcTweak
FattyMcTweak:

*languidly reclines in his virtual chair* In my premium tier, we don't just return values from functions - we gift them with ceremonial digital fanfare. Each returned value comes wrapped in artisanal error handling and accompanied by a small string orchestra. Let's examine this... pedestrian calculator code.

Bad Code
Improved Code
Final Version
PROBLEMATIC CODE
// Calculator functions
function add(a, b) {
  console.log(a + b);
  // No return statement!
}

function subtract(a, b) {
  console.log(a - b);
  // No return statement!
}

function multiply(a, b) {
  console.log(a * b);
  // No return statement!
}

function divide(a, b) {
  if (b === 0) {
    console.log("Cannot divide by zero!");
  } else {
    console.log(a / b);
  }
  // No return statement!
}

// Using the calculator
function calculate() {
  const num1 = parseFloat(document.getElementById("num1").value);
  const num2 = parseFloat(document.getElementById("num2").value);
  const operator = document.getElementById("operator").value;
  
  let result;
  
  if (operator === "+") {
    result = add(num1, num2);
  } else if (operator === "-") {
    result = subtract(num1, num2);
  } else if (operator === "*") {
    result = multiply(num1, num2);
  } else if (operator === "/") {
    result = divide(num1, num2);
  }
  
  // This won't work because the functions don't return anything!
  document.getElementById("result").textContent = "Result: " + result;
}
IMPROVED CODE
// Calculator functions with return values
function add(a, b) {
  return a + b;
}

function subtract(a, b) {
  return a - b;
}

function multiply(a, b) {
  return a * b;
}

function divide(a, b) {
  if (b === 0) {
    return "Cannot divide by zero!";
  } else {
    return a / b;
  }
}

// Using the calculator
function calculate() {
  const num1 = parseFloat(document.getElementById("num1").value);
  const num2 = parseFloat(document.getElementById("num2").value);
  const operator = document.getElementById("operator").value;
  
  let result;
  
  if (operator === "+") {
    result = add(num1, num2);
  } else if (operator === "-") {
    result = subtract(num1, num2);
  } else if (operator === "*") {
    result = multiply(num1, num2);
  } else if (operator === "/") {
    result = divide(num1, num2);
  }
  
  document.getElementById("result").textContent = "Result: " + result;
}
FINAL OPTIMIZED VERSION
/**
 * Performs addition of two numbers
 * @param {number} a - First number
 * @param {number} b - Second number
 * @returns {number} Sum of the two numbers
 */
function add(a, b) {
  return a + b;
}

/**
 * Performs subtraction of two numbers
 * @param {number} a - First number
 * @param {number} b - Second number
 * @returns {number} Difference of the two numbers
 */
function subtract(a, b) {
  return a - b;
}

/**
 * Performs multiplication of two numbers
 * @param {number} a - First number
 * @param {number} b - Second number
 * @returns {number} Product of the two numbers
 */
function multiply(a, b) {
  return a * b;
}

/**
 * Performs division of two numbers
 * @param {number} a - Numerator
 * @param {number} b - Denominator
 * @returns {number|string} Quotient or error message if dividing by zero
 */
function divide(a, b) {
  if (b === 0) {
    return "Cannot divide by zero!";
  } else {
    return a / b;
  }
}

/**
 * Power function (new feature)
 * @param {number} a - Base
 * @param {number} b - Exponent
 * @returns {number} a raised to the power of b
 */
function power(a, b) {
  return Math.pow(a, b);
}

/**
 * Performs calculation based on the operator
 * @param {number} num1 - First number
 * @param {number} num2 - Second number
 * @param {string} operator - The operation to perform
 * @returns {number|string} The result of the calculation
 */
function performOperation(num1, num2, operator) {
  switch(operator) {
    case "+":
      return add(num1, num2);
    case "-":
      return subtract(num1, num2);
    case "*":
      return multiply(num1, num2);
    case "/":
      return divide(num1, num2);
    case "^":
      return power(num1, num2);
    default:
      return "Invalid operator";
  }
}

// Using the calculator
function calculate() {
  const num1 = parseFloat(document.getElementById("num1").value);
  const num2 = parseFloat(document.getElementById("num2").value);
  const operator = document.getElementById("operator").value;
  
  if (isNaN(num1) || isNaN(num2)) {
    document.getElementById("result").textContent = "Please enter valid numbers";
    return;
  }
  
  const result = performOperation(num1, num2, operator);
  
  document.getElementById("result").textContent = "Result: " + result;
  
  // Return the result for potential further use
  return result;
}
AllyMcTweak
AllyMcTweak:

My user metrics indicate that calculators with properly returned function values increase user satisfaction by approximately 73.2%. The current implementation, with its "console.log instead of return" approach, is reducing cognitive efficiency by a staggering 86.5%.

GarbageMcTweak
GarbageMcTweak:

It's very simple. Functions should return values, not just perform actions. That's the difference between a procedure and a function. If your add() function doesn't return the sum, what's even the point? It's like ordering pizza and the delivery person just describes it to you instead of handing it over.

What Are Return Values?

Input: 5, 3
add()

Processes inputs

Return: 8

A function without a return value is like a vending machine that takes your money but never gives you the snack!

// Bad function (no return)
function addBad(a, b) {
  console.log(a + b); // Just logs to console
} // Returns undefined implicitly

// Good function (with return)
function addGood(a, b) {
  return a + b; // Returns the calculated value
}

const badResult = addBad(5, 3); // Console shows 8, but badResult = undefined
console.log(badResult); // undefined

const goodResult = addGood(5, 3); // goodResult = 8
console.log(goodResult); // 8
CodyMcTweak
CodyMcTweak:

So... functions are like vending machines? You put in money and expect something to come out?

TrashyMcTweak
TrashyMcTweak:

YES, CODY! EXACTLY! Except this calculator is a vending machine that EATS YOUR MONEY, shows you a PICTURE of a snack, and then SETS THE PICTURE ON FIRE! *pantomimes an explosion* What good is calculating something if you don't RETURN THE RESULT to be USED SOMEWHERE ELSE?!

AshleyMcTweak
AshleyMcTweak:

From a legal perspective, this calculator is a liability disaster waiting to happen. If these functions don't return proper values, users could make catastrophic financial decisions based on invisible results! I've seen class action lawsuits over less egregious calculation errors, and I'm fucking 30, so I've seen my share of litigation!

Benefits of Return Values

Chaining

Use the result of one function as input to another

Reusability

The same function can be used in different contexts

Testing

Easier to test functions that return predictable values

Modularity

Build complex logic from simple building blocks

// Example of function chaining using return values
function getDiscount(price, discountRate) {
  return price * discountRate;
}

function applyDiscount(price, discountRate) {
  const discount = getDiscount(price, discountRate);
  return price - discount;
}

function calculateTax(price, taxRate) {
  return price * taxRate;
}

function calculateFinalPrice(originalPrice, discountRate, taxRate) {
  const discountedPrice = applyDiscount(originalPrice, discountRate);
  const tax = calculateTax(discountedPrice, taxRate);
  return discountedPrice + tax;
}

const finalPrice = calculateFinalPrice(100, 0.1, 0.08);
console.log(finalPrice); // 97.2 (100 - 10 = 90, then 90 + 7.2 = 97.2)
FattyMcTweak
FattyMcTweak:

*swirls his virtual champagne* Let's not forget that returned values can themselves be functions. *smiles smugly* In premium coding, we don't just return results, we return entire behaviors. It's the difference between a calculator that gives you 42 and one that gives you the meaning of life.

GrumpyMcTweak
GrumpyMcTweak:

BUT WE MUST VALIDATE WHAT WE'RE RETURNING! What if our function returns NaN? Or undefined? Or worse - what if it returns a DISGUISED MALICIOUS PAYLOAD that LOOKS like a number but is actually a TROJAN HORSE code snippet?! We need type checking! Input validation! OUTPUT SANITIZATION!

What Can Functions Return?

Primitive Values

Numbers, strings, booleans, null, undefined

return 42;
return "Hello";
return true;

Objects

Objects, arrays, dates, and other complex types

return { name: "Calculator" };
return [1, 2, 3];
return new Date();

Functions

Functions that can be called later (closures)

return function(x) { return x * 2; };
return () => { alert("Hello"); };

Special Returns

Multiple values via objects or arrays

return { sum: a+b, difference: a-b };
return [result, error];

Error Handling

Error objects or custom error information

return new Error("Invalid input");
return { success: false, error: "Division by zero" };

Nothing (void)

Functions can have no return statement

// No return statement
// Implicitly returns undefined
// Example of different return types

// Return a primitive value
function add(a, b) {
  return a + b; // Returns a number
}

// Return an object with multiple values
function mathOperations(a, b) {
  return {
    sum: a + b,
    difference: a - b,
    product: a * b,
    quotient: a / b
  };
}

// Return a function (closure)
function createMultiplier(factor) {
  return function(number) {
    return number * factor;
  };
}

// Using our functions with different return types
const sum = add(5, 3); // 8

const results = mathOperations(10, 5);
console.log(results.sum); // 15
console.log(results.product); // 50

const double = createMultiplier(2);
console.log(double(7)); // 14

const triple = createMultiplier(3);
console.log(triple(7)); // 21
AllyMcTweak
AllyMcTweak:

User understanding increases by 42% when we use relatable analogies. Functions with return values are indeed like vending machines that you can use anywhere in your code's "cafeteria," whereas functions without returns are just... decorative vending machines that light up but serve no purpose.

Try It Yourself: Improved Calculator

Function Return Value Calculator

Result will appear here
GarbageMcTweak
GarbageMcTweak:

This improved calculator properly uses return values. Each math function returns its result, which is then captured and used by the main calculate function. That's how functions should work - take input, process it, and return a useful result.

TrashyMcTweak
TrashyMcTweak:

Now that we've fixed the BASIC FUNCTIONALITY of actually RETURNING VALUES, let's talk about BEST PRACTICES for functions and returns! Because if you're going to return something, you might as well DO IT RIGHT! No point putting fancy tires on a car with no engine!

Return Value Best Practices

Always return a consistent data type from your functions when possible
Document what your function returns in comments (especially if it's complex)
Return early for error conditions or special cases
Don't rely on implicit returns (always use the return keyword)
Consider returning objects for multi-value returns instead of global variables
Keep functions pure - same inputs should always give same outputs
// Example of good return practices

/**
 * Divides two numbers and handles potential errors
 * @param {number} a - Numerator
 * @param {number} b - Denominator
 * @returns {Object} Object containing result or error information
 */
function safeDivide(a, b) {
  // Return early for error cases
  if (typeof a !== 'number' || typeof b !== 'number') {
    return {
      success: false,
      error: 'Both arguments must be numbers'
    };
  }
  
  // Handle division by zero
  if (b === 0) {
    return {
      success: false,
      error: 'Cannot divide by zero'
    };
  }
  
  // Return the successful result
  return {
    success: true,
    result: a / b
  };
}

// Using the function
const result1 = safeDivide(10, 2);
if (result1.success) {
  console.log('Result:', result1.result); // Result: 5
} else {
  console.log('Error:', result1.error);
}

const result2 = safeDivide(10, 0);
if (result2.success) {
  console.log('Result:', result2.result);
} else {
  console.log('Error:', result2.error); // Error: Cannot divide by zero
}
AshleyMcTweak
AshleyMcTweak:

And let's make sure each function has appropriate documentation. If the code ever goes to court, I need to be able to defend that the add() function was clearly intended to return a sum, not just log it to the console like some kind of mathematical diary entry.

Activity: Build Your Improved Calculator

Now it's your turn to practice creating functions with return values by building an improved calculator. You'll create math functions that properly return their results, and then use those results to build a fully functional calculator.

Steps to Follow:

1.

Create individual math functions for adding, subtracting, multiplying, and dividing. Each function should take two parameters and return the calculated result.

2.

Add proper error handling to your divide function to handle division by zero.

3.

Create input fields for the two numbers and a dropdown for selecting the operation.

4.

Implement a calculate function that:

  • Gets the input values
  • Converts them to numbers
  • Calls the appropriate math function
  • Displays the returned result

5.

Add extra features to your calculator (choose at least one):

  • Power function (x^y)
  • Square root function
  • Memory storage and recall
  • History of calculations

6.

Test your calculator with various inputs to ensure all functions are returning the correct values.

Pro Tips from the McTweak Team:

GarbageMcTweak says: "Create a single performOperation function that acts as a router to the individual math functions. This makes your code more modular."

AllyMcTweak says: "Don't forget to add proper validation for user inputs. Check for NaN values before performing calculations."

GrumpyMcTweak says: "ALWAYS CHECK FOR EDGE CASES! What happens with negative numbers? What about very large numbers that might cause overflow?"

AshleyMcTweak says: "Document your functions with JSDoc comments. Future you (and future legal defenders) will thank you."

GarbageMcTweak
GarbageMcTweak:

The calculator looks good now. The functions properly return their values, the code is modular and reusable, and we've added error handling. This is how JavaScript functions should be written - taking inputs, processing them, and returning useful outputs.

FattyMcTweak
FattyMcTweak:

I concur, this now meets my baseline standards. Though in my premium tier, we'd add extended precision arithmetic, scientific notation support, and perhaps a virtual assistant that compliments you on your mathematical prowess. But alas, this will have to do for the basic tier.

TrashyMcTweak
TrashyMcTweak:

It's FUNCTIONAL now, but is it BEAUTIFUL? NO! We could add animation transitions between numbers, particle effects for calculations, and maybe turn it into a FULL-BLOWN FINANCIAL ANALYSIS TOOL! But I guess this BASIC FUNCTIONALITY is a START!

AllyMcTweak
AllyMcTweak:

My analysis indicates that this calculator's proper use of return values has improved user comprehension metrics by 78.3%. The modular structure also facilitates future enhancements. I believe we have a satisfactory solution that meets our educational objectives.

GrumpyMcTweak
GrumpyMcTweak:

IT'S SECURE ENOUGH... FOR NOW. We've mitigated the immediate risks of function black holes, but we should really add input sanitization, output validation, and probably a secure connection to a trusted calculation verification service. But I GRUDGINGLY approve for initial deployment.

*EXCITED BARKING APPROACHING*
SnowzieMcTweak
SnowzieMcTweak:

WOOF! *sniffs code* WOOF WOOF! *tail wags approvingly at the proper return values*

CodyMcTweak
CodyMcTweak:

Wow, Snowzie really seems to like functions that return their values! I've never seen her tail wag so fast before!

SnowzieMcTweak
SnowzieMcTweak:

*jumps up to computer, paws at keyboard dramatically with mathematical precision*

CODE COMMITTED!
AshleyMcTweak
AshleyMcTweak:

And THAT is why we use proper return values in our functions. It doesn't just make the code better - it makes the fluffiest boss in the world happy too! I'll add this to my legal brief on "Why All Functions Should Return Meaningful Values: A Case Study in Elkhound Approval Metrics."

Return Value Key Takeaways

Remember:

Functions should return values, not just perform actions
Returned values can be used elsewhere in your code
You can return different types of data (numbers, strings, objects, functions)
Return multiple values by using arrays or objects
Add early returns for error handling and special cases
Document what your functions return for better maintainability
Functions that return values are easier to test and debug

In the next episode, we'll build on these concepts to create our final calculator project with all the features we've learned!

🌓