Functor Domain Versioning

It is problematic to update functor domains, if terms have been persisted in serialized form (e.g. using save to save the terms in a file).

The persisted terms will be in the old format, but the program expects the new format.

The attributes default/1 and retiredFunctor/1 can help dealing with such problems.

Default values
The last arguments of a functor can have default values:

domains ppp = fct(           integer A,            real B,            string C,            integer* NewInfo [default([])]        ).

The default attribute does not change anything within the program; it only affects the deserialization. If during deserialization we meet the closing parenthesis too soon we supply default values for the remaining arguments.

Notice that this will only work for text deserialization, in binary form there is no way to determine whether there are fewer arguments or not.

The default attribute does not have any effect for the code that must be written in the program, in that code the last argument must always be present.

Retired functors
Assume that we not only want to add an extra integer list to the fct functor, we also want to drop the real B.

domains ppp = fct(           integer A,            string C,            integer* NewInfo        ).

Now deserialization cannot be handled simply by adding a default argument to the last attributes.

Instead the old functor alternative fct can be retired and replaced by a new fct2:

domains ppp = fct(integer A, real B, string C) [retiredFunctor(aaa::fct_ppp)]; fct2(integer A, string C, integer* New).

The retiredFunctor attribute says that this alternative is no longer in the domain; it can however still be expected in serialized terms. When met in a serialized term, the predicate aaa::fct_ppp</vp> will be used to correct the problem. The predicate aaa::fct_ppp</vp> must have the type:

predicates fct_ppp : (integer A, real B, string C) -> ppp NewValue.

I.e. it takes the arguments of the old functor and returns a value in the functor domain.

We can implement fct_ppp like this:

clauses fct_ppp(A, _B, C) = fct2(A, C, []).

The retired functor does not exist inside the program; the program can only see the rest of the functors, i.e. the non-retired ones.

retiredFunctor/1 will also work for binary serializations, provided:


 * The old domain had more than one alternative (so there are functor numbers in the serialization)
 * New alternatives are added last (to retain functor numbers)

(It is however not recommend using binary serialization for inter-session persistence).