Is it possible to preserve variable names when writing and reading term programatically?

本小妞迷上赌 提交于 2019-12-10 13:28:42

问题


I'm trying to write an SWI-Prolog predicate that applies numbervars/3 to a term's anonymous variables but preserves the user-supplied names of its non-anonymous variables. I eventually plan on adding some kind of hook to term_expansion (or something like that).

Example of desired output:

    ?- TestList=[X,Y,Z,_,_].
       > TestList=[X,Y,Z,A,B].

This answer to the question Converting Terms to Atoms preserving variable names in YAP prolog shows how to use read_term to obtain as atoms the names of the variables used in a term. This list (in the form [X='X',Y='Y',...]) does not contain the anonymous variables, unlike the variable list obtained by term_variables, making isolation of the anonymous variables fairly straightforward.

However, the usefulness of this great feature is somewhat limited if it can only be applied to terms read directly from the terminal. I noticed that all of the examples in the answer involve direct user input of the term. Is it possible to get (as atoms) the variable names for terms that are not obtained through direct user input? That is, is there some way to 'write' a term (preserving variable names) to some invisible stream and then 'read' it as if it were input from the terminal?

Alternatively... Perhaps this is more of a LaTeX-ish line of thinking, but is there some way to "wrap" variables inside single quotes (thereby atom-ifying them) before Prolog expands/tries to unify them as variables, with the end result that they're treated as atoms that start with uppercase letters rather than as variables?


回答1:


You can use the ISO core standard variable_names/1 read and write option. Here is some example code, that replaces anonymous variables in a variable name mapping:

% replace_anon(+Map, +Map, -Map)
replace_anon([_=V|M], S, ['_'=V|N]) :- member(_=W, S), W==V, !, 
   replace_anon(M, S, N).
replace_anon([A=V|M], S, [A=V|N]) :- 
   replace_anon(M, S, N).
replace_anon([], _, []). 

variable_names/1 is ISO core standard. It was always a read option. It then became a write option as well. See also: https://www.complang.tuwien.ac.at/ulrich/iso-prolog/WDCor3

Here is an example run:

Welcome to SWI-Prolog (threaded, 64 bits, version 7.7.25)

?- read_term(X,[variable_names(M),singletons(S)]), 
   replace_anon(M,S,N), 
   write_term(X,[variable_names(N)]).
|: p(X,Y,X).
p(X,_,X)

To use the old numbervars/3 is not recommended, since its not compatible with attribute variables. You cannot use it for example in the presence of CLP(FD).




回答2:


Is it possible to get (as atoms) the variable names for terms that are not obtained through direct user input?

if you want to get variable names from source files you should read them from there.

The easiest way to do so using term expansion.

Solution:

read_term_from_atom(+Atom, -Term, +Options)

Use read_term/3 to read the next term from Atom.

Atom is either an atom or a string object.

It is not required for Atom to end with a full-stop.

Use Atom as input to read_term/2 using the option variable_names and return the read term in Term and the variable bindings in variable_names(Bindings).

Bindings is a list of Name = Var couples, thus providing access to the actual variable names. See also read_term/2.

If Atom has no valid syntax, a syntax_error exception is raised.

write_term( Term ) :-
  numbervars(Term, 0, End),
  write_canonical(Term), nl.


来源:https://stackoverflow.com/questions/54356304/is-it-possible-to-preserve-variable-names-when-writing-and-reading-term-programa

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!