This final course step turns the earlier pieces into one complete rule. The policy is deliberately small: an unopened item may be refunded through day 14. The important habit is to make both the decision and its boundary visible.
State the inputs before the code
The procedure receives:
days: the number of days since delivery; andopened?:#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 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 reviewable.
Keep the rule deterministic
The rule reads only its arguments. It does not fetch a clock, call a server, or
read mutable application state. The caller decides how to calculate days and
passes that value explicitly. Given the same two Lispex values under the same
documented runtime limits, the rule follows the same evaluation path and
produces the same observable result.
This does not prove that the refund policy is fair, legally sufficient, or based on accurate real-world data. Lispex makes the computation inspectable; the surrounding application remains responsible for input provenance and the external action.
Exercise
Change the rule so an unopened item is allowed through day 30. Add the two boundary calls that show the first accepted and first rejected values.
Show one answer
Change (<= days 14) to (<= days 30), then test:
(list (refund-decision 30 #f)
(refund-decision 31 #f))
The expected result is
((decision allow) (decision deny outside-refund-window)).
Course complete
You can now read calls, define a procedure, preserve a list as data, choose a branch, and test a boundary. Choose what to do next:
- deepen language knowledge with Source Text and Reader;
- design larger rules with Writing Decision Rules;
- turn exact source into a reversible visual artifact with Lispex Images; or
- when authenticity and a consumer-pinned current check matter, enter the advanced Lispex Vouch workflow.