Skip to content

Instantly share code, notes, and snippets.

@GeoffChurch
Last active February 19, 2024 00:48
Show Gist options
  • Save GeoffChurch/80bc98ce5d42184c12f6443c5cb64980 to your computer and use it in GitHub Desktop.
Save GeoffChurch/80bc98ce5d42184c12f6443c5cb64980 to your computer and use it in GitHub Desktop.
:- op(700, xfx, .=).
A:AFs .= B:BFs =>
gets(AFs, A, Val),
gets(BFs, B, Val).
X:Fs .= Val => gets(Fs, X, Val).
Val .= X:Fs => gets(Fs, X, Val).
A .= B => A = B.
colon_list(X:Xs0, Out) => colon_list(Xs0, Xs), Out = [X|Xs].
colon_list(X, Out) => Out = [X].
get_(X, X, X).
set_(X, _, X).
% Auto-derive get and set from mut
get(Field, Term, Value) :- mut(Field, get_(Value), Term, _).
set(Field, Value) --> mut(Field, set_(Value)).
% Chained mut
muts([], P) --> call(P).
muts([Field|Fields], P) --> mut(Field, muts(Fields, P)).
% Chained get
gets(Fields) --> { colon_list(Fields, FieldsL) }, foldl(get, FieldsL).
% Chained set
sets(Fields, Value) --> muts(Fields, set_(Value)).
% Example muts
mut(ceo, P,
company(CEO0, Employees),
company(CEO, Employees)) :-
call(P, CEO0, CEO).
mut(dob, P,
person(Name, Salary, DOB0),
person(Name, Salary, DOB)) :-
call(P, DOB0, DOB).
mut(employees, P,
company(CEO, Employees0),
company(CEO, Employees)) :-
call(P, Employees0, Employees).
:- begin_tests(accessors).
test(gets_f_f, [Cmpy1-Cmpy2 =@= company(person(_, _, DOB), Es)-company(person(_, _, DOB), Es)]) :-
Cmpy1:ceo:dob .= Cmpy2:ceo:dob,
Cmpy1:employees .= Cmpy2:employees.
test(gets_f_v, [Cmpy =@= company(person(_, _, 1980), _)]) :-
Cmpy:ceo:dob .= 1980.
test(gets_v_f, [Cmpy =@= company(person(_, _, 1980), _)]) :-
1980 .= Cmpy:ceo:dob.
test(gets_v_v, [X == Y]) :-
X .= Y.
test(sets, [CEO =@= company(person(_, _, 1980), _)]) :-
sets([ceo, dob], 1980, _, CEO).
test(muts, [Cmpy0-Cmpy1 =@= company(person(A, B, _), C)-company(person(A, B, 1981), C)]) :-
call_dcg((
sets([ceo, dob], 1980),
muts([ceo, dob], succ)),
Cmpy0, Cmpy1).
:- end_tests(accessors).
:- run_tests.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment