Metaprogramando
En este capítulo vamos a explicar cómo se puede
convertir datos en código y después ejecutarlo. Pero
previamente mostraremos algunos predicados standard auxiliares
para este propósito, aunque tienen también otros usos.
Manipulación de términos
El predicado functor/3 es uno de los
más útiles entre la biblioteca standard Prolog. Este
predicado permite extraer el functor y la aridad de un
término cualquiera. Pero, al ser reversible, también
permite construir nuevos términos a
partir del functor y la aridad deseada. Los modos de uso son:
- functor(+Termino,-Functor,-Aridad).
- functor(-Termino,+Functor,+Aridad).
El siguiente ejemplo muestra como se extrae functor y aridad:
?- functor(termino(arg(1),arg(2)),Functor,Aridad).
Aridad = 2,
Functor = termino ?
yes
Ahora veremos como crear un nuevo término. Sus argumentos
siempre serán nuevas variables libres:
?- functor(NuevoTermino,prueba,4).
NuevoTermino = prueba(_,_,_,_) ?
yes
?-
Manipulación de argumentos con "arg"
Ahora que podemos construir términos, sería deseable
poder asignarles argumentos. Uno de los predicados que permiten esto
es arg/3. Para ello se indica el
número de índice del argumento deseado, empezando a
numerar por el 1 de izquierda a derecha. El modo de uso es:
- arg(+Indice,+Termino,-Argumento).
El primer uso de este predicado es extraer un argumento concreto de
un término:
?- arg(2,termino(a,b,c,d),ARG).
ARG = b ?
yes
?-
Si el término tiene variables libres como argumento, se les
puede asignar valor mediante arg/3. Pero
el resultado es el mismo que una simple unificación mediante
=/2. Esto se observa en el siguiente
ejemplo:
?- Termino = p(X,b), arg(1,Termino,zzz).
Termino = p(zzz,b),
X = zzz ?
yes
?- Termino = p(X,b), Termino = p(zzz,_).
Termino = p(zzz,b),
X = zzz ?
yes
?-
El predicado arg/3 solamente es
útil cuando se conoce a priori el número de argumentos
del término manipulado, pero en combinación con
functor/3 resulta muy eficaz.
Manipulación de argumentos con "univ"
En ocasiones resulta mucho más útil convertir los
argumentos de un término en una lista y viceversa. Esta es la
función de "univ", nombre que recibe el operador infijo
=../2. Sus modos de uso son:
- +Termino =.. -Lista
- -Termino =.. +Lista
La lista contiene siempre el functor del término en la primera
posición, y los argumentos en el resto de la lista. El
siguiente ejemplo desglosa los elementos de un término:
?- p(a,b,c(i)) =.. X.
X = [p,a,b,c(i)] ?
yes
?-
Y el siguiente ejemplo construye un nuevo término a partir de
la lista de sus componentes...
?- Termino =.. [functor,arg1,arg2,arg3].
Termino = functor(arg1,arg2,arg3) ?
yes
?-
Llamadas de orden superior
Lo interesante ahora es convertir un término en un objetivo
Prolog a ejecutar. Esto se consigue con el predicado
call/1. Naturalmente, el
término debe corresponder con algún predicado
existente, de otra forma, se genera una excepción. Por
ejemplo:
% Un predicado
mipred(X) :-
display(X),
nl.
% Llamada de orden superior
ejemplo :-
X = mipred(5),
call(X).
Naturalmente, este ejemplo carece de utilidad puesto que se puede
ejecutar la llamada a mipred/1
directamente. Pero resulta muy util en combinación con los predicados
anteriormente descritos. Por ejemplo:
sujeto(12).
sujeto(13).
sujeto(78).
aplicar(Predicado) :-
sujeto(X),
LLamada =.. [Predicado,X],
call(LLamada),
fail.
aplicar(_).
ejemplo :-
aplicar(display).
El resultado es el siguiente:
?- ejemplo.
12
13
78
yes
?-
Los predicados de este tipo, que reciben un argumento y lo convierten
a un objetivo ejecutable (sin saber lo que se ejecuta) se denominan
metapredicados. Dicho argumento se denomina
metaargumento.Un ejemplo de metapredicado es
la propia negación por fallo, que se
implementa de esta manera:
not(Objetivo) :-
call(Objetivo),
!,
fail.
not(_).
© Copyright 2002
Angel Fernández Pineda.