1
votes

Is there any way that I can get a binding for a variable in Prolog even if the goal fails. I have a predicate where I am binding a variable with some value and after this I am failing the goal explicitly, but when I run the query it simply results in a fail without providing any biding for the variable. Something similar:

a(X) :-
 X = 'something',
 fail.
2
Do you also have a a(_). rule somewhere in your code? It looks like you're trying to force backtracking with fail, right? - Sergey Kalinichenko

2 Answers

2
votes

yes, this is how it is supposed to happen in Prolog. fail means the rejection of bindings made so far, because it says that these bindings are invalid, do not satisfy the goal.

but you can save some binding that will be undone on backtracking, with e.g. asserta predicate:

a(X) :-
 X = 'something',
 asserta(saved_x(X)),
 fail.

Then, if you query saved_x(Z) afterwards, you will recover that value. Of course this is the part of Prolog that is extra-logical, i.e. outside of the logical programming paradigm.

3
votes

@Will Ness is correct (+1), assert can be used to capture bindings of variables as shown.

However, if you strictly need to retrieve bindings for variables in predicates like a and you know which parts could fail (and you don't care about them), then you could use combinations of cut (!) and true to permit a to proceed regardless. For example, consider:

a(X) :-
    goalA(X), % a goal for which we definitely want a binding
    (goalB, ! ; true). % an 'optional' goal which may fail

goalA('something').
goalB :- fail.

Executing this gives a('something'), even though goalB failed. Note that this isn't a commonly used way to program in Prolog, but if you know exactly what you're doing...