In Prolog, there are predicates that are bidirectional (or even "multidirectional"), in the sense that you can divide a set of variables into input and output variables in many different ways. For example, the predicate number_string acts as a bijection in both directions:
number_string(N, "42"). % finds solution N = 42 number_string(42, S). % finds solution S = "42"
However, this remarkable property does not seem to be preserved as a result of the combination of items. For example, consider the following two predicates that simply translate strings, such as 3x^2 into fragments of an abstract syntax tree, such as term(3,2) :
parse_stuff(String, term(Coeff, Pow)) :- string_concat(CoeffStr, MonomialStr, String), string_concat("x^", PowStr, MonomialStr), number_string(Coeff, CoeffStr), number_string(Pow, PowStr). write_stuff(String, term(Coeff, Pow)) :- number_string(Pow, PowStr), number_string(Coeff, CoeffStr), string_concat("x^", PowStr, MonomialStr), string_concat(CoeffStr, MonomialStr, String).
Both predicates are exactly the same, except that the order of the defining sentences on the right is reversed. All items on the right are bi-directional.
Here is an example session:
?- parse_stuff("3x^2", X). X = term(3, 2). ?- parse_stuff(X, term(3, 2)). ERROR: string_concat/3: Arguments are not sufficiently instantiated ?- write_stuff(X, term(3, 2)). X = "3x^2". ?- write_stuff("3x^2", X). ERROR: number_string/2: Arguments are not sufficiently instantiated
Both predicates work in only one direction, although both of them are obviously bijections, which is rather sad.
The question consists of two parts (there are two requirements: ease of use, ease of maintenance):
- Is there a reliable way to build bi-directional predicates in Prolog?
- Is it possible to avoid duplication of code (i.e., support two versions: one normal, one upside down)?
Maybe there is some kind of flag that says "if necessary, change the order of sentences"?
I am currently using SWI-Prolog 7.1.x, if relevant.
↓ Go to my own answer ↓