Using the attr_unify_hook I want to do something like this:
% Declare a variable that can be unified in French
% or Spanish (or the canonical language which is English)
%
% So the variable value is always stored in english (the canonical
% language) but it allows other languages for unification
?- multi_language(Word,lang(_,[spanish,french])).
multi_language(Word,lang(_,[spanish,french])).
% The value of the variable is in English,
% but allows unification with French
?- $Word = deux. % French
two % The stored value in english
multi_language(Word,lang(french,[spanish,french])). % These are the attributes
% The value of the variable is in English,
% but allows unification with Spanish
?- $Word = dos. % Spanish
two % Stored value in canonical language (english)
multi_language(Word,lang(spanish,[spanish,french])). % Notice the original language is retained in the attributes
This allows to store the variable value in a canonical way, but the variable can be unified in different languages.
So is there any way to store a different value (namely the english value, instead of french or whatever was given originally by the user) with attr_unify_hook? I don’t seem to find a way.
I don’t really get what you want, but the above seems dubious. Prolog variables are not like in imperative languages things that are allocated somewhere and that you give a value. They are unspecified parts of a Prolog term. If that part is specified, the variable is simply gone. So, in X=dos, Y = deux, X = Y, the X=Y is exactly the same as simply calling dos=deux. That doesn’t call any attributed variable hooks as no variables are involved.
An attributed variable is for a reason typically called a constraint: it allows annotating a variable (for as long as it is a variable) with something that indicates what are legal values for that variable. Once such a value is accepted though, the attributed variable no longer exists. This does also deal with unifying two attributed variables, where the hook can compute a joined constraint (i.e., the intersection of the admissible value sets).
You can misuse the latter to create something that uses a variable and puts the value you want to represent in an attribute. This is rather expensive and a bit clumsy to use though. It is probably wiser to rethink your data structures and/or algorithms.
Actually, what I was envisioning was that in X=dos, Y = deux, calling X = Y would be like two=two; which is logically reasonable.
The part that I was completely missing is this:
This would mean that I can’t keep track of the original language, since the attributes are gone.
In logical reasoning (I am referring to human logic), words point to realities, and it is perfectly reasonable --and normal-- for two different words to point to the same reality. Hence, in human languages, deux and two point to the same reality, which is the number two.
I know I can model this in other ways in prolog, but I wish for prolog to be as close to human logic as possible, and this is why I was looking at attributed variables: I was looking at the attributes truly as attributes, and not simply constraints on the possible values.
But they are the latter. As said, you can get what you want by never instantiating anything and keeping all values in attributes. That is clumsy, but possible you can create some layer around that to make it usable. The normal way is to canonical values in your computation and the related synonyms only for I/O. That will surely be a lot fatster and resource friendly.