Converting Terms to Atoms preserving variable names in YAP prolog

前端 未结 1 763
隐瞒了意图╮
隐瞒了意图╮ 2020-11-29 13:07

Is there a way to configure YAP (and/or SWI prolog) so they will preserve variable names in any call to term_to_atom/2 ?.

For example, when I execute th

相关标签:
1条回答
  • 2020-11-29 13:07

    There are two issues involved. How to get the variable name X into the system, and how to get a term with such a variable into the atom.

    The X you type in is read by the top level which converts it to a regular variable which does not have a name associated. Let's see that in YAP:

       ?- read(Term).
       |: X+3*Y+X.
    Term = _A+3*_B+_A
    

    The |: is YAP's prompt for input. And we have entered X+3*Y+X. However, the variable Term contains _A and _B (names chosen by the top level) in place of X and Y. So the information is lost and cannot be restored once it is read by read/1.

    You have to access that information differently with the more general built-in for reading read_term/2,3 and the option variable_names/1.

       ?- read_term(T,[variable_names(Eqs)]).
       |: X+3*Y+X.
    Eqs = ['X'=_A,'Y'=_B],
    T = _A+3*_B+_A
    

    So the read option variable_names/1 gives you the information to restore the variable names. For each named variable read by read_term/2 there is a structure Name = Variable where Name is an atom representing the variable name. Above, 'X' is the name capital X.

    Anonymous variables, that is variables whose name is _, do not occur in the list of variable names. They can be rapidly extracted like so:

     ?- read_term(T,[variable_names(Eqs)]),
        term_variables(Eqs, Named),
        term_variables(Named+T, Vars),
        append(Named, Anons, Vars).
    

    So much for the reading.

    Now for the writing. We cannot write the term directly but have to accompany it with the list Eqs. Let's call the new predicate term_to_atom(Term, Eqs, Atom). In both YAP and SWI there is with_output_to(Output, Goal) which writes the output of Goal to different destinations like atom(A). So you can now use write_term/2 to write the term as you please. An example:

    ?- with_output_to(atom(A),write_term('a b'+X,[quoted(true)])).
    A = '\'a b\'+_131284'.
    

    The variable _131284 looks very ugly. To get variables associated with their names for printing we can implement term_to_atom/3 as follows:

    term_to_atom(T, Eqs, A) :-
       with_output_to(atom(A), write_term(T,[variable_names(Eqs),quoted(true)]) ).
    

    And use it like so:

       ?- read_term(T,[variable_names(Eqs)]), term_to_atom(T, Eqs, Atom).
       |: X+3*Y+X.
    Atom = 'X+3*Y+X',
    Eqs = ['X'=_A,'Y'=_B],
    T = _A+3*_B+_A
    

    variable_names/1 exists as a write option in ISO, Minerva, Jekejeke, GNU, B, SWI, YAP, and SICStus.

    In SICStus, the originator of writing terms to lists, one writes:

    :- use_module(library(codesio)).
    
    term_to_atom(T, Eqs, Atom) :-
       write_term_to_codes(T, Codes, [variable_names(Eqs),quoted(true)]),
       atom_codes(Atom, Codes).
    

    The following was an ISO incompatible work around for YAP prior to 6.3.4. It is no longer necessary. As for the differences to a separate write option: term_to_atom/3 as defined below interferes with constraints and does not correctly render '$VAR'/1.

    But for the moment we can only approximate the ideal option variable_names/1. To print terms with our own variable names, variables have to be substituted in YAP by '$VAR'(Codes) where Codes is a list of character codes. This does not do exactly the same, but it is very close. This goes into a file:

    :- use_module(library(apply)).
    :- use_module(library(lambda)).
    
    write_eqs_term(T, Eqs) :-
       \+ \+ ( 
               maplist(\Eq^( Eq = (N='$VAR'(Chs)), atom_codes(N,Chs)), Eqs),
               write_term(T,[numbervars(true),quoted(true)])
       ).
    
    term_to_atom(T, Eqs, A) :-
       with_output_to(atom(A), write_eqs_term(T, Eqs) ).
    

    For SWI, you would have to replace atom_codes(N,Chs) by N = Ch. and install library(lambda) first. It's pre-installed in YAP.

    0 讨论(0)
提交回复
热议问题