Variable writing

Possibly related, I’m wondering what people think about writing variables by write_term/2,3. We have the ISO extension variable_names(+List) and numbervars(+Bool). SWI-Prolog’s numbervars implies the SP legacy_numbervars, writing ‘$VAR’(Atom) as Atom, provided Atom is a valid Prolog variable token. EC has variables(+Method) with various options.

What do people do to guarantee a term can be read when using anonymous variables? In most systems (I think), the _NNN are based on addresses or offsets on the stacks. This implies that a GC call changes the numbers. Now SWI-Prolog’s write_term/3 is in C, and normally it does not create any terms, so normally it won’t run GC. When one of the portray options is given though, it will run Prolog and (thus) may run GC.

SWI-Prolog’s write_canonical/1,2 writes singleton variables as _ and other variables using numbervars as A,B,… This is IMO a great feature as it makes the term shorter and easier to read, but most importantly, reproducible.

I agree it was unnecessary for ISO to cripple the traditional numbervars, but that’s what we have… So SP’s legacy_numbervars seems a good idea, but we can possibly avoid a new option by allowing a 3-valued numbervars(true|false|legacy).
GP has invented yet another variant by introducing a new functor VARNAME(Name) to work around the limitation…

In my view, the whole $VAR mechanism is a hack that unfortunately survived from early Prologs. It is completely incompatible with constraints, as you can’t simply instantiate a domain variable with an arbitrary term, even temporarily, without introducing additional hacks.
It is a ok as a backward compatibility feature, but I would be against any feature relying on it or requiring it. In a system with attributed variables, there are cleaner ways, like attaching a name as an attribute.

In ECLiPSe, write_term is also in C, portrays are wrapped in \+ \+, and GC’s don’t affect the older stack parts. This should be safe wrt the original term variables emitted by write_term, but there are no guarantees about what you write inside the portray…

Building this into write_term would horribly conflict at least with portray and partial.
And it’s easily done by preprocessing the term before calling write_term.