Using Dyalog Domain Objects for Safe Numeric Ranges in APL
Learn how Dyalog APL domain objects provide automatic range validation that propagates through vectorized code, with a worked temperature‑conversion example and notes on performance and version limits.
16 Nov 2025, 02:03 UTC

When building numeric pipelines in APL you often need to guarantee that values stay inside a specific interval—for example, temperatures between –273.15 °C and 1000 °C, or percentages between 0 and 1. Writing explicit checks after every operation clutters code and is easy to forget, especially when the data flows through many vectorized functions.
Thesis: Domain objects give built‑in validation that travels with the data
Dyalog APL provides ⎕DT (domain definition) to create a domain object. A domain object is an array that carries a tag and a set of validation rules. Whenever you assign a value to a variable that holds a domain object, Dyalog checks the value against the rule and raises a DOMAIN ERROR if it fails. The domain tag propagates through most primitive functions, so the validation stays attached without extra code.
Creating and using a domain
To define a domain you call ⎕DT with a name and a specification. The simplest specification is a pair of numbers that denote the inclusive lower and upper bounds.
⎕DT 'Temperature' (-273.15 1000) ⍝ define a domain named Temperature
After the definition, any array you assign to a variable that is declared with that domain will be validated:
temp ← ⎕NULL ⍝ start with an empty placeholder
temp ← 25 ⍝ OK – 25 lies inside –273.15‥1000
temp ← 1500 ⍝ DOMAIN ERROR: value outside the domain
The domain object itself is just an array; you can inspect it with ⎕DT 'Temperature' which returns a nested representation of the rule.
Worked example: temperature conversion with validation
Suppose you want to convert a list of Celsius values to Fahrenheit, but you must ensure every input is a physically plausible temperature. By giving the input vector a domain, the conversion function can stay pure and vectorized.
⎕DT 'Celsius' (-273.15 1e6) ⍝ generous upper bound for demo
celsius ← ⎕NULL
celsius ← -50 0 25 100 ⍝ all valid
celsius ← -300 0 25 ⍝ DOMAIN ERROR on –300
Now the conversion:
Fahrenheit ← {⍵×9÷5+32} ⍝ plain vectorized function
Fahrenheit celsius ⍝ works because celsius still carries the domain
If you accidentally pass an out‑of‑range value, the error is raised at the point of assignment, not inside Fahrenheit. This keeps the core algorithm simple and lets you handle the error once, at the data‑entry boundary.
Trade‑offs and limitations
- Performance: Each assignment triggers a runtime check. In tight inner loops where millions of numbers are processed, this overhead can be measurable. Profiling with
⎕MONITORshows the extra cost is usually a few percent per assignment, but you should benchmark on your target version. - Serialization: Domain tags are not preserved when you convert to JSON, CSV, or binary files. You must explicitly map domain values to plain numbers before export and re‑apply the domain after import.
- Version sensitivity: The exact propagation rules (e.g., which primitives preserve the domain) changed between Dyalog 17.1 and 18.0. Always verify behavior on the version you plan to deploy.
Actionable next steps
- Open a Dyalog session (any recent version, e.g., 18.2) and run
⎕DT 'MyDomain' (low high)to confirm the definition succeeds. - Assign a valid and an invalid value to a variable holding that domain and observe the
DOMAIN ERRORfor the invalid case. - If you are working with existing code, identify the boundary where data enters your APL system (file read, user input, socket) and wrap the incoming array with the appropriate domain using
⎕DT. - Run a representative workload with
⎕MONITORto measure the added latency; decide whether the safety gain outweighs the cost for your use case.
By attaching validation rules directly to the data, domain objects let you write clearer, more reliable APL programs without scattering manual checks throughout your code.
0 replies
A thoughtful contribution can make all the difference. Be the first to share one.