Introduction to Pattern Matching
Introduction to Pattern Matching
Fundamentals of Patterns
Introduction
In previous lessons, to deal with conditions, we created if...else expressions, and their variants. Those operations ask the compiler to consider various situations, one after another. Another, sometimes better, option is to ask the compiler to directly locate the specific situation you want to deal with. This approach is referred to as pattern matching.
Practical Learning: Matching a String
printfn "==========================================" printfn " - Amazing DeltaX - State Income Tax -" printfn "==========================================" let mutable stateName = "" let mutable taxRate = 0.00 printfn "Enter the information for tax preparation" printfn "States" printfn " AK - Alaska" printfn " AR - Arkansas" printfn " CO - Colorado" printfn " FL - Florida" printfn " GA - Georgia" printfn " IL - Illinois" printfn " IN - Indiana" printfn " KY - Kentucky" printfn " MA - Massachusetts" printfn " MI - Michigan" printfn " MO - Missouri" printfn " MS - Mississippi" printfn " NV - Nevada" printfn " NH - New Hampshire" printfn " NC - North Carolina" printfn " PA - Pennsylvania" printfn " SD - South Dakota" printfn " TN - Tennessee" printfn " TX - Texas" printfn " UT - Utah" printfn " WA - Washington" printfn " WY - Wyoming" printf "Enter State Abbreviation: " let abbr : string = stdin.ReadLine() printfn "--------------------------------------------" printf "Gross Salary: " let grossSalary = float(stdin.ReadLine()) let taxAmount = grossSalary * taxRate / 100.00 let netPay = grossSalary - taxAmount printfn "============================================" printfn " - Amazing DeltaX - State Income Tax -" printfn "--------------------------------------------" printfn $"Gross Salary: {grossSalary:f}" printfn $"State: {stateName}" printfn "Tax Rate: %0.2f%c" taxRate '%' printfn "--------------------------------------------" printfn $"Tax Amount: {taxAmount:f}" printfn $"Net Pay: {netPay:f}" printfn "============================================"
========================================== - Amazing DeltaX - State Income Tax - ========================================== Enter the information for tax preparation States AK - Alaska AR - Arkansas CO - Colorado FL - Florida GA - Georgia IL - Illinois IN - Indiana KY - Kentucky MA - Massachusetts MI - Michigan MO - Missouri MS - Mississippi NV - Nevada NH - New Hampshire NC - North Carolina PA - Pennsylvania SD - South Dakota TN - Tennessee TX - Texas UT - Utah WA - Washington WY - Wyoming Enter State Abbreviation: FL -------------------------------------------- Gross Salary: 1558.85 ============================================ - Amazing DeltaX - State Income Tax - -------------------------------------------- Gross Salary: 1558.85 State: Tax Rate: 0.00% -------------------------------------------- Tax Amount: 0.00 Net Pay: 1558.85 ============================================ Press any key to close this window . . .
========================================== - Amazing DeltaX - State Income Tax - ========================================== Enter the information for tax preparation States AK - Alaska AR - Arkansas CO - Colorado FL - Florida GA - Georgia IL - Illinois IN - Indiana KY - Kentucky MA - Massachusetts MI - Michigan MO - Missouri MS - Mississippi NV - Nevada NH - New Hampshire NC - North Carolina PA - Pennsylvania SD - South Dakota TN - Tennessee TX - Texas UT - Utah WA - Washington WY - Wyoming Enter State Abbreviation: KY -------------------------------------------- Gross Salary: 1558.85 ============================================ - Amazing DeltaX - State Income Tax - -------------------------------------------- Gross Salary: 1558.85 State: Tax Rate: 0.00% -------------------------------------------- Tax Amount: 0.00 Net Pay: 1558.85 ============================================ Press any key to close this window . . .
If you have an expression that can produce many outcomes but only one of them must be considered, you can validate it using the match keyword. The formula to follow is:
match expression with | condition-1 -> result-1 | condition-2 -> result-2 | . . . | condition-x -> result-x
The match and the with keywords are required. The expression can be the name of a variable whose value will be tested. The results of testing the expression will each be validated in the next lines. Each line starts with | (a pipe) and a value from the expression. This produces a result from the condition X, which is followed by the -> operator. Each condition has a body. The body is introduced by the -> operator. On the right side of that -> operator, define what you want process for that particular condition.
Matching an Integer
One of the types of values you can try to match is an integer. In most cases, a match statement behaves like an if conditional statement. Consider the following code that uses an if conditional statement:
let number = 248
let mutable conclusion = "That number is not right."
if number = 248 then
conclusion <- "That number is correct."
printfn "%s" conclusion
printfn "========================================"
This would produce:
That number is correct. ======================================== Press any key to close this window . . .
The same code can be written with a match statement as follows:
let number = 248;
let conclusion = "That number is not right."
match number with
| 248 ->
conclusion = "That number is correct."
printfn "%s" conclusion
printfn "========================================"
We know that an if conditional statement can use one or more else options. Here is an example:
let mutable incomeTax = 0.00
printfn "Payroll Evaluation"
printfn "============================================"
printfn "Enter the information to evaluate taxes"
printfn "Frequency by which the payroll is processed:"
printfn "1 - Weekly"
printfn "2 - Biweekly"
printfn "3 - Semimonthly"
printfn "4 - Monthly"
printf "Enter Payroll Frequency: "
let frequency = int(stdin.ReadLine())
printfn "--------------------------------------------"
printf "Gross Salary: "
let grossSalary = float(stdin.ReadLine())
if frequency = 1 then
incomeTax <- 271.08 + (grossSalary * 24.00 / 100.00)
elif frequency = 2 then
incomeTax <- 541.82 + (grossSalary * 24.00 / 100.00)
elif frequency = 3 then
incomeTax <- 587.12 + (grossSalary * 24.00 / 100.00)
elif frequency = 4 then
incomeTax <- 1174.12 + (grossSalary * 24.00 / 100.00)
printfn "============================================"
printfn "Payroll Evaluation"
printfn "--------------------------------------------"
printfn "Gross Salary: %18.02f" grossSalary
printfn "Income Tax: %18.02f" incomeTax
printfn "============================================"
Here is an example of running the program:
Payroll Evaluation ============================================ Enter the information to evaluate taxes Frequency by which the payroll is processed: 1 - Weekly 2 - Biweekly 3 - Semimonthly 4 - Monthly Enter Payroll Frequency: 3 -------------------------------------------- Gross Salary: 1552.86 ============================================ Payroll Evaluation -------------------------------------------- Gross Salary: 1552.86 Income Tax: 959.81 ============================================ Press any key to close this window . . .
In the same way, each section of a matching pattern can use a natural number. Here is an example:
let mutable incomeTax = 0.00
printfn "Payroll Evaluation"
printfn "============================================"
printfn "Enter the information to evaluate taxes"
printfn "Frequency by which the payroll is processed:"
printfn "1 - Weekly"
printfn "2 - Biweekly"
printfn "3 - Semimonthly"
printfn "4 - Monthly"
printf "Enter Payroll Frequency: "
let frequency = int(stdin.ReadLine())
printfn "--------------------------------------------"
printf "Gross Salary: "
let grossSalary = float(stdin.ReadLine())
match frequency with
| 1 ->
incomeTax <- 271.08 + (grossSalary * 24.00 / 100.00)
| 2 ->
incomeTax <- 541.82 + (grossSalary * 24.00 / 100.00)
| 3 ->
incomeTax <- 587.12 + (grossSalary * 24.00 / 100.00)
| 4 ->
incomeTax <- 1174.12 + (grossSalary * 24.00 / 100.00)
printfn "============================================"
printfn "Payroll Evaluation"
printfn "--------------------------------------------"
printfn "Gross Salary: %18.02f" grossSalary
printfn "Income Tax: %18.02f" incomeTax
printfn "============================================"
Matching a String
Besides a natural number, a matching pattern can compare its expression to strings. In this case, each section uses a string or an expression that evaluates to a string.
Practical Learning: Matching by Some Strings
printfn "=========================================="
printfn " - Amazing DeltaX - State Income Tax -"
printfn "=========================================="
let mutable stateName : string = ""
let mutable taxRate = 0.00
printfn "Enter the information for tax preparation"
printfn "States"
printfn " AK - Alaska"
printfn " AR - Arkansas"
printfn " CO - Colorado"
printfn " FL - Florida"
printfn " GA - Georgia"
printfn " IL - Illinois"
printfn " IN - Indiana"
printfn " KY - Kentucky"
printfn " MA - Massachusetts"
printfn " MI - Michigan"
printfn " MO - Missouri"
printfn " MS - Mississippi"
printfn " NV - Nevada"
printfn " NH - New Hampshire"
printfn " NC - North Carolina"
printfn " PA - Pennsylvania"
printfn " SD - South Dakota"
printfn " TN - Tennessee"
printfn " TX - Texas"
printfn " UT - Utah"
printfn " WA - Washington"
printfn " WY - Wyoming"
printf "Enter State Abbreviation: "
let abbr : string = stdin.ReadLine()
printfn "--------------------------------------------"
printf "Gross Salary: "
let grossSalary = float(stdin.ReadLine())
match abbr with
| "CO" ->
taxRate <- 4.63
stateName <- "Colorado"
| "FL" ->
taxRate <- 0.00
stateName <- "Florida"
| "IL" ->
taxRate <- 4.95
stateName <- "Illinois"
| "IN" ->
taxRate <- 3.23
stateName <- "Indiana"
| "KY" ->
taxRate <- 5.00
stateName <- "Kentucky"
| "MA" ->
taxRate <- 5.00
stateName <- "Massachusetts"
| "MI" ->
taxRate <- 4.25
stateName <- "Michigan"
| "NC" ->
taxRate <- 5.25
stateName <- "North Carolina"
| "NH" ->
taxRate <- 5.00
stateName <- "New Hampshire"
| "NV" ->
taxRate <- 0.00
stateName <- "Nevada"
| "PA" ->
taxRate <- 3.07
stateName <- "Pennsylvania"
| "TN" ->
taxRate <- 1.00
stateName <- "Tennessee"
| "TX" ->
taxRate <- 0.00
stateName <- "Texas"
| "UT" ->
taxRate <- 4.95
stateName <- "Utah"
| "WA" ->
taxRate <- 0.00
stateName <- "Washington"
| "WY" ->
taxRate <- 0.00
stateName <- "Wyoming"
let taxAmount = grossSalary * taxRate / 100.00
let netPay = grossSalary - taxAmount;
printfn "============================================"
printfn " - Amazing DeltaX - State Income Tax -"
printfn "--------------------------------------------"
printfn $"Gross Salary: {grossSalary:f}"
printfn $"State: {stateName}"
printfn "Tax Rate: %0.2f%c" taxRate '%'
printfn "--------------------------------------------"
printfn $"Tax Amount: {taxAmount:f}"
printfn $"Net Pay: {netPay:f}"
========================================== - Amazing DeltaX - State Income Tax - ========================================== Enter the information for tax preparation States AK - Alaska AR - Arkansas CO - Colorado FL - Florida GA - Georgia IL - Illinois IN - Indiana KY - Kentucky MA - Massachusetts MI - Michigan MO - Missouri MS - Mississippi NV - Nevada NH - New Hampshire NC - North Carolina PA - Pennsylvania SD - South Dakota TN - Tennessee TX - Texas UT - Utah WA - Washington WY - Wyoming Enter State Abbreviation: CO -------------------------------------------- Gross Salary: 1558.85 ============================================ - Amazing DeltaX - State Income Tax - -------------------------------------------- Gross Salary: 1558.85 State: Colorado Tax Rate: 4.63% -------------------------------------------- Tax Amount: 72.17 Net Pay: 1486.68 ============================================ Press any key to close this window . . .
========================================== - Amazing DeltaX - State Income Tax - ========================================== Enter the information for tax preparation States AK - Alaska AR - Arkansas CO - Colorado FL - Florida GA - Georgia IL - Illinois IN - Indiana KY - Kentucky MA - Massachusetts MI - Michigan MO - Missouri MS - Mississippi NV - Nevada NH - New Hampshire NC - North Carolina PA - Pennsylvania SD - South Dakota TN - Tennessee TX - Texas UT - Utah WA - Washington WY - Wyoming Enter State Abbreviation: KY -------------------------------------------- Gross Salary: 1558.85 ============================================ - Amazing DeltaX - State Income Tax - -------------------------------------------- Gross Salary: 1558.85 State: Kentucky Tax Rate: 5.00% -------------------------------------------- Tax Amount: 77.94 Net Pay: 1480.91 ============================================ Press any key to close this window . . .
Matching an Enumeration
A matching pattern can use an enumeration. In this case, each section can use a member of an enumeration.
Practical Learning: Matching an Enumeration
type CompoundFrequency = | Daily | Weekly | Monthly | Quaterly | Semiannually | Annually let mutable frequency = 0.00 let mutable interestRate = 0.00 let periods = 42 let mutable compounding = CompoundFrequency.Monthly printfn "Simple Interest" printfn "--------------------------------------------------------" printfn "Provide the values that will be used to evaluate a loan." printf "Principal: " let principal = float(stdin.ReadLine()) printfn "--------------------------------------------------------" printfn "Compound Frequencies" printfn "1. Weekly" printfn "2. Monthly" printfn "3. Quaterly" printfn "4. Semiannually" printfn "5. Annually" printf "Type your choice: " let choice = stdin.ReadLine() if choice = "1" then compounding <- CompoundFrequency.Weekly elif choice = "2" then compounding <- CompoundFrequency.Monthly elif choice = "3" then compounding <- CompoundFrequency.Quaterly elif choice = "4" then compounding <- CompoundFrequency.Semiannually elif choice = "5" then compounding <- CompoundFrequency.Annually else compounding <- CompoundFrequency.Daily match compounding with | CompoundFrequency.Daily -> interestRate <- 8.95 frequency <- 365.00 | CompoundFrequency.Weekly -> interestRate <- 52.00 frequency <- 11.95 | CompoundFrequency.Monthly -> interestRate <- 12.00 frequency <- 14.75 | CompoundFrequency.Quaterly -> interestRate <- 4.00 frequency <- 18.85 | CompoundFrequency.Semiannually -> interestRate <- 2.00 frequency <- 22.55 | CompoundFrequency.Annually -> interestRate <- 1.00 frequency <- 26.25 let iRate = interestRate / float 100 let per = float periods / frequency let interestAmount = principal * iRate * per printfn "=========================================================" printfn "Simple Interest" printfn "--------------------------------------------------------" printfn "Principal: %0.02f" principal printfn "Interest Rate: %0.02f %c" interestRate '%' printfn "Periods: %i months" periods printfn "-------------------------------" printfn "Interest Amount: %0.02f" interestAmount printfn "Future Value: %0.02f" (principal + interestAmount) printfn "========================================================="
Simple Interest -------------------------------------------------------- Provide the values that will be used to evaluate a loan. Principal: 7248.95 -------------------------------------------------------- Compound Frequencies 1. Weekly 2. Monthly 3. Quaterly 4. Semiannually 5. Annually Type your choice: 2 ========================================================= Simple Interest -------------------------------------------------------- Principal: 7248.95 Interest Rate: 14.75% Periods: 42 months ------------------------------- Interest Amount: 3742.27 Future Value: 10991.22 ========================================================= Press any key to close this window . . .
Conditionally Matching
Matching a Boolean Variable
Besides natural numbers and strings, a matching pattern can process logical expressions. To make it happen, you can first declare a Boolean variable. You can also use an expression that holds a Boolean value. Pass the Boolean value or expression to match. For each section of the matching pattern, use one of the possible Boolean outcomes. At a minimum, if you are using a Boolean variable, one section can use true and the other can process the false outcome. Here is an example:
let mutable conclusion = "" let emplTitle = "Manager" let emplIsManager = emplTitle = "Manager" match emplIsManager with | true -> conclusion <- "The employee is a manager." | false -> conclusion <- "The staff member is a regular employee." printfn "%s" conclusion printfn "========================================"
This would produce:
The employee is a manager. ======================================== Press any key to close this window . . .
Matching a Boolean Expression
In the previous example, we included a Boolean variable to match. Otherwise, if you have a Boolean expression, you can pass it directly to match. Here is an example:
let mutable conclusion = ""
let emplTitle = "Manager"
match emplTitle = "Manager" with
| true ->
conclusion <- "The employee is a manager."
| false ->
conclusion <- "The staff member is a regular employee."
printfn "%s" conclusion
printfn "========================================"
In the same way, since every conditional operation produces a Boolean value, it can be used for a matching pattern. Here is an example:
let timeWorked = 30.00
// If TimeWorked >= 40
match timeWorked >= 40.00 with
| true ->
printfn "The employee works full-time."
| false ->
printfn "The staff member worked part-time."
printfn "========================================"
As a result, you will see that in many cases, an if conditional statement such such as this:
printfn "FUN DEPARTMENT STORE"
printfn "======================================================="
printfn "Payroll Preparation"
printfn "-------------------------------------------------------"
printfn "Enter the following pieces of information"
printfn "-------------------------------------------------------"
printfn "Employee Information"
printfn "-------------------------------------------------------"
printf "First Name: "
let firstName : string = stdin.ReadLine()
printf "Last Name: "
let lastName : string = stdin.ReadLine()
printf "Hourly Salary: "
let hSalary = float(stdin.ReadLine());
printfn "-------------------------------------------------------"
printfn "Time worked"
printfn "-------------------------------------------------------"
printf "Monday: "
let mon = float(stdin.ReadLine())
printf "Tuesday: "
let tue = float(stdin.ReadLine())
printf "Wednesday: "
let wed = float(stdin.ReadLine())
printf "Thursday: "
let thu = float(stdin.ReadLine())
printf "Friday: "
let fri = float(stdin.ReadLine())
let timeWorked = mon + tue + wed + thu + fri
let mutable regTime = 0.00
let mutable overtime = 0.00
let mutable regPay = 0.00
let mutable overPay = 0.00
if timeWorked <= 40.00 then
regTime <- timeWorked
regPay <- hSalary * timeWorked
overtime <- 0.00
overPay <- 0.00
else
regTime <- 40.00
regPay <- hSalary * 40.00
overtime <- timeWorked - 40.00
overPay <- hSalary * 1.50 * overtime
let netPay = regPay + overPay
printfn "+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+"
printfn "FUN DEPARTMENT STORE"
printfn "======================================================="
printfn "Payroll Evaluation"
printfn "======================================================="
printfn "Employee Information"
printfn "-------------------------------------------------------"
printfn $"Full Name: {firstName} {lastName}"
printfn $"Hourly Salary: {hSalary:f}"
printfn "======================================================="
printfn "Time Worked Summary"
printfn "--------+---------+-----------+----------+-------------"
printfn " Monday | Tuesday | Wednesday | Thursday | Friday"
printfn "--------+---------+-----------+----------+-------------"
printfn $" {mon:f} | {tue:f} | {wed:f} | {thu:f} | {fri:f}"
printfn "========+=========+===========+==========+============="
printfn " Pay Summary"
printfn "-------------------------------------------------------"
printfn " Time Pay"
printfn "-------------------------------------------------------"
printfn " Regular: %10.2f%10.2f" regTime regPay
printfn "-------------------------------------------------------"
printfn " overtime:%10.2f%10.2f" overtime overPay
printfn "======================================================="
printfn " Net Pay: %20.2f" netPay
printfn "======================================================="
can also be implemented as a matching pattern like this:
printfn "FUN DEPARTMENT STORE" printfn "=======================================================" printfn "Payroll Preparation" printfn "-------------------------------------------------------" . . . match timeWorked <= 40.00 with | true -> regTime <- timeWorked regPay <- hSalary * timeWorked overtime <- 0.00 overPay <- 0.00 | false -> regTime <- 40.00 regPay <- hSalary * 40.00 overtime <- timeWorked - 40.00 overPay <- hSalary * 1.50 * overtime let netPay = regPay + overPay . . .
Here is an example of running the program:
FUN DEPARTMENT STORE ======================================================= Payroll Preparation ------------------------------------------------------- Enter the following pieces of information ------------------------------------------------------- Employee Information ------------------------------------------------------- First Name: Jacob Last Name: Melman Hourly Salary: 22.84 ------------------------------------------------------- Time worked ------------------------------------------------------- Monday: 8 Tuesday: 7.50 Wednesday: 9.50 Thursday: 10.50 Friday: 8 +=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+ FUN DEPARTMENT STORE ======================================================= Payroll Evaluation ======================================================= Employee Information ------------------------------------------------------- Full Name: Jacob Melman Hourly Salary: 22.84 ======================================================= Time Worked Summary --------+---------+-----------+----------+------------- Monday | Tuesday | Wednesday | Thursday | Friday --------+---------+-----------+----------+------------- 8.00 | 7.50 | 9.50 | 10.50 | 8.00 ========+=========+===========+==========+============= Pay Summary ------------------------------------------------------- Time Pay ------------------------------------------------------- Regular: 40.00 913.60 ------------------------------------------------------- overtime: 3.50 119.91 ======================================================= Net Pay: 1033.51 ======================================================= Press any key to close this window . . .
Practical Learning: Matching Unknown Outcomes
========================================== - Amazing DeltaX - State Income Tax - ========================================== Enter the information for tax preparation States AK - Alaska AR - Arkansas CO - Colorado FL - Florida GA - Georgia IL - Illinois IN - Indiana KY - Kentucky MA - Massachusetts MI - Michigan MO - Missouri MS - Mississippi NV - Nevada NH - New Hampshire NC - North Carolina PA - Pennsylvania SD - South Dakota TN - Tennessee TX - Texas UT - Utah WA - Washington WY - Wyoming Enter State Abbreviation: USA -------------------------------------------- Gross Salary: 1000 Unhandled exception. Microsoft.FSharp.Core.MatchFailureException: The match cases were incomplete at . . .\Program.fs:line 102 Press any key to close this window . . .
Introduction
When you create a match statement, you provide the values that must each be processed. Unfortunately, in most cases, at least one value is left out. As a result, you must tell the compiler what to do for (the) value(s) that cannot be processed. To assist you with this, the F# language provides an operator as the underscore _. In some cases, you can have a situation where you want to deal with only the default case. In that case, the formula to follow is:
match expression with | _ ->statement(s)
In most cases, you will deaul with known values and at lease one unknown value. For that scenario, the formula to follow is:
match expression with
| condition-1 -> result-1
| condition-2 -> result-2
| . . .
| condition-x -> result-x
| _ ->statement(s)
Processing a Default Value
Consider a program with the following code:
let number = 1
let mutable conclusion = "That number is not right."
if number = 1 then conclusion <- "That number is correct."
printfn "%s" conclusion
printfn "===================================="
This would produce:
That number is correct. ==================================== Press any key to close this window . . .
As mentioned earlier, you can create a matching pattern that has only a default section. That situation is the same as having a simple if condition. As a result, the above code can be converted into a matching pattern with a default section as follows:
let number = 1
let mutable conclusion = "That number is not right."
match number with | _ -> conclusion <- "That number is correct."
printfn "%s" conclusion
printfn "========================================"
Processing Unknown Values
Consider the following program:
let mutable startingSalary = 16_000
let mutable employmentStatus = ""
printfn "Employment Status:"
printfn "f - Full-Time"
printfn "p - Part-Time"
printfn "c - Contractor"
printfn "--------------------------"
printf "Enter Employment Status: ";
let status = char(stdin.ReadLine())
match status with
| 'f' ->
startingSalary <- 40_000
employmentStatus <- "Full-Time"
| 'p' ->
employmentStatus <- "Part-Time"
startingSalary <- 32_000
| 'c' ->
startingSalary <- 24_000
employmentStatus <- "Contractor"
printfn "Employee Record"
printfn "----------------------------------"
printfn "Employment Status: %s" employmentStatus
printfn "Starting Yearly Salary: %i" startingSalary
printfn "=================================="
Notice that this code produces a warning. Here is an example of running the program:
Employment Status: f - Full-Time p - Part-Time c - Contractor -------------------------- Enter Employment Status: p Employee Record ---------------------------------- Employment Status: Part-Time Starting Yearly Salary: 32000 ================================== Press any key to close this window . . .
Here is another example of running the program:
Employment Status: f - Full-Time p - Part-Time c - Contractor -------------------------- Enter Employment Status: c Employee Record ---------------------------------- Employment Status: Contractor Starting Yearly Salary: 24000 ================================== Press any key to close this window . . .
Here is another example of running the program:
Employment Status: f - Full-Time p - Part-Time c - Contractor -------------------------- Enter Employment Status: f Employee Record ---------------------------------- Employment Status: Full-Time Starting Yearly Salary: 40000 ================================== Press any key to close this window . . .
Here is one more example of running the program:
Employment Status: f - Full-Time p - Part-Time c - Contractor -------------------------- Enter Employment Status: u Unhandled exception. Microsoft.FSharp.Core.MatchFailureException: The match cases were incomplete at . . .\Program.fs:line 21 Press any key to close this window . . .
Notice that, this time, when we provide a value that is not expected, the program produces an error. As seen so far, in most cases, your matching statements will deal with different values. When there is at least one value that you did not consider, you should include the underscore section. Here is an example:
let mutable startingSalary = 16_000
let mutable employmentStatus = ""
printfn "Employment Status:"
printfn "f - Full-Time"
printfn "p - Part-Time"
printfn "c - Contractor"
printfn "----------------------------------"
printf "Enter Employment Status: ";
let status = char(stdin.ReadLine())
match status with
| 'f' ->
startingSalary <- 40_000
employmentStatus <- "Full-Time"
| 'p' ->
employmentStatus <- "Part-Time"
startingSalary <- 32_000
| 'c' ->
startingSalary <- 24_000
employmentStatus <- "Contractor"
| _ ->
startingSalary <- 22_000
employmentStatus <- "Unknown"
printfn "Employee Record"
printfn "----------------------------------"
printfn "Employment Status: %s" employmentStatus
printfn "Starting Yearly Salary: %i" startingSalary
printfn "=================================="
Here is an example of running the program:
Employment Status: f - Full-Time p - Part-Time c - Contractor ---------------------------------- Enter Employment Status: a Employee Record ---------------------------------- Employment Status: Unknown Starting Yearly Salary: 22000 ================================== Press any key to close this window . . .
If you create an underscore section in your matching pattern, that underscore section should always be the last (unlike C# where the default section can appear anywhere, such as in the beginning of the cases or between any two cases).
Ignoring the Default Outcome
Although you should always anticipate the default case, sometimes, you can ignore it or deal with it in other section of your program. Still, in mose cases, if you don't create an underscore case, you program will present a warning, which could result in an error if the user provides a value that doesn't one of those the program is prepared for. To let you create a default case that doesn't present functionality for it, the F# language provides the empty parentheses operator. To use it, for the body of the last case, simply type () and don't provide any other code for it. Here is an example:
let mutable startingSalary = 16_000
let mutable employmentStatus = "Unknown"
printfn "Employment Status:"
printfn "f - Full-Time"
printfn "p - Part-Time"
printfn "c - Contractor"
printfn "----------------------------------"
printf "Enter Employment Status: ";
let status = char(stdin.ReadLine())
match status with
| 'f' ->
startingSalary <- 40_000
employmentStatus <- "Full-Time"
| 'p' ->
employmentStatus <- "Part-Time"
startingSalary <- 32_000
| 'c' ->
startingSalary <- 24_000
employmentStatus <- "Contractor"
| _ -> ()
printfn "Employee Record"
printfn "----------------------------------"
printfn "Employment Status: %s" employmentStatus
printfn "Starting Yearly Salary: %i" startingSalary
printfn "=================================="
Here is an example of running the program:
Employment Status: f - Full-Time p - Part-Time c - Contractor ---------------------------------- Enter Employment Status: q Employee Record ---------------------------------- Employment Status: Unknown Starting Yearly Salary: 16000 ================================== Press any key to close this window . . .
Practical Learning: Addressing the Default Outcome
printfn "=========================================="
printfn " - Amazing DeltaX - State Income Tax -"
printfn "=========================================="
let mutable stateName = ""
let mutable taxRate = 0.00
printfn "Enter the information for tax preparation"
printfn "States"
printfn " AK - Alaska"
printfn " AR - Arkansas"
printfn " CO - Colorado"
printfn " FL - Florida"
printfn " GA - Georgia"
printfn " IL - Illinois"
printfn " IN - Indiana"
printfn " KY - Kentucky"
printfn " MA - Massachusetts"
printfn " MI - Michigan"
printfn " MO - Missouri"
printfn " MS - Mississippi"
printfn " NV - Nevada"
printfn " NH - New Hampshire"
printfn " NC - North Carolina"
printfn " PA - Pennsylvania"
printfn " SD - South Dakota"
printfn " TN - Tennessee"
printfn " TX - Texas"
printfn " UT - Utah"
printfn " WA - Washington"
printfn " WY - Wyoming"
printf "Enter State Abbreviation: "
let abbr : string = stdin.ReadLine()
printfn "--------------------------------------------"
printf "Gross Salary: "
let grossSalary = float(stdin.ReadLine())
match abbr with
| "CO" ->
taxRate <- 4.63
stateName <- "Colorado"
| "FL" ->
taxRate <- 0.00
stateName <- "Florida"
| "IL" ->
taxRate <- 4.95
stateName <- "Illinois"
| "IN" ->
taxRate <- 3.23
stateName <- "Indiana"
| "KY" ->
taxRate <- 5.00
stateName <- "Kentucky"
| "MA" ->
taxRate <- 5.00
stateName <- "Massachusetts"
| "MI" ->
taxRate <- 4.25
stateName <- "Michigan"
| "NC" ->
taxRate <- 5.25
stateName <- "North Carolina"
| "NH" ->
taxRate <- 5.00
stateName <- "New Hampshire"
| "NV" ->
taxRate <- 0.00
stateName <- "Nevada"
| "PA" ->
taxRate <- 3.07
stateName <- "Pennsylvania"
| "TN" ->
taxRate <- 1.00
stateName <- "Tennessee"
| "TX" ->
taxRate <- 0.00
stateName <- "Texas"
| "UT" ->
taxRate <- 4.95
stateName <- "Utah"
| "WA" ->
taxRate <- 0.00
stateName <- "Washington"
| "WY" ->
taxRate <- 0.00
stateName <- "Wyoming"
| _ -> ()
let taxAmount = grossSalary * taxRate / 100.00
let netPay = grossSalary - taxAmount
printfn "============================================"
printfn " - Amazing DeltaX - State Income Tax -"
printfn "--------------------------------------------"
printfn $"Gross Salary: {grossSalary:f}"
printfn $"State: {stateName}"
printfn "Tax Rate: %0.2f%c" taxRate '%'
printfn "--------------------------------------------"
printfn $"Tax Amount: {taxAmount:f}"
printfn $"Net Pay: {netPay:f}"
printfn "============================================"
========================================== - Amazing DeltaX - State Income Tax - ========================================== Enter the information for tax preparation States AK - Alaska AR - Arkansas CO - Colorado FL - Florida GA - Georgia IL - Illinois IN - Indiana KY - Kentucky MA - Massachusetts MI - Michigan MO - Missouri MS - Mississippi NV - Nevada NH - New Hampshire NC - North Carolina PA - Pennsylvania SD - South Dakota TN - Tennessee TX - Texas UT - Utah WA - Washington WY - Wyoming Enter State Abbreviation: USA -------------------------------------------- Gross Salary: 100.00 ============================================ - Amazing DeltaX - State Income Tax - -------------------------------------------- Gross Salary: 100.00 State: Tax Rate: 0.00% -------------------------------------------- Tax Amount: 0.00 Net Pay: 100.00 ============================================ Press any key to close this window . . .
Nesting Pattern Matching
You can create a pattern matching operation inside another. This is referred to as nesting. Here is an example:
// -- Annual Compound Interest - Money Borrowed let principal = 2500 let amountCategory = if principal < 1000 then 1 elif principal < 2000 then 2 elif principal < 5000 then 3 else 4 let mutable periods = 0 let mutable typeOfPeriods = 3 //"Daily" // "Monthly" "Quarterly" "Annually" let mutable compounded = "Quarterly" let numberOfYears = 6 let mutable interestRate = 0.00 match typeOfPeriods with | 1 -> compounded <- "Daily" periods <- 360 match amountCategory with | 1 -> interestRate <- 2.25 / 100.00 | 2 -> interestRate <- 3.45 / 100.00 | 3 -> interestRate <- 4.35 / 100.00 | _ -> interestRate <- 6.05 / 100.00 | 2 -> compounded <- "Monthly" periods <- 12 match amountCategory with | 1 -> interestRate <- 2.35 / 100.00 | 2 -> interestRate <- 2.95 / 100.00 | 3 -> interestRate <- 4.05 / 100.00 | _ -> interestRate <- 6.85 / 100.00 | 3 -> compounded <- "Quarterly" periods <- 4 match amountCategory with | 1 -> interestRate <- 2.25 / 100.00 | 2 -> interestRate <- 4.30 / 100.00 | 3 -> interestRate <- 5.55 / 100.00 | _ -> interestRate <- 7.35 / 100.00 | 4 -> compounded <- "Annually" periods <- 1 match amountCategory with | 1 -> interestRate <- 3.15 / 100.00 | 2 -> interestRate <- 4.35 / 100.00 | 3 -> interestRate <- 6.25 / 100.00 | _ -> interestRate <- 8.05 / 100.00 | _ -> periods <- 0 interestRate <- 0.00 // Calculation let compoundInYears = float periods * float numberOfYears let n1 = float 1 + (interestRate / float periods) let futureValue = float principal * (n1 ** compoundInYears) printfn "Deposit Summary" printfn "--------------------------" printfn "Amount Deposited: %d" principal printfn "Interest Rate: %0.02f%c" (interestRate * 100.00) '%' printfn "Periods: %i years" periods printfn "Compounded: %s" compounded printfn "--------------------------" printfn "Future Value: %0.02f" futureValue printfn "=========================="
This would produce:
Deposit Summary -------------------------- Amount Deposited: 2500 Interest Rate: 5.55% Periods: 4 years Compounded: Quarterly -------------------------- Future Value: 3479.89 ========================== Press any key to close this window . . .
Practical Learning: Ending the Lesson
|
|||
Previous | Copyright © 2009-2024, FunctionX | Friday 06 October 2023 | Next |
|