I have a simple constraint that I’ve built (code at bottom) noun/2
that says "X
must be a noun". To test, the only noun in the world is “rock” and the only atom that is a rock is rock1
:
?- noun("rock", X), X = rock1.
X = rock1.
?- noun("rock", X), X = rock2.
false.
If I want to find all X
that meet the constraint I can use the resolveConstraints/1
predicate I wrote (code at bottom) to do that:
?- noun("rock", X), resolveConstraints(X).
X = rock1.
But I really want the system to automatically call resolveConstraints(X) if the constrained variable is left unbound at the end of the query. Right now, the system behavior appears to be to print the constraints:
?- noun("rock", X).
noun(rock,$VAR(X)).
Is there a way to change the behavior to what I want?
Here’s the code for my “constraint system”:
:- module(noun, [resolveConstraints/1, noun/2]).
attr_unify_hook(AttValue, VarValue) :-
nonvar(VarValue) ->
nounEval(AttValue, VarValue)
;
fail.
noun(TypeName, X) :-
var(X),
put_attr(X, noun, TypeName).
nounEval("rock", rock1).
attribute_goals(X) -->
{ get_attr(X, noun, TypeName) },
[noun(TypeName, X)].
% Backtrack over all values of Variable that meet the constraints
resolveConstraints(Variable) :-
get_attrs(Variable, AttVars),
recurseAtt(AttVars, Variable, [], Terms),
comma_list(Conjunction, Terms),
del_attrs(Variable),
Conjunction.
recurseAtt([], _, ValueIn, ValueIn) :- !.
recurseAtt(Att, Variable, ValueIn, ValueOut) :-
Att = att(Module, Value, More),
atomic_list_concat([Module, 'Eval'], PredicateName),
compound_name_arguments(Term, PredicateName, [Value, Variable]),
recurseAtt(More, Variable, [Term | ValueIn], ValueOut).