Skip to content

Instantly share code, notes, and snippets.

@GeoffChurch
Last active February 27, 2025 12:28
Show Gist options
  • Save GeoffChurch/50a1c871f42c7c1650a527bcb5d0c08b to your computer and use it in GitHub Desktop.
Save GeoffChurch/50a1c871f42c7c1650a527bcb5d0c08b to your computer and use it in GitHub Desktop.
Prolog getters, setters, mutators using term_expansion
user:term_expansion((:- derive_accessors(ClassTemplate)), Clauses) :-
ClassTemplate =.. [ClassName|Fields],
functor(ClassTemplate, ClassName, Arity),
functor(Skel, ClassName, Arity),
term_variables(Skel, Vars),
foldl(build_accessors(Skel), Fields, Vars, [], Clauses).
return(G), [Ret] --> { call(G, Ret) }.
build_accessors(Skel, Field, Var) -->
foldl(return, [derive_get(Skel, Field, Var),
% derive_dcg_get(Skel, Field, Var),
derive_set(Skel, Field, Var),
derive_mut(Skel, Field, Var)]).
% e.g. get_name(employee(A, _), A).
derive_get(Skel, Field, Var, Ret) :-
atom_concat(get_, Field, GetF),
Ret =.. [GetF, Skel, Var].
% derive_dcg_get(Skel, Field, Var, Ret) :-
% atom_concat(dcg_, Field, GetF),
% Ret =.. [GetF, Var, Skel, Skel].
% e.g. set_name(A, employee(_, B), employee(A, B)).
derive_set(Skel, Field, Var, Ret) :-
copy_term([Var], Skel, [Var_], Skel_),
atom_concat(set_, Field, SetF),
Ret =.. [SetF, Var_, Skel, Skel_].
% e.g. mut_name(A, employee(B, C), employee(D, C)) :- call(A, B, D).
derive_mut(Skel, Field, Var, Ret) :-
copy_term([Var], Skel, [Var_], Skel_),
atom_concat(mut_, Field, MutF),
Head =.. [MutF, Goal, Skel, Skel_],
Ret = (Head :- call(Goal, Var, Var_)).
% Example:
:- derive_accessors(employee(name, salary)).
become_bob_bonus -->
set_name(bob),
mut_salary(plus(100)).
:- John = employee(john, 30000),
% poor john learns about the become bob bonus
become_bob_bonus(John, Bob),
% now he is wealthy bob
get_salary(Bob, Salary),
writeln(salary:Salary).
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment