Currency Library
Currency handling with ISO 4217 currency codes. Stores amounts as integer minor units (cents) to avoid floating-point errors. Import with IMPORT currency (also imports jurisdiction).
Status: Prototype (version 1.0.0). API may change.
Location
jl4-core/libraries/currency.l4
Supported Currencies
USD, EUR, GBP, JPY, CHF, CAD, AUD, CNY, HKD, SGD, INR, BRL, MXN, SEK, NZD, KRW
Each currency provides constants, e.g. `US Dollar code` ("USD"), `US Dollar numeric` (840), `US Dollar decimals` (2), and `US Dollar country`. JPY and KRW have 0 decimal places; all others 2.
Construction and Formatting
| Function | Signature | Description |
|---|---|---|
Money minorUnits currencyCode |
NUMBER → STRING → EITHER STRING STRING |
Format minor units as an amount string, e.g. Money 12345 "USD" → RIGHT "123.45 USD". LEFT for unknown currencies or non-integer minor units. |
decimal places for currency currencyCode |
STRING → EITHER STRING NUMBER |
Minor-unit decimal places for a currency code |
power of 10 exponent |
NUMBER → NUMBER |
10^n for n in 0-3 (defaults to 100 otherwise) |
The zero-padding and decimal-point formatting are performed by helpers (formatAmount, formatNumber, padLeft) local to Money's WHERE clause — they are not separately importable.
Amount Conversion
| Function | Signature | Description |
|---|---|---|
major to minor units majorUnits currencyCode |
NUMBER → STRING → EITHER STRING NUMBER |
Dollars to cents (floors to an integer) |
minor to major units minorUnits currencyCode |
NUMBER → STRING → EITHER STRING NUMBER |
Cents to dollars |
Arithmetic Operations
All arithmetic works on minor-unit amounts and validates the currency code first (LEFT for unknown currencies).
| Function | Signature | Description |
|---|---|---|
add money amount1 amount2 currencyCode |
NUMBER → NUMBER → STRING → EITHER STRING NUMBER |
Sum of two amounts |
subtract money amount1 amount2 currencyCode |
NUMBER → NUMBER → STRING → EITHER STRING NUMBER |
Difference of two amounts |
multiply money amount factor currencyCode |
NUMBER → NUMBER → STRING → EITHER STRING NUMBER |
Amount × factor, floored to whole minor units |
divide money amount divisor currencyCode |
NUMBER → NUMBER → STRING → EITHER STRING NUMBER |
Amount ÷ divisor, floored; LEFT on division by zero |
Comparison Operations
Plain minor-unit comparisons (both amounts assumed to be in the same currency):
| Function | Signature | Description |
|---|---|---|
money equal amount1 amount2 |
NUMBER → NUMBER → BOOLEAN |
amount1 = amount2 |
money greater than amount1 amount2 |
NUMBER → NUMBER → BOOLEAN |
amount1 > amount2 |
money less than amount1 amount2 |
NUMBER → NUMBER → BOOLEAN |
amount1 < amount2 |
money at least amount1 amount2 |
NUMBER → NUMBER → BOOLEAN |
amount1 >= amount2 |
money at most amount1 amount2 |
NUMBER → NUMBER → BOOLEAN |
amount1 <= amount2 |
Validation Functions
| Function | Signature | Description |
|---|---|---|
is valid currency code code |
STRING → BOOLEAN |
Exactly 3 characters, all uppercase (format only) |
is non-negative amount |
NUMBER → BOOLEAN |
amount >= 0 |
is positive amount |
NUMBER → BOOLEAN |
amount > 0 |
Example: Currency Operations
-- Currency Example: ISO 4217 currency handling
IMPORT currency
-- Currency codes
#EVAL `US Dollar code` -- "USD"
#EVAL `Euro code` -- "EUR"
-- Decimal places per currency
#EVAL `decimal places for currency` "USD" -- RIGHT 2
#EVAL `decimal places for currency` "JPY" -- RIGHT 0 (no decimals)
#EVAL `decimal places for currency` "XXX" -- LEFT "Unknown currency code: XXX"
-- Create money from minor units (cents)
-- 12345 cents = $123.45
DECIDE priceInCents IS 12345
DECIDE formattedPrice IS Money priceInCents "USD"
#EVAL formattedPrice -- RIGHT "123.45 USD"
-- Japanese Yen has no decimals
DECIDE yenAmount IS Money 1000 "JPY"
#EVAL yenAmount -- RIGHT "1000 JPY"
-- Convert between major and minor units
DECIDE dollars IS 99.99
DECIDE cents IS `major to minor units` dollars "USD"
#EVAL cents -- RIGHT 9999
DECIDE backToDollars IS `minor to major units` 9999 "USD"
#EVAL backToDollars -- RIGHT 99.99
-- Arithmetic (all in minor units to avoid floating point errors)
DECIDE amount1 IS 1000 -- $10.00
DECIDE amount2 IS 500 -- $5.00
DECIDE added IS `add money` amount1 amount2 "USD"
#EVAL added -- RIGHT 1500 ($15.00)
DECIDE subtracted IS `subtract money` amount1 amount2 "USD"
#EVAL subtracted -- RIGHT 500 ($5.00)
-- Multiply by factor (e.g., tax)
DECIDE taxRate IS 1.08 -- 8% tax
DECIDE withTax IS `multiply money` amount1 taxRate "USD"
#EVAL withTax -- RIGHT 1080 ($10.80)
-- Comparisons
#EVAL `money greater than` 1000 500 -- TRUE
#EVAL `money at least` 1000 1000 -- TRUE
-- Validation
#EVAL `is valid currency code` "USD" -- TRUE
#EVAL `is valid currency code` "usd" -- FALSE (must be uppercase)
#EVAL `is non-negative` 100 -- TRUE
#EVAL `is positive` 0 -- FALSE
See currency.l4 source for all functions.