Writing a predicate to add atoms

2019-08-12 18:54发布

问题:

I have to write a predicate to do work like following:

  ?- cat(north,south,X).
  X = northsouth

  ?- cat(alley,'91',Y).
  X = alley91

  ?-cat(7,uthah,H).
    Bad Input
    H = H

Please Help..

回答1:

atom_concat_redefined(A1, A2, A3) :-
   ( nonvar(A1) -> atom_chars(A1, Chs1) ; true ),
   ( nonvar(A2) -> atom_chars(A2, Chs2) ; true ),
   ( nonvar(A1), nonvar(A2) -> true ; atom_chars(A3, Chs3) ),
   append(Chs1, Chs2, Chs3),
   atom_chars(A1, Chs1),
   atom_chars(A2, Chs2),
   atom_chars(A3, Chs3).

This definition produces the same errors in a standard conforming implementation like SICStus or GNU - there should be no other differences, apart from performance. To compare the errors use the goal:

| ?- catch(atom_concat_redefined(A,B,abc+1), error(E,_), true).
E = type_error(atom,abc+1) ? ;
no

Note the underscore in error(E,_), which hides the implementation defined differences. Implementations provide additional information in this argument, in particular, they would reveal that atom_chars/2 or atom_concat/3 produced the error.



回答2:

atom_codes/2 it's the ISO approved predicate to convert between an atom and a list of codes. When you have 2 lists corresponding to first two arguments, append/3 (alas, not ISO approved, but AFAIK available in every Prolog), will get the list corresponding to third argument, then, convert that list to atom...

Note that, while append/3 is a 'pure' Prolog predicate, and can work with any instantiation pattern, atom_codes/2 requires at least one of it's argument instantiated. Here is a SWI-Prolog implementation of cat/3, 'working' a bit more generally. I hope it will inspire you to read more about Prolog...

ac(X,Xs) :-  when((ground(X);ground(Xs)), atom_codes(X,Xs)).
cat(X,Y,Z) :- maplist(ac, [X,Y,Z],[Xs,Ys,Zs]), append(Xs,Ys,Zs).

edit

as noted by @false I was wrong about append/3. Now I'll try to understand better what append/3 does... wow, a so simple predicate, so behaviour rich!



标签: prolog