One rule that renames many fields at once, driven by a small mapping table.
variable-predicates.py · output · proof · check · try it in the playground
Data often arrives with someone else’s field names. A source system calls
them source_name and source_age; we want name and age.
Can we translate the field names with a lookup table, instead of writing one rule per field? And can we see where each translated value came from?
Here every fact is a triple: a subject, a relation, and a value.
fact(t('alice', 'source_name', 'Alice'))
reads alice has source_name ‘Alice’.
The trick is that the relation in the middle is just data — so a rule can use a variable there and treat the relation name like any other value.
fact(t('alice', 'source_name', 'Alice'))
fact(t('alice', 'source_age', 30))
fact(maps('source_name', 'name'))
fact(maps('source_age', 'age'))
implies(t(S, Source, O) & maps(Source, Target), t(S, Target, O))
query(t('alice', 'name', Name))
query(t('alice', 'age', Age))
The rule reads: if S has value O under the Source name, and Source maps to Target, then S has value O under the Target name. One rule covers every row of the mapping table.
t('alice', 'name', 'Alice')
t('alice', 'age', 30)
Alice’s name and age, now under the field names we wanted. The original facts are left as they were.
For the name:
The age is the same rule again, with facts 2 and 4. The proof shows which mapping row produced each value.
A separate checker read all 6 steps of the proof against the program and confirmed that:
Verdict: checked. Nothing taken on trust.
python -m peye examples/variable-predicates.py # the answers
python -m peye --proof examples/variable-predicates.py # answers with their proof
Or open it in the playground.
Add a new field and a mapping row — fact(t('alice', 'source_city', 'Gent'))
and fact(maps('source_city', 'city')) — plus the question
query(t('alice', 'city', _)). The same rule answers
t('alice', 'city', 'Gent').
When relation names are data, one general rule plus a table can replace a pile of special cases — and the proof still tells you exactly which table row was used.