Keyboard shortcuts

Press ← or → to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

Activity 7: Hand-coding challenge

In this activity you will hand-write two small functions that work out what someone pays at a check-out counter, given the sticker price, the sales tax, and whether they have a membership card worth 10% off.

Part 1 - Hand-coding on your own

You need to write your own sheet up but can work side-by-side.

You are writing two functions. main is written for you at the bottom, and it only ever calls print_receipt.

print_receipt takes the sticker price, the tax rate, and whether the customer has a membership card. It prints the receipt below, and returns nothing.

The rule: print_receipt does no arithmetic. No multiplying, no subtracting. Every number it prints either arrived as a parameter or came back from the other function.

The other function does all of the arithmetic. You decide what to call it, what it takes, and what it hands back.

A function can only return one value, but that value can be a tuple, so it can carry several numbers back at once.

Design it so that print_receipt has everything it needs.

Example, for print_receipt(100.00, 0.08, true):

Original:  $100.00
Tax:       $8.00
Discount:  $10.80
Total:     $97.20

Start with the function that does the arithmetic, since print_receipt has to call it.

#![allow(unused)]
fn main() {
fn ____________(______________________) -> ____________ {
    // Your implementation here
















    
}
}

Now print_receipt, which calls the function you just designed. Does it need a return type?

#![allow(unused)]
fn main() {
fn print_receipt(______________________) ________ {
    // Your implementation here

















}
}

main is written for you. You do not need to change it, but just notice what it calls.

fn main() {
    print_receipt(100.00, 0.08, true);
    print_receipt(100.00, 0.08, false);
    print_receipt(0.02, 0.08, true);
}

Things to think about:

  • Did your function hand back anything print_receipt did not actually need?
  • Does it matter in what order the tax and discount are applied?
  • What would happen if the sticker price were very low (like 2 cents), or negative?

Part 2 - Swap for feedback

If you worked with someone, get feedback from a different person!

When I announce, you'll swap papers with a neighbor and look at their solution. Take a minute to give them feedback including:

  • Any highlights of what they did well
  • Any bugs you notice
  • Any style feedback

At the end, I will collect papers and pick a couple (anonymized) to show on the screen for discussion.

Solutions

One possible solution:

#![allow(unused)]
fn main() {
fn calculate_totals(price: f64, tax_rate: f64, has_card: bool) -> (f64, f64, f64) {
    let tax = price * tax_rate;
    let subtotal = price + tax;
    let discount = if has_card { subtotal * 0.1 } else { 0.0 };
    let final_price = subtotal - discount;
    (tax, discount, final_price)
}

fn print_receipt(price: f64, tax_rate: f64, has_card: bool) {
    let (tax, discount, final_price) = calculate_totals(price, tax_rate, has_card);

    println!("Original:  ${:.2}", price);
    println!("Tax:       ${:.2}", tax);
    println!("Discount:  ${:.2}", discount);
    println!("Total:     ${:.2}", final_price);
}
}

print_receipt(100.00, 0.08, true) prints $100.00, $8.00, $10.80, $97.20.

This is one good answer, not the only one.

Alternatives:

  • Returns the original price as a fourth value, (price, tax, discount, total). Okay but redundant
  • Returns only the final price. Then print_receipt has to work out the tax and the discount (technically violates design requirements)
  • Returns a subtotal as well. Harmless, but nothing on the receipt prints it

Notes:

  • The tuple has to be destructured, let (tax, discount, final_price) = ..., or reached into with .0, .1 and .2
  • print_receipt has no return type, so it returns ()
  • A has_card of false gives a discount of 0.0, not a missing value. The tuple is the same shape either way
  • Tax then discount and discount then tax both give the same total (but different tax and discount values)
  • The 2 cent case is interesting: tax is 0.0016 and discount 0.00216, so both print as 0.02. The receipt looks like it does not add up, because {:.2} is hiding the complete values
  • A negative price runs but might not give sensible answers