This step combines the earlier pieces into one complete rule. The policy is deliberately direct. An unopened item may be refunded through day 14. Build the habit of making both the decision and its boundary visible.
State the inputs before the code
The procedure receives two inputs.
daysis the number of days since delivery.opened?is#twhen the item has been opened, otherwise#f.
This lesson assumes the caller already supplied a valid non-negative day count and a boolean. Input validation is a separate decision boundary covered in Handling Errors Deterministically.
Write the rule
(define (refund-decision days opened?)
(if (and (<= days 14) (not opened?))
'(decision allow)
'(decision deny outside-refund-window)))
(refund-decision 9 #f)Result
(decision allow)Read the test from left to right. days must be at most 14, and opened?
must be false. and stops immediately if the first condition fails. if
evaluates only the selected quoted decision.
The denied label is intentionally conservative. In a real policy you may want separate reasons for “too late” and “already opened.” That is a product choice, not a hidden behavior of Lispex.
Test the boundary, not just the happy path
(list (refund-decision 14 #f)
(refund-decision 15 #f)
(refund-decision 9 #t))Result
((decision allow) (decision deny outside-refund-window) (decision deny outside-refund-window))| Case | Why it matters | Decision |
|---|---|---|
| day 14, unopened | the inclusive edge | allow |
| day 15, unopened | the first value outside the window | deny |
| day 9, opened | the second condition independently fails | deny |
If someone later changes <= to <, the first row changes. A boundary table
makes that change reviewable.
Keep the rule deterministic
The rule reads its arguments. The caller calculates days from its clock and
application state, then passes that value explicitly. Given the same two
Lispex values under the same documented runtime values, the rule follows the
same evaluation path and produces the same observable result.
Lispex makes the computation inspectable. Policy review owns fairness and legal requirements, the input pipeline owns real-world data provenance, and the surrounding application owns the external action.
Exercise
Change the rule so an unopened item is allowed through day 30. Add the two boundary calls that show the last accepted and first rejected values.
Show one answer
Change (<= days 14) to (<= days 30), then run the two boundary calls.
(list (refund-decision 30 #f)
(refund-decision 31 #f))The expected result is
((decision allow) (decision deny outside-refund-window)).
Ready for Step 6?
You can now read calls, define a procedure, preserve a list as data, choose a branch, and test a boundary. The next step is Where Your Program Runs.
You can also branch out from the course here.
- Deepen your language knowledge with Source Text and Reader.
- Keep the exact record of one run and check it with Running and Checking Decision Records.
- Turn exact source into a reversible visual artifact with Lispex Images.
- When you need to authenticate who signed a rule and re-check it against your own exact request, enter the advanced Lispex Vouch workflow.