Skip to main content

Day 19 - Conditional data

TODO: extend this?

Introduction to Conditional Data

1. Introduction (10 minutes)

  • Overview:

    • Explain that sometimes data can come in multiple forms and that we need a way to represent alternatives within one type.
    • Introduce the idea of conditional data—data that can be one of several variants.
  • Example Context:

    • A payment system where a payment can be made by cash, credit card, or check.
  • Learning Goals:

    • Understand what conditional data is.
    • Learn how to define and create conditional data types in Pyret.
    • Use pattern matching with cases to distinguish among variants.
  • Do Now:

    • Ask: “Can you think of a situation where one type of data might have several different forms? (Examples: transportation mode, notification type, or feedback type)”
    • Briefly share responses.

2. Defining and Creating Conditional Data (20 minutes)

  • Defining a Conditional Data Type:

    • Define a new type called PaymentMethod with three variants:
      • cash (no extra data)
      • credit (with card-number and expiry)
      • check (with bank-account and check-number)
    • Pyret Code:
      # Define a PaymentMethod type with multiple variants
      data PaymentMethod:
      | cash
      | credit(card-number :: String, expiry :: String)
      | check(bank-account :: String, check-number :: Number)
      end
  • Creating Examples:

    • Create instances of PaymentMethod.
    • Examples:
      # Create different payment methods
      payment-1 = cash
      payment-2 = credit("1111-2222-3333-4444", "09/26")
      payment-3 = check("987654321", 55)

3. Programming with Conditional Data (20 minutes)

  • Taking Apart Variants with cases:

    • Write a function that returns a descriptive string for a payment method.
    • Example Function:
      fun display-payment(p :: PaymentMethod) -> String:
      cases (PaymentMethod) p:
      | cash => "Paid in cash"
      | credit(cn, exp) => "Paid by credit card ending with " + string-from-number(string-length(cn)) + " digits; expires " + exp
      | check(acc, num) => "Paid by check from account " + acc + " (check #" + string-from-number(num) + ")"
      end
      end
    • Note: In the credit branch, we use string-length merely to demonstrate field access (in practice, one might extract the last four digits).
  • Interactive Exercise:

    • Ask: “What is the output of display-payment(payment-3)?”
    • Expected output: "Paid by check from account 987654321 (check #55)"
    • Then ask: “What does display-payment(cash) return?”
  • Processing Fields in Variants:

    • Explain that in each cases branch, the program directory is extended with entries that match the names given (e.g., cn and exp in credit) to the fields in the corresponding case of the data.

4. Wrap-Up and Reflection (10 minutes)

  • Recap Key Points:
    • Conditional data allows us to represent values that can be one of several forms.
    • We define these types using data with multiple alternatives (each introduced with a |).
    • Pattern matching with cases distinguishes the different variants and binds their fields.