Zona HTML Zona Java Zona PHP Zona ASP Zona Bases de datos
Inicio > Tutoriales > Otros lenguajes > Prolog > Curso avanzado de Prolog
-Tutoriales

Curso avanzado de Prolog


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.

 
Utilidades
Leer comentarios (0)
Escribir comentario
  Puntuación:
(26 votos)
Votar
Recomendar este tutorial
Estadísticas
 
Patrocinados
 

Copyright © 1999-2006 Programación en castellano. Todos los derechos reservados.
Formulario de Contacto - Datos legales - Publicidad

Hospedaje web y servidores dedicados linux por Ferca Network