Module 4: Decision Logic
Prerequisites: Modules 1–3
In this module, you'll learn how to encode constitutive rules - legal rules that determine facts, classifications, and eligibility.
Learning Objectives
By the end of this module, you will be able to:
- Distinguish between constitutive rules (decision logic) and regulative rules (obligations)
- Express eligibility determinations using DECIDE
- Define computations and definitions using MEANS
- Break down complex calculations with WHERE
- Write decision logic that reads like legal text
What is Decision Logic?
Constitutive vs Regulative Rules
Legal systems contain two types of rules:
Regulative rules (Modules 1 and 6) specify what parties must, may, or must not do:
- "The applicant must submit documentation within 30 days"
- "The landlord may terminate the lease if rent is unpaid"
- "The seller shall not disclose confidential information"
Constitutive rules (this module) determine facts, classifications, and eligibility:
- "An applicant is eligible if they are a citizen and over 18"
- "The tax owed is 20% of gross income minus deductions"
- "A person is a resident if they have lived here for 183 days or more"
In L4, we express constitutive rules as decision logic using functions.
Why Functional Purity Matters for Legal Rules
L4 follows the functional programming principle that every input needed to make a decision must be explicitly declared. This is a feature, not a bug.
Explicit Dependencies
When you write decision logic in L4, the GIVEN clause declares exactly what information is needed:
GIVEN `the applicant` IS A Person
`today` IS A DATE
GIVETH A BOOLEAN
DECIDE `the application is timely` IF ...
This signature tells you immediately: "To determine if an application is timely, I need to know who the applicant is and what today's date is."
No Hidden Dependencies
In natural language, legal rules often have implicit dependencies:
"The applicant is eligible if they are a resident."
Questions immediately arise:
- What makes someone a resident?
- How long must they have resided?
- Where must they reside?
In L4, you must make these dependencies explicit:
GIVEN `the applicant` IS A Person
`the jurisdiction` IS A STRING
GIVETH A BOOLEAN
DECIDE `the applicant is eligible` IF
`the applicant is a resident of the jurisdiction`
WHERE
`the applicant is a resident of the jurisdiction` MEANS
`the applicant`'s `country of residence` EQUALS `the jurisdiction`
AND `the applicant`'s `years of residence` >= 5
Notice how the helper decision is a resident of also declares its dependencies. You can't hide information - if a decision needs something, you must pass it explicitly.
"It Depends" - On What, Exactly?
This explicit dependency tracking has a huge benefit for legal reasoning:
When someone says "it depends" - L4 forces you to specify what "it" depends ON.
-- ❌ Unclear: What does eligibility depend on?
"The person is eligible"
-- ✅ Clear: Eligibility depends on these specific factors
GIVEN `the person` IS A Person
`the application date` IS A DATE
`the jurisdiction rules` IS A `Rule Set`
GIVETH A BOOLEAN
DECIDE `the person is eligible` IF ...
The function signature documents the complete set of factors that affect the decision. This makes legal rules:
- Auditable: You can trace exactly what information influenced a decision
- Testable: You know exactly what inputs to vary in your test scenarios
- Maintainable: When requirements change, you know what dependencies need updating
- Explainable: You can show stakeholders exactly what factors matter
Parameter Threading
If a sub-decision needs information, you must "thread" it through the caller:
GIVEN `the applicant` IS A Person
`today` IS A DATE -- We need this
GIVETH A BOOLEAN
DECIDE `qualifies for benefit` IF
`is eligible` `the applicant` `today` -- Pass it through!
AND ...
WHERE
GIVEN person IS A Person
`the current date` IS A DATE -- Sub-decision needs it too!
GIVETH A BOOLEAN
`is eligible` MEANS ...
This might seem verbose, but it's transparency, not bureaucracy. Every piece of information that influences the legal outcome is visible and traceable.
Working Examples
All examples in this module are in:
-- Module 4: Decision Logic - Complete Examples
-- All examples are validated and use natural language identifiers
IMPORT prelude
IMPORT daydate
-- =======================================
-- SECTION 1: Basic Eligibility Decisions
-- =======================================
-- Simple age-based eligibility
GIVEN `the person's age` IS A NUMBER
GIVETH A BOOLEAN
DECIDE `the person is an adult` IF `the person's age` >= 18
-- Voting eligibility
GIVEN `the person's age` IS A NUMBER
`is citizen` IS A BOOLEAN
GIVETH A BOOLEAN
DECIDE `the person is eligible to vote` IF
`the person's age` >= 18
AND `is citizen`
-- Senior discount qualification
GIVEN `the customer's age` IS A NUMBER
GIVETH A BOOLEAN
DECIDE `qualifies for senior discount` IF
`the customer's age` >= 65
-- Student status determination
GIVEN `the person's age` IS A NUMBER
`is enrolled` IS A BOOLEAN
GIVETH A BOOLEAN
DECIDE `the person is a student` IF
`the person's age` >= 16
AND `the person's age` <= 25
AND `is enrolled`
-- =======================================
-- SECTION 2: Using DECIDE IF vs DECIDE IS vs MEANS
-- =======================================
-- DECIDE IF: Best for yes/no questions with conditions
GIVEN `the income` IS A NUMBER
GIVETH A BOOLEAN
DECIDE `qualifies for exemption` IF `the income` < 10000
-- DECIDE IS: Best for classification or value assignment
GIVEN `the income` IS A NUMBER
GIVETH A STRING
DECIDE `the tax bracket` IS
BRANCH
IF `the income` < 10000 THEN "exempt"
IF `the income` < 50000 THEN "standard"
OTHERWISE "higher rate"
-- MEANS: Best for computations and definitions
GIVEN `the income` IS A NUMBER
GIVETH A STRING
`the income category` MEANS
BRANCH
IF `the income` < 20000 THEN "low"
IF `the income` < 80000 THEN "medium"
OTHERWISE "high"
-- =======================================
-- SECTION 3: Tax and Financial Calculations with WHERE
-- =======================================
-- Simple tax calculation
GIVEN `the gross income` IS A NUMBER
`the tax rate` IS A NUMBER
GIVETH A NUMBER
`the tax owed` MEANS
`the taxable income` * `the tax rate`
WHERE
`the standard deduction` MEANS 12000
`the taxable income` MEANS
IF `the gross income` > `the standard deduction`
THEN `the gross income` - `the standard deduction`
ELSE 0
-- Progressive tax with multiple brackets
GIVEN `the income` IS A NUMBER
GIVETH A NUMBER
`the income tax owed` MEANS
`tax on first bracket` + `tax on second bracket` + `tax on third bracket`
WHERE
`tax on first bracket` MEANS
`amount in first bracket` * 0.10
`tax on second bracket` MEANS
`amount in second bracket` * 0.20
`tax on third bracket` MEANS
`amount in third bracket` * 0.30
`amount in first bracket` MEANS
BRANCH
IF `the income` <= 10000 THEN `the income`
OTHERWISE 10000
`amount in second bracket` MEANS
BRANCH
IF `the income` <= 10000 THEN 0
IF `the income` <= 50000 THEN `the income` - 10000
OTHERWISE 40000
`amount in third bracket` MEANS
BRANCH
IF `the income` <= 50000 THEN 0
OTHERWISE `the income` - 50000
-- Net income calculation
GIVEN `the gross income` IS A NUMBER
`the expenses` IS A NUMBER
GIVETH A NUMBER
`the net income` MEANS
`the gross income` - `the total deductions`
WHERE
`the standard deduction` MEANS
IF `calculated deduction` >= 1000
THEN `calculated deduction`
ELSE 1000
`calculated deduction` MEANS `the gross income` * 0.10
`the total deductions` MEANS
`the standard deduction` + `the expenses`
-- =======================================
-- SECTION 4: Structured Entity Examples
-- =======================================
DECLARE Person HAS
name IS A STRING
age IS A NUMBER
citizenship IS A STRING
`annual income` IS A NUMBER
`criminal record` IS A BOOLEAN
-- Comprehensive benefit eligibility
GIVEN `the applicant` IS A Person
GIVETH A BOOLEAN
DECIDE `the applicant is eligible for benefit` IF
`the applicant is a qualifying resident`
AND `the applicant is of age`
AND `the applicant meets income threshold`
AND NOT `the applicant is disqualified`
WHERE
`the applicant is a qualifying resident` MEANS
`the applicant`'s citizenship = "citizen"
`the applicant is of age` MEANS
`the applicant`'s age >= 21
AND `the applicant`'s age < 65
`the applicant meets income threshold` MEANS
`the applicant`'s `annual income` < 30000
`the applicant is disqualified` MEANS
`the applicant`'s `criminal record`
-- Tax bracket determination with record
GIVEN `the taxpayer` IS A Person
GIVETH A STRING
DECIDE `the taxpayer's bracket` IS
BRANCH
IF `the taxpayer`'s `annual income` < 10000 THEN "exempt"
IF `the taxpayer`'s `annual income` < 50000 THEN "standard"
IF `the taxpayer`'s `annual income` < 100000 THEN "higher"
OTHERWISE "top rate"
-- =======================================
-- SECTION 5: Multi-Factor Decisions
-- =======================================
-- Loan approval decision
GIVEN `the income` IS A NUMBER
`the credit score` IS A NUMBER
`the loan amount` IS A NUMBER
GIVETH A BOOLEAN
DECIDE `the loan is approved` IF
`income requirement is met`
AND `credit score is sufficient`
AND `debt to income ratio is acceptable`
WHERE
`income requirement is met` MEANS
`the income` >= `the loan amount` * 0.3
`credit score is sufficient` MEANS
`the credit score` >= 650
`debt to income ratio is acceptable` MEANS
`the loan amount` <= `the income` * 4
-- Insurance premium calculation
GIVEN `the insured age` IS A NUMBER
`the coverage amount` IS A NUMBER
`is smoker` IS A BOOLEAN
GIVETH A NUMBER
`the annual premium` MEANS
`the base premium` * `the age factor` * `the smoking factor`
WHERE
`the base premium` MEANS
`the coverage amount` * 0.001
`the age factor` MEANS
BRANCH
IF `the insured age` < 30 THEN 1.0
IF `the insured age` < 50 THEN 1.5
OTHERWISE 2.0
`the smoking factor` MEANS
IF `is smoker` THEN 1.5 ELSE 1.0
-- =======================================
-- SECTION 6: Real-World Contract Scenarios
-- =======================================
-- Late payment penalty calculation
GIVEN `the principal amount` IS A NUMBER
`days overdue` IS A NUMBER
GIVETH A NUMBER
`the late payment penalty` MEANS
BRANCH
IF `days overdue` <= 0 THEN 0
IF `days overdue` <= 30 THEN `the principal amount` * 0.02
OTHERWISE `the principal amount` * 0.05
-- Lease renewal qualification
GIVEN `years as tenant` IS A NUMBER
`late payments` IS A NUMBER
`current rent` IS A NUMBER
`market rent` IS A NUMBER
GIVETH A BOOLEAN
DECIDE `qualifies for lease renewal` IF
`tenant is in good standing`
AND `rent is at market rate`
WHERE
`tenant is in good standing` MEANS
`years as tenant` >= 1
AND `late payments` = 0
`rent is at market rate` MEANS
`current rent` >= `market rent` * 0.9
-- =======================================
-- SECTION 7: Optional Values and Dates
-- =======================================
-- A contract with an optional termination date
DECLARE Contract HAS
`the effective date` IS A DATE
`the termination date` IS A MAYBE DATE
`the notice period in days` IS A NUMBER
-- A party who may or may not have given notice
DECLARE `Contract Party` HAS
`the party's name` IS A STRING
`notice was given on` IS A MAYBE DATE
-- Days between two dates, using serial day numbers
GIVEN `the first date` IS A DATE
`the second date` IS A DATE
GIVETH A NUMBER
`the days between` MEANS
DATE_SERIAL `the second date` - DATE_SERIAL `the first date`
-- Contract clause interpretation with MAYBE and dates
GIVEN `the contract` IS A Contract
`the party` IS A `Contract Party`
`today` IS A DATE
GIVETH A BOOLEAN
DECIDE `the party may terminate` IF
`the contract is active`
AND `the party has given sufficient notice`
WHERE
`the contract is active` MEANS
`today` >= `the contract`'s `the effective date`
AND CONSIDER `the contract`'s `the termination date`
WHEN NOTHING THEN TRUE
WHEN JUST `the end date` THEN `today` < `the end date`
`the party has given sufficient notice` MEANS
CONSIDER `the party`'s `notice was given on`
WHEN NOTHING THEN FALSE
WHEN JUST `the notice date` THEN
`the days between` `the notice date` `today` >= `the contract`'s `the notice period in days`
-- =======================================
-- SECTION 8: Test Data
-- =======================================
`test person eligible` MEANS
Person "Alice" 25 "citizen" 25000 FALSE
`test person ineligible age` MEANS
Person "Bob" 17 "citizen" 20000 FALSE
`test person ineligible citizenship` MEANS
Person "Carol" 30 "permanent resident" 20000 FALSE
`test person ineligible income` MEANS
Person "David" 30 "citizen" 50000 FALSE
`test person disqualified` MEANS
Person "Eve" 30 "citizen" 20000 TRUE
`the open-ended contract` MEANS Contract (Date 1 1 2024) NOTHING 30
`the party with notice` MEANS `Contract Party` "Acme Ltd" (JUST (Date 1 3 2024))
`the party without notice` MEANS `Contract Party` "Beta Ltd" NOTHING
-- =======================================
-- SECTION 9: Tests
-- =======================================
-- Basic eligibility tests
#EVAL `the person is an adult` 21
#EVAL `the person is an adult` 16
#EVAL `the person is eligible to vote` 25 TRUE
#EVAL `the person is eligible to vote` 16 TRUE
#EVAL `qualifies for senior discount` 70
#EVAL `qualifies for senior discount` 50
-- Tax calculation tests
#EVAL `the tax owed` 50000 0.20
#EVAL `the income tax owed` 75000
#EVAL `the net income` 100000 15000
-- Structured entity tests
#EVAL `the applicant is eligible for benefit` `test person eligible`
#EVAL `the applicant is eligible for benefit` `test person ineligible age`
#EVAL `the applicant is eligible for benefit` `test person ineligible citizenship`
#EVAL `the applicant is eligible for benefit` `test person ineligible income`
#EVAL `the applicant is eligible for benefit` `test person disqualified`
#EVAL `the taxpayer's bracket` `test person eligible`
-- Multi-factor decision tests
#EVAL `the loan is approved` 60000 700 200000
#EVAL `the loan is approved` 40000 700 200000
#EVAL `the annual premium` 35 100000 FALSE
#EVAL `the annual premium` 35 100000 TRUE
-- Contract scenario tests
#EVAL `the late payment penalty` 1000 15
#EVAL `the late payment penalty` 1000 45
#EVAL `qualifies for lease renewal` 2 0 1800 2000
#EVAL `qualifies for lease renewal` 2 3 1800 2000
-- Optional values and dates tests
#EVAL `the days between` (Date 1 3 2024) (Date 15 4 2024)
#EVAL `the party may terminate` `the open-ended contract` `the party with notice` (Date 15 4 2024)
#EVAL `the party may terminate` `the open-ended contract` `the party without notice` (Date 15 4 2024)
Basic Decisions with DECIDE
Eligibility Determinations
The most common legal decision: "Does X qualify?"
GIVEN `the applicant` IS A Person
GIVETH A BOOLEAN
DECIDE `the applicant is eligible for benefits` IF
`the applicant is a citizen`
AND `the applicant's age` >= 18
AND NOT `the applicant is disqualified`
Key points:
- Use DECIDE IF for yes/no questions
- Use backticks for natural language identifiers
- Conditions follow IF, connected by AND/OR/NOT
Classification Rules
"What category does X fall into?"
Use BRANCH for multi-way classification decisions:
GIVEN `the income` IS A NUMBER
GIVETH A STRING
DECIDE `the tax bracket` IS
BRANCH
IF `the income` < 10000 THEN "low"
IF `the income` < 50000 THEN "medium"
OTHERWISE "high"
Note: BRANCH is clearer than nested IF/THEN/ELSE for classification decisions. It avoids indentation problems and reads more like a legal test with multiple conditions. See Module 3: Control Flow for details.
DECIDE IS vs DECIDE IF
Use whichever reads more naturally:
-- These are equivalent:
DECIDE `the person is an adult` IF age >= 18
DECIDE `the person is an adult` IS age >= 18
-- Use IF when it reads like a legal condition:
DECIDE `qualifies for exemption` IF
`is a first-time buyer`
AND `purchase price` < 500000
-- Use IS with BRANCH for multi-way classification:
DECIDE `the applicable rate` IS
BRANCH
IF `customer type` = "premium" THEN 0.05
IF `customer type` = "standard" THEN 0.10
OTHERWISE 0.15
Computations with MEANS
Defining Calculations
Use MEANS to define computed values and formulas:
GIVEN `the gross income` IS A NUMBER
`the deductions` IS A NUMBER
GIVETH A NUMBER
`the taxable income` MEANS
`the gross income` - `the deductions`
Simple Tax Calculation
GIVEN `the taxable income` IS A NUMBER
GIVETH A NUMBER
`the tax owed` MEANS
`the taxable income` * `the tax rate`
DECIDE vs MEANS
Both define things - use whichever reads better:
| Use DECIDE when... | Use MEANS when... |
|---|---|
| Asking a yes/no question | Defining a value or computation |
| Determining classification/status | Stating what something equals |
| Condition reads naturally with IF | Definition reads naturally with = |
Examples:
-- ✅ Good: DECIDE for questions
DECIDE `the person is eligible` IF age >= 18
-- ✅ Good: MEANS for definitions
`the person's status` MEANS
IF age >= 18 THEN "adult" ELSE "minor"
-- Both work, but one reads better:
DECIDE `the person is an adult` IF age >= 18 -- More natural
`the person is an adult` MEANS age >= 18 -- Also valid
`the net income` MEANS `gross income` - `expenses` -- More natural
DECIDE `the net income` IS `gross income` - `expenses` -- Also valid
Breaking Down Complex Logic with WHERE
Local Helper Calculations
Legal formulas often involve intermediate calculations. Use WHERE to break them down:
GIVEN `the principal` IS A NUMBER
`the annual rate` IS A NUMBER
`the years` IS A NUMBER
GIVETH A NUMBER
`the compound interest` MEANS
`the principal` * EXPONENT `the growth factor` `the years`
WHERE
`the growth factor` MEANS 1 + `the annual rate`
(EXPONENT base power is L4's built-in exponentiation function.)
Benefits:
- Makes complex formulas readable
- Gives meaningful names to intermediate values
- Matches how legal documents explain calculations
Multiple WHERE Definitions
GIVEN `the loan amount` IS A NUMBER
`the annual rate` IS A NUMBER
`the term in months` IS A NUMBER
GIVETH A NUMBER
`the monthly payment` MEANS
`the loan amount` *
(`the monthly rate` * `the compound factor`) /
(`the compound factor` - 1)
WHERE
`the monthly rate` MEANS `the annual rate` / 12
`the compound factor` MEANS EXPONENT (1 + `the monthly rate`) `the term in months`
Realistic Legal Scenarios
Example 1: Benefit Eligibility
From
-- Module 4: Decision Logic - Complete Examples
-- All examples are validated and use natural language identifiers
IMPORT prelude
IMPORT daydate
-- =======================================
-- SECTION 1: Basic Eligibility Decisions
-- =======================================
-- Simple age-based eligibility
GIVEN `the person's age` IS A NUMBER
GIVETH A BOOLEAN
DECIDE `the person is an adult` IF `the person's age` >= 18
-- Voting eligibility
GIVEN `the person's age` IS A NUMBER
`is citizen` IS A BOOLEAN
GIVETH A BOOLEAN
DECIDE `the person is eligible to vote` IF
`the person's age` >= 18
AND `is citizen`
-- Senior discount qualification
GIVEN `the customer's age` IS A NUMBER
GIVETH A BOOLEAN
DECIDE `qualifies for senior discount` IF
`the customer's age` >= 65
-- Student status determination
GIVEN `the person's age` IS A NUMBER
`is enrolled` IS A BOOLEAN
GIVETH A BOOLEAN
DECIDE `the person is a student` IF
`the person's age` >= 16
AND `the person's age` <= 25
AND `is enrolled`
-- =======================================
-- SECTION 2: Using DECIDE IF vs DECIDE IS vs MEANS
-- =======================================
-- DECIDE IF: Best for yes/no questions with conditions
GIVEN `the income` IS A NUMBER
GIVETH A BOOLEAN
DECIDE `qualifies for exemption` IF `the income` < 10000
-- DECIDE IS: Best for classification or value assignment
GIVEN `the income` IS A NUMBER
GIVETH A STRING
DECIDE `the tax bracket` IS
BRANCH
IF `the income` < 10000 THEN "exempt"
IF `the income` < 50000 THEN "standard"
OTHERWISE "higher rate"
-- MEANS: Best for computations and definitions
GIVEN `the income` IS A NUMBER
GIVETH A STRING
`the income category` MEANS
BRANCH
IF `the income` < 20000 THEN "low"
IF `the income` < 80000 THEN "medium"
OTHERWISE "high"
-- =======================================
-- SECTION 3: Tax and Financial Calculations with WHERE
-- =======================================
-- Simple tax calculation
GIVEN `the gross income` IS A NUMBER
`the tax rate` IS A NUMBER
GIVETH A NUMBER
`the tax owed` MEANS
`the taxable income` * `the tax rate`
WHERE
`the standard deduction` MEANS 12000
`the taxable income` MEANS
IF `the gross income` > `the standard deduction`
THEN `the gross income` - `the standard deduction`
ELSE 0
-- Progressive tax with multiple brackets
GIVEN `the income` IS A NUMBER
GIVETH A NUMBER
`the income tax owed` MEANS
`tax on first bracket` + `tax on second bracket` + `tax on third bracket`
WHERE
`tax on first bracket` MEANS
`amount in first bracket` * 0.10
`tax on second bracket` MEANS
`amount in second bracket` * 0.20
`tax on third bracket` MEANS
`amount in third bracket` * 0.30
`amount in first bracket` MEANS
BRANCH
IF `the income` <= 10000 THEN `the income`
OTHERWISE 10000
`amount in second bracket` MEANS
BRANCH
IF `the income` <= 10000 THEN 0
IF `the income` <= 50000 THEN `the income` - 10000
OTHERWISE 40000
`amount in third bracket` MEANS
BRANCH
IF `the income` <= 50000 THEN 0
OTHERWISE `the income` - 50000
-- Net income calculation
GIVEN `the gross income` IS A NUMBER
`the expenses` IS A NUMBER
GIVETH A NUMBER
`the net income` MEANS
`the gross income` - `the total deductions`
WHERE
`the standard deduction` MEANS
IF `calculated deduction` >= 1000
THEN `calculated deduction`
ELSE 1000
`calculated deduction` MEANS `the gross income` * 0.10
`the total deductions` MEANS
`the standard deduction` + `the expenses`
-- =======================================
-- SECTION 4: Structured Entity Examples
-- =======================================
DECLARE Person HAS
name IS A STRING
age IS A NUMBER
citizenship IS A STRING
`annual income` IS A NUMBER
`criminal record` IS A BOOLEAN
-- Comprehensive benefit eligibility
GIVEN `the applicant` IS A Person
GIVETH A BOOLEAN
DECIDE `the applicant is eligible for benefit` IF
`the applicant is a qualifying resident`
AND `the applicant is of age`
AND `the applicant meets income threshold`
AND NOT `the applicant is disqualified`
WHERE
`the applicant is a qualifying resident` MEANS
`the applicant`'s citizenship = "citizen"
`the applicant is of age` MEANS
`the applicant`'s age >= 21
AND `the applicant`'s age < 65
`the applicant meets income threshold` MEANS
`the applicant`'s `annual income` < 30000
`the applicant is disqualified` MEANS
`the applicant`'s `criminal record`
-- Tax bracket determination with record
GIVEN `the taxpayer` IS A Person
GIVETH A STRING
DECIDE `the taxpayer's bracket` IS
BRANCH
IF `the taxpayer`'s `annual income` < 10000 THEN "exempt"
IF `the taxpayer`'s `annual income` < 50000 THEN "standard"
IF `the taxpayer`'s `annual income` < 100000 THEN "higher"
OTHERWISE "top rate"
-- =======================================
-- SECTION 5: Multi-Factor Decisions
-- =======================================
-- Loan approval decision
GIVEN `the income` IS A NUMBER
`the credit score` IS A NUMBER
`the loan amount` IS A NUMBER
GIVETH A BOOLEAN
DECIDE `the loan is approved` IF
`income requirement is met`
AND `credit score is sufficient`
AND `debt to income ratio is acceptable`
WHERE
`income requirement is met` MEANS
`the income` >= `the loan amount` * 0.3
`credit score is sufficient` MEANS
`the credit score` >= 650
`debt to income ratio is acceptable` MEANS
`the loan amount` <= `the income` * 4
-- Insurance premium calculation
GIVEN `the insured age` IS A NUMBER
`the coverage amount` IS A NUMBER
`is smoker` IS A BOOLEAN
GIVETH A NUMBER
`the annual premium` MEANS
`the base premium` * `the age factor` * `the smoking factor`
WHERE
`the base premium` MEANS
`the coverage amount` * 0.001
`the age factor` MEANS
BRANCH
IF `the insured age` < 30 THEN 1.0
IF `the insured age` < 50 THEN 1.5
OTHERWISE 2.0
`the smoking factor` MEANS
IF `is smoker` THEN 1.5 ELSE 1.0
-- =======================================
-- SECTION 6: Real-World Contract Scenarios
-- =======================================
-- Late payment penalty calculation
GIVEN `the principal amount` IS A NUMBER
`days overdue` IS A NUMBER
GIVETH A NUMBER
`the late payment penalty` MEANS
BRANCH
IF `days overdue` <= 0 THEN 0
IF `days overdue` <= 30 THEN `the principal amount` * 0.02
OTHERWISE `the principal amount` * 0.05
-- Lease renewal qualification
GIVEN `years as tenant` IS A NUMBER
`late payments` IS A NUMBER
`current rent` IS A NUMBER
`market rent` IS A NUMBER
GIVETH A BOOLEAN
DECIDE `qualifies for lease renewal` IF
`tenant is in good standing`
AND `rent is at market rate`
WHERE
`tenant is in good standing` MEANS
`years as tenant` >= 1
AND `late payments` = 0
`rent is at market rate` MEANS
`current rent` >= `market rent` * 0.9
-- =======================================
-- SECTION 7: Optional Values and Dates
-- =======================================
-- A contract with an optional termination date
DECLARE Contract HAS
`the effective date` IS A DATE
`the termination date` IS A MAYBE DATE
`the notice period in days` IS A NUMBER
-- A party who may or may not have given notice
DECLARE `Contract Party` HAS
`the party's name` IS A STRING
`notice was given on` IS A MAYBE DATE
-- Days between two dates, using serial day numbers
GIVEN `the first date` IS A DATE
`the second date` IS A DATE
GIVETH A NUMBER
`the days between` MEANS
DATE_SERIAL `the second date` - DATE_SERIAL `the first date`
-- Contract clause interpretation with MAYBE and dates
GIVEN `the contract` IS A Contract
`the party` IS A `Contract Party`
`today` IS A DATE
GIVETH A BOOLEAN
DECIDE `the party may terminate` IF
`the contract is active`
AND `the party has given sufficient notice`
WHERE
`the contract is active` MEANS
`today` >= `the contract`'s `the effective date`
AND CONSIDER `the contract`'s `the termination date`
WHEN NOTHING THEN TRUE
WHEN JUST `the end date` THEN `today` < `the end date`
`the party has given sufficient notice` MEANS
CONSIDER `the party`'s `notice was given on`
WHEN NOTHING THEN FALSE
WHEN JUST `the notice date` THEN
`the days between` `the notice date` `today` >= `the contract`'s `the notice period in days`
-- =======================================
-- SECTION 8: Test Data
-- =======================================
`test person eligible` MEANS
Person "Alice" 25 "citizen" 25000 FALSE
`test person ineligible age` MEANS
Person "Bob" 17 "citizen" 20000 FALSE
`test person ineligible citizenship` MEANS
Person "Carol" 30 "permanent resident" 20000 FALSE
`test person ineligible income` MEANS
Person "David" 30 "citizen" 50000 FALSE
`test person disqualified` MEANS
Person "Eve" 30 "citizen" 20000 TRUE
`the open-ended contract` MEANS Contract (Date 1 1 2024) NOTHING 30
`the party with notice` MEANS `Contract Party` "Acme Ltd" (JUST (Date 1 3 2024))
`the party without notice` MEANS `Contract Party` "Beta Ltd" NOTHING
-- =======================================
-- SECTION 9: Tests
-- =======================================
-- Basic eligibility tests
#EVAL `the person is an adult` 21
#EVAL `the person is an adult` 16
#EVAL `the person is eligible to vote` 25 TRUE
#EVAL `the person is eligible to vote` 16 TRUE
#EVAL `qualifies for senior discount` 70
#EVAL `qualifies for senior discount` 50
-- Tax calculation tests
#EVAL `the tax owed` 50000 0.20
#EVAL `the income tax owed` 75000
#EVAL `the net income` 100000 15000
-- Structured entity tests
#EVAL `the applicant is eligible for benefit` `test person eligible`
#EVAL `the applicant is eligible for benefit` `test person ineligible age`
#EVAL `the applicant is eligible for benefit` `test person ineligible citizenship`
#EVAL `the applicant is eligible for benefit` `test person ineligible income`
#EVAL `the applicant is eligible for benefit` `test person disqualified`
#EVAL `the taxpayer's bracket` `test person eligible`
-- Multi-factor decision tests
#EVAL `the loan is approved` 60000 700 200000
#EVAL `the loan is approved` 40000 700 200000
#EVAL `the annual premium` 35 100000 FALSE
#EVAL `the annual premium` 35 100000 TRUE
-- Contract scenario tests
#EVAL `the late payment penalty` 1000 15
#EVAL `the late payment penalty` 1000 45
#EVAL `qualifies for lease renewal` 2 0 1800 2000
#EVAL `qualifies for lease renewal` 2 3 1800 2000
-- Optional values and dates tests
#EVAL `the days between` (Date 1 3 2024) (Date 15 4 2024)
#EVAL `the party may terminate` `the open-ended contract` `the party with notice` (Date 15 4 2024)
#EVAL `the party may terminate` `the open-ended contract` `the party without notice` (Date 15 4 2024)
:
DECLARE Person HAS
name IS A STRING
age IS A NUMBER
citizenship IS A STRING
`annual income` IS A NUMBER
`criminal record` IS A BOOLEAN
GIVEN `the applicant` IS A Person
GIVETH A BOOLEAN
DECIDE `the applicant is eligible for benefit` IF
`the applicant is a qualifying resident`
AND `the applicant is of age`
AND `the applicant meets income threshold`
AND NOT `the applicant is disqualified`
WHERE
`the applicant is a qualifying resident` MEANS
`the applicant`'s citizenship = "citizen"
`the applicant is of age` MEANS
`the applicant`'s age >= 21
AND `the applicant`'s age < 65
`the applicant meets income threshold` MEANS
`the applicant`'s `annual income` < 30000
`the applicant is disqualified` MEANS
`the applicant`'s `criminal record`
Notice:
- Natural language identifiers with backticks
- WHERE breaks down the eligibility logic
- Each condition has a clear name
- Logic mirrors how legislation is written
Example 2: Progressive Tax Calculation
GIVEN `the income` IS A NUMBER
GIVETH A NUMBER
`the income tax owed` MEANS
`tax on first bracket` + `tax on second bracket` + `tax on third bracket`
WHERE
`tax on first bracket` MEANS
`amount in first bracket` * 0.10
`tax on second bracket` MEANS
`amount in second bracket` * 0.20
`tax on third bracket` MEANS
`amount in third bracket` * 0.30
`amount in first bracket` MEANS
BRANCH
IF `the income` <= 10000 THEN `the income`
OTHERWISE 10000
`amount in second bracket` MEANS
BRANCH
IF `the income` <= 10000 THEN 0
IF `the income` <= 50000 THEN `the income` - 10000
OTHERWISE 40000
`amount in third bracket` MEANS
BRANCH
IF `the income` <= 50000 THEN 0
OTHERWISE `the income` - 50000
Optional Values with MAYBE
Legal data is often incomplete: a contract may or may not have a termination date; notice may or may not have been given. L4 models "a value that might be absent" with the MAYBE type:
MAYBE DATEmeans "a date, or nothing"NOTHINGis the value when it's absentJUST valuewraps a value when it's present
You inspect a MAYBE with CONSIDER, handling both cases:
CONSIDER `the contract`'s `the termination date`
WHEN NOTHING THEN TRUE -- no termination date: contract is open-ended
WHEN JUST `the end date` THEN ... -- there is one: use `the end date`
The type system forces you to say what happens in both cases—no "null pointer" surprises, and no silently ignored edge case.
Working with Dates
L4 has a built-in DATE type. With IMPORT daydate, you can construct dates as Date day month year (for example, Date 15 4 2024) and compare them directly with <, >=, and so on.
To count the days between two dates, convert them to serial day numbers with DATE_SERIAL:
GIVEN `the first date` IS A DATE
`the second date` IS A DATE
GIVETH A NUMBER
`the days between` MEANS
DATE_SERIAL `the second date` - DATE_SERIAL `the first date`
Example 3: Contract Clause Interpretation
Putting MAYBE and dates together (from
-- Module 4: Decision Logic - Complete Examples
-- All examples are validated and use natural language identifiers
IMPORT prelude
IMPORT daydate
-- =======================================
-- SECTION 1: Basic Eligibility Decisions
-- =======================================
-- Simple age-based eligibility
GIVEN `the person's age` IS A NUMBER
GIVETH A BOOLEAN
DECIDE `the person is an adult` IF `the person's age` >= 18
-- Voting eligibility
GIVEN `the person's age` IS A NUMBER
`is citizen` IS A BOOLEAN
GIVETH A BOOLEAN
DECIDE `the person is eligible to vote` IF
`the person's age` >= 18
AND `is citizen`
-- Senior discount qualification
GIVEN `the customer's age` IS A NUMBER
GIVETH A BOOLEAN
DECIDE `qualifies for senior discount` IF
`the customer's age` >= 65
-- Student status determination
GIVEN `the person's age` IS A NUMBER
`is enrolled` IS A BOOLEAN
GIVETH A BOOLEAN
DECIDE `the person is a student` IF
`the person's age` >= 16
AND `the person's age` <= 25
AND `is enrolled`
-- =======================================
-- SECTION 2: Using DECIDE IF vs DECIDE IS vs MEANS
-- =======================================
-- DECIDE IF: Best for yes/no questions with conditions
GIVEN `the income` IS A NUMBER
GIVETH A BOOLEAN
DECIDE `qualifies for exemption` IF `the income` < 10000
-- DECIDE IS: Best for classification or value assignment
GIVEN `the income` IS A NUMBER
GIVETH A STRING
DECIDE `the tax bracket` IS
BRANCH
IF `the income` < 10000 THEN "exempt"
IF `the income` < 50000 THEN "standard"
OTHERWISE "higher rate"
-- MEANS: Best for computations and definitions
GIVEN `the income` IS A NUMBER
GIVETH A STRING
`the income category` MEANS
BRANCH
IF `the income` < 20000 THEN "low"
IF `the income` < 80000 THEN "medium"
OTHERWISE "high"
-- =======================================
-- SECTION 3: Tax and Financial Calculations with WHERE
-- =======================================
-- Simple tax calculation
GIVEN `the gross income` IS A NUMBER
`the tax rate` IS A NUMBER
GIVETH A NUMBER
`the tax owed` MEANS
`the taxable income` * `the tax rate`
WHERE
`the standard deduction` MEANS 12000
`the taxable income` MEANS
IF `the gross income` > `the standard deduction`
THEN `the gross income` - `the standard deduction`
ELSE 0
-- Progressive tax with multiple brackets
GIVEN `the income` IS A NUMBER
GIVETH A NUMBER
`the income tax owed` MEANS
`tax on first bracket` + `tax on second bracket` + `tax on third bracket`
WHERE
`tax on first bracket` MEANS
`amount in first bracket` * 0.10
`tax on second bracket` MEANS
`amount in second bracket` * 0.20
`tax on third bracket` MEANS
`amount in third bracket` * 0.30
`amount in first bracket` MEANS
BRANCH
IF `the income` <= 10000 THEN `the income`
OTHERWISE 10000
`amount in second bracket` MEANS
BRANCH
IF `the income` <= 10000 THEN 0
IF `the income` <= 50000 THEN `the income` - 10000
OTHERWISE 40000
`amount in third bracket` MEANS
BRANCH
IF `the income` <= 50000 THEN 0
OTHERWISE `the income` - 50000
-- Net income calculation
GIVEN `the gross income` IS A NUMBER
`the expenses` IS A NUMBER
GIVETH A NUMBER
`the net income` MEANS
`the gross income` - `the total deductions`
WHERE
`the standard deduction` MEANS
IF `calculated deduction` >= 1000
THEN `calculated deduction`
ELSE 1000
`calculated deduction` MEANS `the gross income` * 0.10
`the total deductions` MEANS
`the standard deduction` + `the expenses`
-- =======================================
-- SECTION 4: Structured Entity Examples
-- =======================================
DECLARE Person HAS
name IS A STRING
age IS A NUMBER
citizenship IS A STRING
`annual income` IS A NUMBER
`criminal record` IS A BOOLEAN
-- Comprehensive benefit eligibility
GIVEN `the applicant` IS A Person
GIVETH A BOOLEAN
DECIDE `the applicant is eligible for benefit` IF
`the applicant is a qualifying resident`
AND `the applicant is of age`
AND `the applicant meets income threshold`
AND NOT `the applicant is disqualified`
WHERE
`the applicant is a qualifying resident` MEANS
`the applicant`'s citizenship = "citizen"
`the applicant is of age` MEANS
`the applicant`'s age >= 21
AND `the applicant`'s age < 65
`the applicant meets income threshold` MEANS
`the applicant`'s `annual income` < 30000
`the applicant is disqualified` MEANS
`the applicant`'s `criminal record`
-- Tax bracket determination with record
GIVEN `the taxpayer` IS A Person
GIVETH A STRING
DECIDE `the taxpayer's bracket` IS
BRANCH
IF `the taxpayer`'s `annual income` < 10000 THEN "exempt"
IF `the taxpayer`'s `annual income` < 50000 THEN "standard"
IF `the taxpayer`'s `annual income` < 100000 THEN "higher"
OTHERWISE "top rate"
-- =======================================
-- SECTION 5: Multi-Factor Decisions
-- =======================================
-- Loan approval decision
GIVEN `the income` IS A NUMBER
`the credit score` IS A NUMBER
`the loan amount` IS A NUMBER
GIVETH A BOOLEAN
DECIDE `the loan is approved` IF
`income requirement is met`
AND `credit score is sufficient`
AND `debt to income ratio is acceptable`
WHERE
`income requirement is met` MEANS
`the income` >= `the loan amount` * 0.3
`credit score is sufficient` MEANS
`the credit score` >= 650
`debt to income ratio is acceptable` MEANS
`the loan amount` <= `the income` * 4
-- Insurance premium calculation
GIVEN `the insured age` IS A NUMBER
`the coverage amount` IS A NUMBER
`is smoker` IS A BOOLEAN
GIVETH A NUMBER
`the annual premium` MEANS
`the base premium` * `the age factor` * `the smoking factor`
WHERE
`the base premium` MEANS
`the coverage amount` * 0.001
`the age factor` MEANS
BRANCH
IF `the insured age` < 30 THEN 1.0
IF `the insured age` < 50 THEN 1.5
OTHERWISE 2.0
`the smoking factor` MEANS
IF `is smoker` THEN 1.5 ELSE 1.0
-- =======================================
-- SECTION 6: Real-World Contract Scenarios
-- =======================================
-- Late payment penalty calculation
GIVEN `the principal amount` IS A NUMBER
`days overdue` IS A NUMBER
GIVETH A NUMBER
`the late payment penalty` MEANS
BRANCH
IF `days overdue` <= 0 THEN 0
IF `days overdue` <= 30 THEN `the principal amount` * 0.02
OTHERWISE `the principal amount` * 0.05
-- Lease renewal qualification
GIVEN `years as tenant` IS A NUMBER
`late payments` IS A NUMBER
`current rent` IS A NUMBER
`market rent` IS A NUMBER
GIVETH A BOOLEAN
DECIDE `qualifies for lease renewal` IF
`tenant is in good standing`
AND `rent is at market rate`
WHERE
`tenant is in good standing` MEANS
`years as tenant` >= 1
AND `late payments` = 0
`rent is at market rate` MEANS
`current rent` >= `market rent` * 0.9
-- =======================================
-- SECTION 7: Optional Values and Dates
-- =======================================
-- A contract with an optional termination date
DECLARE Contract HAS
`the effective date` IS A DATE
`the termination date` IS A MAYBE DATE
`the notice period in days` IS A NUMBER
-- A party who may or may not have given notice
DECLARE `Contract Party` HAS
`the party's name` IS A STRING
`notice was given on` IS A MAYBE DATE
-- Days between two dates, using serial day numbers
GIVEN `the first date` IS A DATE
`the second date` IS A DATE
GIVETH A NUMBER
`the days between` MEANS
DATE_SERIAL `the second date` - DATE_SERIAL `the first date`
-- Contract clause interpretation with MAYBE and dates
GIVEN `the contract` IS A Contract
`the party` IS A `Contract Party`
`today` IS A DATE
GIVETH A BOOLEAN
DECIDE `the party may terminate` IF
`the contract is active`
AND `the party has given sufficient notice`
WHERE
`the contract is active` MEANS
`today` >= `the contract`'s `the effective date`
AND CONSIDER `the contract`'s `the termination date`
WHEN NOTHING THEN TRUE
WHEN JUST `the end date` THEN `today` < `the end date`
`the party has given sufficient notice` MEANS
CONSIDER `the party`'s `notice was given on`
WHEN NOTHING THEN FALSE
WHEN JUST `the notice date` THEN
`the days between` `the notice date` `today` >= `the contract`'s `the notice period in days`
-- =======================================
-- SECTION 8: Test Data
-- =======================================
`test person eligible` MEANS
Person "Alice" 25 "citizen" 25000 FALSE
`test person ineligible age` MEANS
Person "Bob" 17 "citizen" 20000 FALSE
`test person ineligible citizenship` MEANS
Person "Carol" 30 "permanent resident" 20000 FALSE
`test person ineligible income` MEANS
Person "David" 30 "citizen" 50000 FALSE
`test person disqualified` MEANS
Person "Eve" 30 "citizen" 20000 TRUE
`the open-ended contract` MEANS Contract (Date 1 1 2024) NOTHING 30
`the party with notice` MEANS `Contract Party` "Acme Ltd" (JUST (Date 1 3 2024))
`the party without notice` MEANS `Contract Party` "Beta Ltd" NOTHING
-- =======================================
-- SECTION 9: Tests
-- =======================================
-- Basic eligibility tests
#EVAL `the person is an adult` 21
#EVAL `the person is an adult` 16
#EVAL `the person is eligible to vote` 25 TRUE
#EVAL `the person is eligible to vote` 16 TRUE
#EVAL `qualifies for senior discount` 70
#EVAL `qualifies for senior discount` 50
-- Tax calculation tests
#EVAL `the tax owed` 50000 0.20
#EVAL `the income tax owed` 75000
#EVAL `the net income` 100000 15000
-- Structured entity tests
#EVAL `the applicant is eligible for benefit` `test person eligible`
#EVAL `the applicant is eligible for benefit` `test person ineligible age`
#EVAL `the applicant is eligible for benefit` `test person ineligible citizenship`
#EVAL `the applicant is eligible for benefit` `test person ineligible income`
#EVAL `the applicant is eligible for benefit` `test person disqualified`
#EVAL `the taxpayer's bracket` `test person eligible`
-- Multi-factor decision tests
#EVAL `the loan is approved` 60000 700 200000
#EVAL `the loan is approved` 40000 700 200000
#EVAL `the annual premium` 35 100000 FALSE
#EVAL `the annual premium` 35 100000 TRUE
-- Contract scenario tests
#EVAL `the late payment penalty` 1000 15
#EVAL `the late payment penalty` 1000 45
#EVAL `qualifies for lease renewal` 2 0 1800 2000
#EVAL `qualifies for lease renewal` 2 3 1800 2000
-- Optional values and dates tests
#EVAL `the days between` (Date 1 3 2024) (Date 15 4 2024)
#EVAL `the party may terminate` `the open-ended contract` `the party with notice` (Date 15 4 2024)
#EVAL `the party may terminate` `the open-ended contract` `the party without notice` (Date 15 4 2024)
):
DECLARE Contract HAS
`the effective date` IS A DATE
`the termination date` IS A MAYBE DATE
`the notice period in days` IS A NUMBER
DECLARE `Contract Party` HAS
`the party's name` IS A STRING
`notice was given on` IS A MAYBE DATE
GIVEN `the contract` IS A Contract
`the party` IS A `Contract Party`
`today` IS A DATE
GIVETH A BOOLEAN
DECIDE `the party may terminate` IF
`the contract is active`
AND `the party has given sufficient notice`
WHERE
`the contract is active` MEANS
`today` >= `the contract`'s `the effective date`
AND CONSIDER `the contract`'s `the termination date`
WHEN NOTHING THEN TRUE
WHEN JUST `the end date` THEN `today` < `the end date`
`the party has given sufficient notice` MEANS
CONSIDER `the party`'s `notice was given on`
WHEN NOTHING THEN FALSE
WHEN JUST `the notice date` THEN
`the days between` `the notice date` `today` >= `the contract`'s `the notice period in days`
Try it with the test data from the examples file:
`the open-ended contract` MEANS Contract (Date 1 1 2024) NOTHING 30
`the party with notice` MEANS `Contract Party` "Acme Ltd" (JUST (Date 1 3 2024))
#EVAL `the party may terminate` `the open-ended contract` `the party with notice` (Date 15 4 2024)
-- Result: TRUE
Function Signatures
Every decision or computation needs a type signature that declares:
- Inputs (GIVEN): What information is needed
- Output (GIVETH): What type of result is produced
Common Patterns
Boolean decisions (yes/no questions):
GIVEN `the person` IS A Person
GIVETH A BOOLEAN
DECIDE `the person is eligible` IF ...
Classification (categorizing into types):
GIVEN `the entity` IS AN Entity
GIVETH A STRING
DECIDE `the entity type` IS ...
Computation (calculating a value):
GIVEN `the income` IS A NUMBER
GIVETH A NUMBER
`the tax owed` MEANS ...
Multiple inputs:
GIVEN `the applicant` IS A Person
`the application date` IS A DATE
`today` IS A DATE
GIVETH A BOOLEAN
DECIDE `the application is timely` IF ...
Exercises
Exercise 1: Simple Eligibility
Write a decision that determines if a person qualifies for a senior discount (age 65 or older):
GIVEN `the person's age` IS A NUMBER
GIVETH A BOOLEAN
DECIDE `qualifies for senior discount` IF
-- Your code here
Solution
GIVEN `the person's age` IS A NUMBER
GIVETH A BOOLEAN
DECIDE `qualifies for senior discount` IF
`the person's age` >= 65
#EVAL `qualifies for senior discount` 70
#EVAL `qualifies for senior discount` 50
Exercise 2: Multi-Condition Eligibility
A person qualifies for a student loan if they:
- Are between 18 and 35 years old
- Are enrolled in an accredited institution
- Have no prior loan defaults
Write the decision logic.
Solution
GIVEN `the applicant's age` IS A NUMBER
`the applicant is enrolled in an accredited institution` IS A BOOLEAN
`the applicant has prior loan defaults` IS A BOOLEAN
GIVETH A BOOLEAN
DECIDE `the applicant qualifies for a student loan` IF
`the applicant is of eligible age`
AND `the applicant is enrolled in an accredited institution`
AND NOT `the applicant has prior loan defaults`
WHERE
`the applicant is of eligible age` MEANS
`the applicant's age` >= 18
AND `the applicant's age` <= 35
#EVAL `the applicant qualifies for a student loan` 25 TRUE FALSE
#EVAL `the applicant qualifies for a student loan` 40 TRUE FALSE
#EVAL `the applicant qualifies for a student loan` 25 TRUE TRUE
Exercise 3: Tax Bracket Classification
Write a decision that classifies income into tax brackets:
- Income < $10,000: "exempt"
- Income $10,000-$50,000: "standard"
- Income > $50,000: "higher rate"
Solution
GIVEN `the income` IS A NUMBER
GIVETH A STRING
DECIDE `the tax bracket` IS
BRANCH
IF `the income` < 10000 THEN "exempt"
IF `the income` <= 50000 THEN "standard"
OTHERWISE "higher rate"
#EVAL `the tax bracket` 5000
#EVAL `the tax bracket` 30000
#EVAL `the tax bracket` 80000
Exercise 4: Calculation with WHERE
Write a computation for net income that:
- Starts with gross income
- Subtracts standard deduction (calculated as 10% of gross, minimum $1000)
- Subtracts itemized deductions
Use WHERE to break down the calculation clearly.
Solution
GIVEN `the gross income` IS A NUMBER
`the itemized deductions` IS A NUMBER
GIVETH A NUMBER
`the net income` MEANS
`the gross income` - `the standard deduction` - `the itemized deductions`
WHERE
`the standard deduction` MEANS
IF `the calculated deduction` >= 1000
THEN `the calculated deduction`
ELSE 1000
`the calculated deduction` MEANS
`the gross income` * 0.10
#EVAL `the net income` 100000 5000
#EVAL `the net income` 8000 500
Common Mistakes
1. Missing Type Signature
-- ❌ Wrong: No GIVETH
GIVEN `the person's age` IS A NUMBER
DECIDE `is adult` IF `the person's age` >= 18
-- ✅ Right: Include GIVETH
GIVEN `the person's age` IS A NUMBER
GIVETH A BOOLEAN
DECIDE `is adult` IF `the person's age` >= 18
2. Using Programmer Names
-- ❌ Wrong: Programmer style
GIVEN p IS A Person
GIVETH A BOOLEAN
isEligible p MEANS p.age >= 18 && !p.disqualified
-- ✅ Right: Natural language
GIVEN `the person` IS A Person
GIVETH A BOOLEAN
DECIDE `the person is eligible` IF
`the person`'s age >= 18
AND NOT `the person`'s disqualified
3. Complex Logic Without WHERE
-- ❌ Wrong: Everything inline, hard to read
`the result` MEANS
(x * 0.1 + y * 0.2) / EXPONENT (1 + r) n
-- ✅ Right: Break down with WHERE
`the result` MEANS
`the combined amount` / `the discount factor`
WHERE
`the combined amount` MEANS x * 0.1 + y * 0.2
`the discount factor` MEANS EXPONENT (1 + r) n
4. Wrong DECIDE vs MEANS Choice
-- ❌ Awkward: MEANS for a yes/no question
`is eligible` MEANS age >= 18 AND income < 50000
-- ✅ Better: DECIDE IF for questions
DECIDE `is eligible` IF
age >= 18
AND income < 50000
-- ❌ Awkward: DECIDE for a simple definition
DECIDE `the net amount` IS gross - deductions
-- ✅ Better: MEANS for definitions
`the net amount` MEANS gross - deductions
5. Nested IF/THEN/ELSE Instead of BRANCH
-- ❌ Fragile: Nested IF/THEN/ELSE (indentation-sensitive)
`the category` MEANS
IF score >= 90 THEN "excellent"
ELSE IF score >= 70 THEN "good"
ELSE IF score >= 50 THEN "pass"
ELSE "fail"
-- ✅ Better: BRANCH (clear, flat structure)
`the category` MEANS
BRANCH
IF score >= 90 THEN "excellent"
IF score >= 70 THEN "good"
IF score >= 50 THEN "pass"
OTHERWISE "fail"
Summary
| Concept | Use for | Syntax |
|---|---|---|
| DECIDE IF | Yes/no questions, eligibility | DECIDE name IF condition |
| DECIDE IS | Classification, value assignment | DECIDE name IS expression |
| MEANS | Definitions, computations | name MEANS expression |
| BRANCH | Multi-way classification | BRANCH IF cond1 THEN val1 ... OTHERWISE |
| WHERE | Breaking down complex logic | expression WHERE helpers |
| GIVEN ... GIVETH ... | Type signature (always required!) | GIVEN inputs GIVETH OutputType name... |
Key principles:
- Write code that reads like legal text
- Use backticks liberally for natural language
- Use WHERE to make complex logic transparent
- Choose DECIDE vs MEANS based on readability
What's Next?
In Module 5: Functions, you'll go deeper into the machinery behind decision logic: reusable functions, recursion, and higher-order functions like map and filter that let you apply decisions across whole lists of cases.
After that, Module 6: Regulative Rules shows how to combine constitutive rules (decision logic) with regulative rules (obligations, permissions, prohibitions) to model complete legal workflows.