Consider a (meta-logical) predicate var_in_vars(Var, Vars)
which takes a variable Var
and a list of variables Vars
and succeeds if Var
occurs in Vars
. So we do not need to ensure that Var
is a variable, nor that Vars
is a list of variables.
What is the most compact and canonical way to express this in ISO Prolog? Here is an overview of the built-ins in ISO/IEC 13211-1:1995 including Cor.2:2012.
?- var_in_vars(V, [U,V,W]).
true.
?- var_in_vars(V, [X,Y,Z]).
false.
Solution Synthesis
Solution : Short
Alternative 1 : Simple
Alternative 2 : Depending on circumstances, this could be more suitable
Alternative 3 : More complex
Alternative 4 : Other possibility
Links :
Standard
Note : The context of the question, which is a specific compactness challenge involving the expressivity of ISO predicates under given circumstances.
One possibility:
and shorter:
EDIT: Future readers, please take into account the context of the question, which is a specific compactness challenge involving the expressivity of ISO predicates under given circumstances.
In other circumstances, you will likely benefit more from a definition like:
this definition passes the tests, but... do I miss some subtlety ?
The solution @false can be simplified to:
When
V
is a member of theVs
list, the second argument returnsVs
(due to the left-to-right traversal of theVs+V
term). WhenV
is not a member ofVs
, the second argument returns a list that have one more element thanVs
and thus cannot unify with it. Although there's an implicit unification in the second argument, in neither case there's a danger of creating a cyclic term. I.e. unification being STO is not a problem in this simplified solution.But is the simplification worth it w.r.t. performance? The use of equality,
(==)/2
have the potential of failing earlier and thus making the original solution faster.An alternative solution is:
But the solutions by @mat are better and more elegant and the solution by @CapelliC was for a long time the most portable one (the
subsumes_term/2
predicate was only standardized recently and not all systems provided theunify_with_occurs_check/2
predicate).And here goes another one, although a bit more complex:
So this relies on the precise order how variables are visited. And since this is well defined in the standard we can rely that they
A drawback of this definition is that it has minimum cost proportional to the length of
Vs
. But since an internal traversal is often quite efficiently implemented, this is not such a problem.It has one big advantage: It only succeeds if
Vs
is a list of variables.