Acceso a los predicados

functor(Pred,P,Arity).
Usos:
  1. obtener nombre y num. de args
  2. construir un predicado

?- functor(papa(juan,juanito),F,N).
F = juan, N = 2

?- functor(Pred,foo,3).
Pred = foo(_,_,_).

arg(N,Pred,Valor).
Usos:
  1. seleccionar un argumento
  2. instanciar un argumento

?- arg(2,arbol(6,4,8),X).
X = 4

?- arg(2,arbol(3,X,7),1).
X = 1

Ejemplo: substituye un elemento por otro: subst(Old,New,Pred,NPred)

subst(Old,New,Old,New).
subst(Old,New,Otro,Otro) :-
       atomic(Otro),
       Otr0 \= Old.     % o \+ Otro = Old
subst(Old,New,Pred,NPred) :-
       functor(Pred,F,N),
       functor(NPred,F,N),
       subst_aux(N,Old,New,Pred,NPred).

subst_aux(N,Old,New,Pred,NPred) :-
       N > 0,
       arg(N,Pred,ArgN),
       subst(Old,New,ArgN,NArgN),
       arg(N,NPred,NArgN),
       N1 is N - 1,
       subst_aux(N1,Old,New,Pred,NPred).
subst_aux(0,_,_,_,_).

El programa de arriba no toma en cuenta variables. Si tuvieramos variables, entonces hay que cambiar la primera por lo siguiente:

subst(Old,New,Var,Var) :- var(Var), !.
subst(Old,New,Viejo,New):- atomic(Viejo), Old = Viejo, !.

``univ'' <=> ``=..''

Pred =.. [F|Args]

padre(a,b) =.. [padre,a,b]

?- Meta =.. [foo,a,b,c].
Meta = foo(a,b,c).

?- foo(a,b,c) =.. [P|A].
P = foo, A = [a,b,c]

Con functor y arg o con =.., podemos crear nuevos predicados.

Podemos definir ``univ'' en términos de ``functor'' y ``arg''.

Si sabemos el predicado y queremos obtener la lista $[F \mid Args]$:

univ(Pred,[F|Args]) :-
      functor(Pred,F,N),
      args(1,N,Pred,Args).

args(I,N,Pred,[Arg1|Args]) :-
      I =< N,
      arg(I,Pred,Arg1),
      I1 is I + 1,
      args(I1,N,Pred,Args).
args(I,N,_,[]):- I > N.

Si sabemos la lista $[F \mid Args]$ y queremos obtener el predicado:

univ(Pred,[F|Args]) :-
      long(Args,N),
      functor(Pred,F,N),
      args(Args,Pred,1).

args([Arg1|Args],Pred,N) :-
      arg(N,Pred,Arg),
      N1 is N + 1,
      args(Args,Pred,N1).
args([],_,_).

long([],0).
long([H|T],N) :-
     long(T,N1),
     N is N1 + 1.

Maplist: tener un predicado que queremos aplicar a una lista de argumentos (asuminedo que el resultado siempre es el último argumento)

maplista(_,[],[]).
maplista(F,[L1|T1],[Res1|ResT]) :-
     junta(L1,[Res1],Args),  % si es un solo arg. no hace falta
     Meta =.. [F|Args],
     call(Meta),
     maplista(F,T1,ResT).

e.g.,
?- maplista(junta,[[[a,b],[c,d]],[[1,2],[3,4]]],X).
X = [[a,b,c,d],[1,2,3,4]]

?- maplista(quita,[[a,[b,c,a,d]],[1,[2,1,3,4]]],X).
X = [[b,c,d],[2,3,4]]

Para copiar una estructura a otra:

copy(Pred,CPred) :-
    copy(Pred,CPred,[],_).

copy(Var1,Var2,Subst,Subst) :-
    var(Var1),
    v_member(Var1/Var2,Subst),
    !.
copy(Var1,Var2,Subst,[Var1/Var2|Subst]) :-
    var(Var1), !.
copy(Pred,CPred,Subst1,Subst2) :-
    functor(Pred,F,N),
    functor(CPred,F,N),
    copy_args(N,Pred,CPred,Subst1,Subst2).

copy_args(0,_,_,S,S) :- !.
copy_args(N,Pred,CPred,S1,S3) :-
    arg(N,Pred,ArgN),
    copy(Arg1,CArg1,S1,S2),
    arg(N,CPred,CPredN),
    N1 is N - 1,
    copy_args(N1,Pred,CPred,S2,S3).

v_member(A/B,[V1/B|_]) :-
    A == V1, !.
v_member(X,[_|T]) :-
    v_member(X,T).



emorales 2012-05-03