Está en la página 1de 82

VISUAL PROLOG

Entorno de desarrollo

1 Secciones de un programa en Visual Prolog


1.1 Directivas de compilacin
1.2 Seccin de constantes
1.3 Seccin de dominios
1.3.1 Dominios de Objetos Compuestos
1.3.2 Dominios de Objetos Compuestos Functorless
1.3.3 Sinnimos de Dominios Estndar
1.3.4 Dominios tipo Lista
1.3.5 Dominios tipo Predicado
1.4 Seccin de la base de datos
1.4.1 Predicados definidos en Visual Prolog para manejar
la base de datos
1.5 Seccin de definicin de predicados
1.5.1 Tipos de predicados
1.5.2 Ejemplos de cmo conseguir la coherencia entre
reglas y predicados en el aspecto determinista
1.6 Seccin de clusulas
1.7 Seccin de meta u objetivo
1.8 Ejemplo
2 El entorno de desarrollo de Visual Prolog

2.1 Aplicaciones orientadas a eventos


2.2 Aplicaciones orientadas a eventos en Visual Prolog
2.2.1 Tipos de ventanas en Visual Prolog
2.2.2 El dilogo Experto del entorno de desarrollo VPI
2.2.3 El primer programa VPI

Secciones de un programa en Visual Prolog


Un programa en Visual Prolog est compuesto de varias secciones que se
describen a continuacin:
Directivas de compilacin: que se dan al comienzo del
programa.
Seccin de constantes: puede contener cero, una o varias
constantes.
Seccin de dominios: puede contener cero, uno o varios
dominios.
Seccin de la base de datos: puede contener cero, uno o
varios predicados de la base de datos.
Seccin de predicados: puede contener cero, una o varias
declaraciones de predicados.
Seccin de clusulas: puede contener cero, una o varias
clusulas.
Seccin de meta: para que el programa se ejecute de
forma independiente debe existir una meta construida
dentro del propio programa.
[NDICE]

Directivas de compilacin
Nos permiten controlar las caractersticas del compilador. Estas directivas pueden
ser cambiadas a travs del men, mediante opciones de lnea de comando y en el
propio cdigo fuente. En caso de activar una misma directiva de forma distinta en
el entorno y en el cdigo fuente, prevalece la activacin realizada en el cdigo
fuente. Ver Tabla 1
Directiva

Significado

bgidriver

Esta directiva se utiliza de un modo similar a este ejemplo: bgidriver


"_CGA_driver_far", para establecer el tipo de controlador de grficos que se
debe linkar con un programa MS-DOS de grficos BGI.

bgifont

Esta directiva se utiliza de un modo similar a este ejemplo: bgifont


"_gothic_font_far", para establecer el tipo de fuente de texto que se debe utilizar
con el programa a la hora de escribir un programa para MS-DOS basado en
grficos BGI.
Esta directiva activa la deteccin de clusulas no deterministas. Si
especificamos esta directiva, Visual Prolog dar un warning cada vez que se
detecte un predicado de tipo no determinista. Hay dos tipos de clusulas no
deterministas:

check_determ

Aquellas que no poseen corte y hay una o ms clusulas que pueden


casar con los mismos argumentos de entrada para un patrn de flujo.

Aquellas que llaman a otras no deterministas y el predicado llamado no


est seguido de un corte.

code

Especifica el tamao del array interno de cdigo. Por defecto son 2000 prrafos
(unidades de 16 bits), para la versin VP de 16 bits. En otro caso, son 10000.
Por ejemplo si escribimos code=1024 tenemos un array de cdigo de 16 * 1024
bytes=16Kbytes de tamao.

config

Permite definir el aspecto de los programas en modo texto en MS-DOS antiguo.

diagnostics

Permite observar los un conjunto de parmetros de un programa Prolog.

error

Produce mensajes de error en tiempo de compilacin. Cuando se encuentra un


error de este tipo al llegar a la lnea de la directiva, se visualiza en pantalla el
mensaje escrito al lado de #error. Es muy til para encontrar inconsistencias
debidas al programador y violacin de restricciones impuestas.

errorlevel

Permite establecer el grado de detalle con que VP informa de los errores al

programador. Puede ser 0, 1 2.

heap

Sirve para especificar la cantidad de memoria que se reservar para un


ejecutable TSR en MS-DOS.

gstacksize

Se debe escribir en la seccin MAIN para que sea tenida en cuenta y permite
establecer el nmero de bytes de la pila global (cantidad de memoria virtual que
el sistema operativo debe reservar), mientras el programa est cargado.

nobreak

En ausencia de esta directiva cada vez que se realice una llamada a un


predicado, se examinar el teclado para ver si se ha pulsado ctrl-break, por lo
que se ralentiza la ejecucin de la aplicacin y, adems, ocupa un pequeo
espacio de programa. El uso de la directiva evita que se genere este cdigo
examinador. Cuando se utiliza esta directiva, la nica forma de salir de un bucle
infinito es mediante un proceso de reset.

nowarnings

Suprime los avisos generados por la existencia de una variable una sola vez en
una clusula. Estas variables pueden ser sustituidas por variables annimas,
luego, en principio, no deben aparecer en un programa bien escrito.

printermenu

Permite la generacin de cdigo en programas MS-DOS que facilita la


impresin de pantallas en modo texto, mediante la pulsacin del conjunto Alt-p

project

Se usa cuando utilizamos una metodologa de diseo e implementacin


modular. Permite especificar a qu proyecto pertenece un mdulo determinado.
Tabla 1

[NDICE]

Seccin de constantes
En la seccin de constantes podemos declarar constantes simblicas que pueden
usarse en el cuerpo del programa. La utilidad de las constantes en Visual Prolog
es similar a la que estos elementos tienen en otros lenguajes de programacin,
normalmente, sirven para facilitar el uso de diversas cantidades, expresiones y
smbolos.
La definicin de la seccin de constantes se encabeza con la palabra
reservada CONSTANTS, y cada lnea de definicin es de la forma <Nombre
Constante> = <Definicin de Macro>.
Por ejemplo, el siguiente fragmento de programa visualiza en pantalla el
contenido:

12
A=1, B=2
1 Solution
CONSTANTS
numero=1
expresion=1+1
GOAL
A=numero,B=expresion,write(A),write(B),nl.

Las restricciones que se imponen en el uso de constantes se exponen a


continuacin:
El sistema no distingue entre maysculas y minsculas.
La definicin de una constante no puede referirse a s
misma, es decir, no es posible construir definiciones
recursivas de constantes.
Puede haber varias secciones CONSTANTS a lo largo del
programa, y toda constante debe ser definida antes de ser
utilizada.
Las constantes declaradas son efectivas desde el punto en
que son declaradas hasta el final del fichero fuente donde
han sido definidas y en algunos ficheros incluidos tras la
declaracin.
Las constantes slo se pueden declarar una vez.
[NDICE]

Seccin de dominios
En la seccin DOMAINS se pueden definir dominios no especificados por
defecto por Visual Prolog. Por ejemplo, el dominio integer es estndar para el
compilador, no as el dominio sinnimo ENTERO o dominios complejos. En
estos ltimos casos, el programador debe definirlo en esta seccin.

Cada seccin de dominios debe comenzar con la palabra DOMAINS. Ejemplo:


DOMAINS
ENTERO=INTEGER

Es posible usar 5 formatos de declaraciones para dominios definidos por el


usuario.
[NDICE]

Dominios de Objetos Compuestos


El formato es como sigue:
dominio = [reference] [align {byte|word|dword}] declaracion1;
[declaracion2];...
dominio: nombre dado al dominio especificado por el
usuario.
declaracion1; [declaracion2]: declaracin de objetos
compuestos alternativos que tienen que tener la forma
siguiente: functor([sub_1 [, sub_2, ...] ]) donde
o functor es el nombre del objeto compuesto
alternativo.
o sub_1 [,sub_2, ...] son subcomponentes del objeto
compuesto que deben tener su correspondiente
nombre y dominio. Este ltimo puede ser estndar o
definido por el usuario.
reference: indica la declaracin de un dominio de
referencia. En este tipo de dominios los argumentos de
entrada pueden ser variables libres.
align: indica el tipo de distribucin de memoria que se va a
usar.
Ejemplo:
DOMAINS

LECTOR=lee(SYMBOLNombre,LECTURAItem)
LECTURA=libro(SYMBOLAutor,SYMBOLTitulo,SYMBOLEditorial);
revista(SYMBOLTitulo,INTEGERNumero)

Los nombres colocados al lado de cada dominio en los subcomponentes de la


definicin de los dominios del ejemplo son opcionales y pueden omitirse, ya que
slo sirven para aumentar la legibilidad del programa.
El smbolo ";" indica que el dominio LECTURA puede referirse tanto
a libros como a revistas, es decir, tanto los objetos libros como los
objetos revistas pertenecen al dominio LECTURA.
El siguiente programa lista lo que cada lector lee en las
variables X e Y respectivamente.
DOMAINS
LECTOR=lee(SYMBOLNombre,LECTURAItem)
LECTURA=libro(SYMBOLAutor,SYMBOLTitulo,SYMBOLEditorial);
revista(SYMBOLTitulo,INTEGERNumero)
PREDICATES
lectores(LECTOR)
CLAUSES
lectores(lee(antonio,libro(cervantes,quijote,anaya))).
lectores(lee(pepe,revista(hola,22))).
lectores(lee(juan,libro(delphi4,alvarez,anaya))).
GOAL
lectores(lee(X,Y)).

El resultado obtenido tras la ejecucin del objetivo propuesto en la seccin de


metas es:
X=antonio, Y=libro("cervantes","quijote","anaya")
X=pepe, Y=revista("hola",22)
X=juan, Y=libro("delphi4","alvarez","anaya")

3 Solutions
[NDICE]

Dominios de Objetos Compuestos Functorless


En estos dominios podemos definir tipos de objetos que slo se pueden
comportar como una nica clase de objetos. Mientras que en el caso anterior un
determinado dominio poda definir un objeto u otro, en el caso de dominios de
objetos Functorless dicho dominio slo puede definir un objeto compuesto. La
sintaxis de este tipo de dominios es similar a la anterior salvo porque es necesario
especificar la palabrastruct y no puede haber ms de una definicin de objeto por
dominio.
dominio = struct [align {byte|word|dword}] declaracion
Con este tipo de declaracin los objetos utilizado mantienen una sintaxis muy
parecida a la de C.
Ejemplo:
DOMAINS
ESCULT=structescultura(INTEGERns,SYMBOLautor,SYMBOLmaterial)
PINTURA=structcuadro(INTEGERns,SYMBOLautor,SYMBOLtecnica)

[NDICE]

Sinnimos de Dominios Estndar


En ocasiones, puede ser til definir sinnimos de dominios que son estndar, para
una mayor legibilidad del programa, por ejemplo. As pues en la siguiente
declaracin:
DOMAINS
ENTERO=integer
ESCULT=structescultura(ENTEROns,SYMBOLautor,SYMBOLmaterial)
PINTURA=structcuadro(ENTEROns,SYMBOLautor,SYMBOLtecnica)

ENTERO no es ms que un sinnimo de integer que puede ser usado del mismo
modo que este ltimo.

[NDICE]

Dominios tipo Lista


Las listas son estructuras comunes de datos en Prolog consideradas como una
forma de objeto compuesto. Son secuencias de elementos generalmente
homogneos. Sin embargo, en Visual Prolog es fcil crear listas heterogneas
mediante el uso eficaz de declaracin de dominios.
La sintaxis para crear una lista de objetos es del modo:
dominiolista = dominiocomponentes*
Si dominiocomponentes define varios objetos distintos, la lista definida ser
heterognea o polimrfica.
Veamos varios ejemplo de listas homogneas:
DOMAINS
listaenteros=integer*/*Listadeenteros*/
listacaracteres=char*/*Listadecaracteres*/
listacuadros=cuadro*/*Listadeestructurasdeldominiocuadro*/

Veamos ahora un ejemplo de lista polimrfica que puede almacenar tanto


estructuras tipo cuadro como estructuras tipo escultura:
DOMAINS
objetos=escultura(ENTEROns,SYMBOLautor,SYMBOLmaterial);
cuadro(ENTEROns,SYMBOLautor,SYMBOLtecnica)
/*Losobjetospuedenseresculturasocuadros*/
listapolim=objetos*/*Estoesunalistadeobjetos*/

[NDICE]

Dominios tipo Predicado


Un dominio predicado (dominio puntero a predicado), permite la declaracin de
un grupo o una clase de predicados. La sintaxis es como sigue:

PredicadoDom = TipoPredicado [Retorno] (ListaArg) [- [[TipoPredicado]


patron]] [lenguaje]
donde:
PredicadoDom es el nombre del dominio.
TipoPredicado es de la forma {procedure | determ |
nondeterm | failure | erroneous | multi}, estos son los tipos
de predicados que pueden existir.
Retorno es el dominio al que pertenecen los datos de
retorno cuando el predicado es una funcin.
ListaArg es la lista de argumentos del predicado que son
objetos con sus correspondientes dominios.
patron (de flujo) define como se van a usar los
argumentos, si son de entrada (i), o de salida (o), o de
entrada-salida (i|o).
lenguaje define el tipo de lenguaje que ha sido usado para
definir un tipo de predicado. Puede ser: language{ asm | c |
pascal | prolog | stdcall | syscall }.
Ejemplo:
DOMAINS
par=pares(INTEGER,INTEGER)
listapares=par*
listaenteros=integer*
unaria=determINTEGER(INTEGER)(i)
PREDICATES
predicadosuma(par,INTEGER)
cubo:unaria
cuadrado:unaria
operacion(listapares,unaria,listaenteros)

CLAUSES
cubo(E,ECubo):ECubo=E*E*E.
cuadrado(E,ECuadrado):ECuadrado=E*E.
predicadosuma(pares(E1,E2),Suma):Suma=E1+E2.
/**/
operacion([],_,[]).
operacion([X|Y],OperacionUnaria,LRes):predicadosuma(X,S),
Res=OperacionUnaria(S),
operacion(Y,OperacionUnaria,Aux),
LRes=[Res|LAux].
GOAL
operacion([pares(3,2),
pares(2,1),pares(3,4)],cuadrado,ListaCuadrados),
operacion([pares(3,2),
pares(2,1),pares(3,4)],cubo,ListaCubos).

Vamos a explicar detalladamente cmo funciona el ejemplo propuesto para


ilustrar el uso de la seccin DOMAINS.
El predicado principal se denomina operacion y admite como argumentos una
lista de predicados del dominio listapares, un predicado del
dominio OperacionUnaria y una lista de enteros. Es interesante notar que en
Visual Prolog podemos pasar como argumentos de nuestros predicados, no slo
datos y objetos compuestos sino tambin predicados y funciones que realizan
diversas operaciones. De este modo, el predicado operacion recorre cada par de
la lista, suma los nmeros que componen dicho par y les aplica el predicado
(operacin unaria), pasado por parmetro, as el mismo
predicado operacion sirve para calcular cuadrados, cubos, etc., sobre la suma de
los pares de la lista original.
Como vemos unaria = determ INTEGER (INTEGER) - (i) es la definicin de un
dominio al que pertenecen todos los predicados que tengan esa forma. Cualquier
predicado que realiza una operacin unaria de este tipo encaja en ese dominio.

As pues en el ejemplo tenemos definidos los predicados cuadrado y cubo como


del dominio unaria.
En la seccin CLAUSES se define exactamente el cuerpo de ambos predicados
que este caso actan como funciones.
Para la meta especificada, el resultado de la ejecucin es el siguiente:
ListaCuadrados=[25,9,49], ListaCubos=[125,27,343]
1 Solution
[NDICE]

Seccin de la base de datos


Como sabemos un programa en Visual Prolog no es ms que un conjunto de
hechos y reglas. En ocasiones, podemos querer actualizar este conjunto de
hechos mientras el programa se ejecuta. En tal caso, los hechos deben tratarse
como un conjunto dinmico de datos que pertenecen a una base que puede ser
actualizada y modificada convenientemente mientras dura la ejecucin del
programa.
Slo los hechos que se declaran en la seccin FACTS sern dinmicos y podrn
ser actualizados en tiempo de ejecucin.
La seccin FACTS (tambin llamada DATABASE) tiene la siguiente forma:
[GLOBAL] {FACTS | DATABASE} [- nombre de la base de datos]
[nocopy][{nondeterm|determ|single}] hecho_1[([Lista_Args_hecho_1])]
...
[nocopy][{single|determ|nondeterm}] hecho_N[([Lista_Args_hecho_N])]
...
donde:
GLOBAL: determina si esta seccin es o no de mbito
global a todo el proyecto.

nocopy: determina que los datos que se van a enlazar o


unificar con una variable al hacer una llamada al hecho no
se almacenarn temporalmente en la pila global del
programa.
nodeterm: determina que pueden existir varias instancias
para el hecho.
determ: determina que slo puede existir una instancia
para el hecho en el mismo momento.
single: determina que slo puede existir una y slo una
instancia para el hecho.
[NDICE]

Predicados definidos en Visual Prolog para manejar la base de


datos
assert(<Dominio del hecho> Hecho) - (i): Inserta un hecho
tras otros encontrados pertenecientes al mismo predicado
en la base de hechos. Si se trata de un hecho single lo
sustituye. Este predicado nunca falla.
assert(<De correspondientes dominios del hecho> Hecho,
NombreSeccionHechos) - (i,i): Inserta un hecho tras otros
encontrados pertenecientes al mismo predicado en la base
de hechos con el nombre especificado
en NombreSeccionHechos. El hecho debe ser un trmino
perteneciente al dominio de la seccin de hechos dados
en NombreSeccionHechos. Este predicado nunca falla.
asserta(<Dominio del hecho> Hecho) - (i): ): Inserta un
hecho delante de otros encontrados pertenecientes al
mismo predicado en la base de hechos. Este predicado
nunca falla.
asserta(<De correspondientes dominios del hecho>
Hecho, NombreSeccionHechos) - (i,i): Inserta un hecho
delante de otros encontrados pertenecientes al mismo
predicado en la base de hechos con el nombre especificado

en NombreSeccionHechos. El hecho debe ser un trmino


perteneciente al dominio de la seccin de hechos dados
en NombreSeccionHechos. Este predicado nunca falla.
assertz(<Dominio del hecho> Hecho) - (i): Como assert/1.
Este predicado nunca falla.
assertz(<De correspondientes dominios del hecho> Hecho,
NombreSeccionHechos) - (i,i): Como assert/2. Este
predicado nunca falla.
consult(STRING OSNombreFichero) - (i): Sirve para leer
hechos desde un fichero de hechos y almacenarlos en la
base de hechos. Este fichero debe haber sido salvado
con save.
consult(STRING OSNombreFichero, NombreSeccionHechos)
- (i,i): Sirve para leer hechos desde un fichero de hechos y
almacenarlos en la base de hechos de
nombre NombreSeccionHechos. Este fichero debe haber
sido salvado con save.
save(STRING OSNombreFichero) - (i): Sirve para salvar los
hechos de la seccin de hechos sin nombre en un fichero
de texto.
save(STRING OSNombreFichero, NombreSeccionHechos) (i,i): Sirve para salvar los hechos de una seccin de hechos
con nombre NombreSeccionHechos en un fichero de texto.
nondeterm retract(<Dominio del hecho> Hecho): Borra el
primer hecho que encuentre que case con el hecho
especificado en el argumento. Falla cuando no hay ms
hechos que borrar.
nondeterm retract(<De correspondientes dominios del
hecho> Hecho, NombreSeccionHechos) - (i,i): Borra el
primer hecho que encuentre que case con el hecho
especificado en el argumento. Acta sobre del dominio de
hechos con nombre NombreSeccionHechos. Falla cuando
no hay ms hechos que borrar.

determ retractall(<Dominio del hecho> Hecho) - (i): Borra


el todos los hechos encontrados que casen con el hecho
especificado en el argumento. Nunca falla.
determ retractall(<De correspondientes dominios del
hecho> Hecho, NombreSeccionHechos ) - (i,i): Borra todos
los hechos encontrados que casen con el hecho
especificado en el argumento. Acta sobre del dominio de
hechos con nombre NombreSeccionHechos.
Veamos ahora algunos ejemplos de uso de los predicados mostrados para manejar
la base de hechos.
FACTS
padre(string,string)
PREDICATES
abuelo(string,string)
CLAUSES
padre(juan,pepe).
padre(juan,luis).
padre(pepe,manolo).
abuelo(X,Y):padre(X,Z),padre(Z,Y).
GOAL
assert(padre(pepe,beatriz)),
assertz(padre(pepe,carlos)),
asserta(padre(pepe,maria)),
abuelo(juan,Y).

Tenemos 3 hechos que definen quin es padre de quin y un predicado para


deducir el parentesco abuelo.
Tras la ejecucin de la meta obtenemos el siguiente resultado:
Y=maria

Y=manolo
Y=beatriz
Y=carlos
4 Solutions

Si examinamos paso a paso esta ejecucin, lo que ha sucedido ha sido lo


siguiente:
Tras el primer assert hemos insertado el hecho padre(pepe,
beatriz) tras padre(pepe, manolo).
El predicado assertz funciona como assert, luego hemos
insertado el hecho padre(pepe, carlos) tras el
hecho padre(pepe, beatriz).
Por ltimo asserta inserta al principio, luego el
hecho padre(pepe, maria) ha quedado colocado el primero.
Veamos ahora un ejemplo del uso de retract y retractall.
FACTS
padre(string,string)
PREDICATES
abuelo(string,string)
CLAUSES
padre(juan,pepe).
padre(juan,luis).
padre(pepe,manolo).
padre(pepe,beatriz).
padre(pepe,carlos).
padre(pepe,maria).
abuelo(X,Y):padre(X,Z),padre(Z,Y).
GOAL

retract(padre(pepe,_)),!,
padre(pepe,L).

En este caso retract borra todas la primera ocurrencia de padre, siempre que su
primer argumento sea pepe.
El corte que va despus de retract sirve para que Visual Prolog no haga
backtracking y borre todas las ocurrencias de padre(pepe, ...), ya que por defecto
el compilador intenta ofrecer todas las posibles soluciones para una meta dada.
Con el corte situado en ese lugar, slo se hace bactracking sobre padre(pepe, L).
El resultado de la ejecucin se muestra a continuacin:
L=beatriz
L=carlos
L=maria

En el ejemplo siguiente, vemos que en lugar de usar retract estamos


usando retractall para borrar todas las ocurrencias de padre(pepe, ...).
FACTS
padre(string,string)
PREDICATES
abuelo(string,string)
CLAUSES
padre(juan,pepe).
padre(juan,luis).
padre(pepe,manolo).
padre(pepe,beatriz).
padre(pepe,carlos).
padre(pepe,maria).
abuelo(X,Y):padre(X,Z),padre(Z,Y).
GOAL
retractall(padre(pepe,_)),

padre(pepe,L).

El resultado de esta ejecucin es:


No Solution

[NDICE]

Seccin de definicin de predicados


En esta seccin se definen los predicados que pueden pertenecer a dominios
definidos en la seccin DOMAINS (punteros a predicados), o se definen los
predicados con una forma determinada en caso de que no los hayamos agrupado
en ningn dominio concreto (todas las reglas de la seccin de clusulas deben
pertenecer a algn predicado). La seccin de definicin de predicados va
precedida siempre de la palabra PREDICATES.
Por ejemplo podemos tener este caso:
DOMAINS
unaria=determINTEGER(INTEGER)(i)
PREDICATES
cubo:unaria
CLAUSES
cubo(E,Res):Res=E*E*E.

O podemos tener este otro:


PREDICATES
cubo(INTEGER,INTEGER)
CLAUSES
cubo(E,Res):Res=E*E*E.

En el primer caso cubo se define como una funcin y debe ser llamada
como A=cubo(3) y en el segundo caso la llamada debe hacerse como cubo(3, A).
Ambas formas de definicin son igualmente correctas y su uso depender de la
aplicacin en cuestin en la que estemos trabajando.

Punteros a predicados: su forma general es como


sigue: Nombre: Dominio del predicado [namespec] donde:
o Nombre: es el nombre del puntero a predicado.
o Dominio del predicado: es el dominio al que
pertenece el predicado y debe declararse en la
seccin DOMAINS.
o [namespec]: puede ser usado para especificar el
nombre de un cdigo objeto pblico en una
declaracin global. Su principal uso se da cuando se
linkan mdulos escritos en otros lenguajes.
Predicados y funciones: su forma general es como
sigue: [TipoPredicado] [DominioRetorno]
NombrePredicado[(ListaArgumentos)] [- [flowpatterns]]
[lenguaje] [namespec] donde:
o [TipoPredicado]: es de la forma {procedure | determ |
nondeterm | failure | erroneous | multi}. Pueden
declararse varios junto con los
distintos flowpatterns seleccionados para el
predicado.
o [DominioRetorno]: es el dominio de retorno si se est
declarando una funcin.
o NombrePredicado: es el nombre del predicado.
o [(ListaArgumentos)]: es la lista de argumentos del
predicado.
o [- [flowpatterns]]: los patrones de flujo indican como
se usa cada argumento de la lista de argumentos.
Utilizaremos i para los argumentos de entrada
y o para los argumentos de salida. Pueden declararse
varios para un mismo predicado.
o [lenguaje]: es de la forma language { asm | c | pascal
| prolog | stdcall | syscall }.

o [namespec]: es usado como en el caso de punteros a


predicados.
[NDICE]

Tipos de predicados
Como hemos visto, pueden existir 6 tipos de predicados en funcin de cmo y
cuantas soluciones pueden aportar y si pueden o no fallar. Cada predicado puede
tener varias clusulas o reglas que lo implementa, por tanto, clusulas y
predicados deben ser coherentes.
Esta coherencia est relacionada con el concepto de determinismo en Visual
Prolog.
La mayora de los lenguajes son deterministas. Esto quiere decir que cualquier
conjunto de datos de entrada conduce a un nico conjunto de instrucciones para
producir un conjunto de datos de salida. Sin embargo, en Visual Prolog se admite
la inferencia no determinista basada en predicados no deterministas.
Visual Prolog ejerce un gran control sobre el determinismo de las reglas y
predicados que aparecen en los programas, principalmente con el objeto de
ahorrar espacio de almacenamiento en tiempo de ejecucin. Cuando una clusula
o regla determinista que compone un predicado termina con xito, el espacio de
pila correspondiente puede ser dispensado rpidamente, liberando de este modo
el espacio ocupado.
El sistema de control del determinismo de Visual Prolog es muy fuerte. De
hecho, el compilador fuerza al programador, a travs de este control, a declarar
en sus predicados 2 aspectos de comportamiento importantes:
Si la llamada a un predicado puede fallar.
Nmero de soluciones que un predicado puede producir.
De acuerdo a estos dos aspectos de determinismo, Visual Prolog soporta los
siguientes tipos de predicados:
erroneous: nunca debe fallar y debe producir 0 soluciones.
failure: puede fallar y debe producir 0 soluciones.

nondeterm: puede fallar y puede producir mltiples


soluciones.
procedure: nunca debe fallar aunque pueden producirse
errores en tiempo de ejecucin y debe producir una nica
solucin.
determ: puede fallar y debe producir una nica solucin, es
decir, no hacen backtracking.
multi: nunca debe fallar y puede producir mltiples
soluciones mediante la tcnica de backtracking.
El sistema de control de determinismo de Visual Prolog chequea la
correspondencia de las definiciones de predicados con los modos de
determinismo declarados para los predicados. Por defecto, el compilador verifica
las clusulas o reglas de predicados y da un warning si no puede garantizar que
un predicado declarado como multi, procedure o erroneous nunca falla.
Todos los predicados se definen internamente con alguno de estos modos. Para
los predicados definidos como determ, procedure, failure o erroneous el
compilador dar un warning para cada clusula o regla del programa que d
como resultado un predicado no determinista.
Hay dos tipos de clusulas no deterministas:
Aquellas que no contienen un corte y hay una o ms
clusulas que pueden casar (o unificarse) con los mismos
argumentos de entrada para ese patrn de flujo de
entrada.
Aquellas que llaman a un predicado no determinista y
dicha llamada no est seguida de un corte. Debido a esto,
el no determinismo puede extenderse por muchos
predicados a menos que se utilicen uno o ms cortes.
Cuando se escriben predicados declarados como multi, procedure o erroneous se
deben seguir un par de reglas:

Si alguna clusula de predicado puede fallar se debe definir


al final una clusula que no falle seguro.
De acuerdo a los dominios declarados, para cualquier
posible conjunto de elementos de entrada debe existir una
clusula que tenga una cabeza que case con dicho
conjunto.
[NDICE]

Ejemplos de cmo conseguir la coherencia entre reglas y


predicados en el aspecto determinista
Como hemos dicho hay dos tipos de clusulas no deterministas: uno de los tipos
son aquellas que no contienen un corte y hay una o ms clusulas que pueden
casar (o unificarse) con los mismos argumentos de entrada para ese patrn de
flujo de entrada. Veamos un ejemplo de predicado definido como determinista
con un conjunto de clusulas que no son deterministas:
DOMAINS
list=integer*
PREDICATES
lista(list)
prueba
CLAUSES
lista([]).
lista([1]).
lista([1,2]):write("Hola").
lista(L):write(L).
prueba:lista([1,2]),
nl,
lista([1,2,3]).
GOAL
prueba.

Como vemos el conjunto de reglas para el predicado lista(list) son todas no


deterministas, ya que no aparece un corte en ellas y hay varias que pueden casar
con el mismo patrn de entrada. Por ejemplo, la lista vaca puede casar
en lista([]) y en lista(L).
Para resolver la incoherencia podemos tomar dos soluciones:
Hacer lista(list) no determinista escribiendo delante la
palabra reservada nondeterm.
Conseguir que cada clusula o regla que compone el
predicado sea determinista y para ello hay que hacer un
uso correcto del corte. Esta segunda solucin es ms
correcta y optimizada en este caso, ya que lo que se
pretende en el ejemplo es que el predicado nos aporte una
nica solucin, es decir no interesa que haga backtracking
ni siquiera forzado.
Vamos a suponer que forzamos el fallo tal y como tenemos actualmente escrito el
programa, para ello la nica variacin que hay que hacer es la siguiente:
prueba:lista([1,2]),
nl,
lista([1,2,3]),
fail.

La ejecucin del programa produce el siguiente resultado:


Hola
[1,2,3][1,2]
[1,2,3]

Veamos el rbol de ejecucin que se ha generado en la Figura 1:

Figura 1
rbol de ejecucin

Nos interesa que el programa aporte una nica solucin y no un conjunto de


ellas, incluso si intentamos hacer backtracking de un modo forzado. El corte nos
proporciona capacidad para podar el rbol de ejecucin, por tanto, hemos de
poner tantos cortes como se requieran para conseguir que el programa definido
por el conjunto de reglas aporte una solucin nica en cualquier caso.
La modificacin realizada, la ejecucin del programa y el rbol de ejecucin se
presentan a continuacin, ver Figura 2:
lista([]):!.
lista([1]):!.
lista([1,2]):write("Hola"),!.
lista(L):write(L).

Hola
[1,2,3]

Figura 2
rbol de ejecucin
[NDICE]

Seccin de clusulas
La seccin de clusulas contiene la especificacin o implementacin del conjunto
de hechos y reglas que componen el programa. Dicha seccin se encabeza con la
palabra CLAUSES.
Una clusula puede ser:
Un hecho: por ejemplo padre(juan, maria).
Una regla de deduccin: por ejemplo abuelo(X, Y):-padre(X,
Z), padre(Z, Y). Como se observa la regla de deduccin se
puede interpretar del modo siguiente, la parte izquierda es
cierta si la parte derecha de la regla es cierta. Para ello
deben ser ciertas todas las clusulas separadas por
conjunciones "," o, al menos, una de las que estn
separadas por disyunciones ";". Si una parte de la regla

falla, se intenta hacer backtracking con la inmediatamente


anterior, y si esta es la parte izquierda de la clusula con la
clusula siguiente en caso de que exista.
Una secuencia de clusulas que definen un predicado se denomina
procedimiento.
[NDICE]

Seccin de meta u objetivo


En esta seccin se coloca la meta u objetivo que deseamos que Prolog satisfaga.
Es similar a cualquier otra regla, ya que la meta est compuesta de un conjunto
de submetas que hay que demostrar, la principal diferencia reside en que detrs
de la palabra GOAL no se pone ":-", es decir no existe parte izquierda de la regla,
y sta se ejecuta directamente cuando arranca el programa.
[NDICE]

Ejemplo
[CDIGO FUENTE] [EJECUTABLE]

Vamos a ver un ejemplo completo de cmo realizar un programa en Visual


Prolog haciendo uso de todas las secciones que hemos visto.
El programa debe gestionar una lista polimrfica de obras de arte. Las obras de
arte pueden ser cuadros o esculturas. Los datos que se deben almacenar en un
cuadro son el nmero de serie, el autor, el estilo y las dimensiones. Los datos que
se deben almacenar en una escultura son el nmero de serie, el autor y el
material.
El programa permitir insertar en orden las obras y visualizar listados de
cuadros y esculturas de forma separada.
Comencemos, pues a examinar el cdigo construido.
DOMAINS
obra=cuadro(INTEGER,STRING,STRING,STRING);
escultura(INTEGER,STRING,STRING)
LIST=obra*

En la seccin DOMAINS definimos el dominio obra, que agrupar dos tipos de


objetos compuestos: cuadros o esculturas.
El dominio LIST define el tipo lista polimrfica de obras de arte.
Grficamente tenemos:

PREDICATES
obtenerNS(INTEGER,obra)
insorden(obra,LIST,LIST)
pedirdatoscuadro(STRING,STRING)
pedirdatosescultura(STRING)
insertar(LIST,LIST,CHAR,INTEGER,STRING)
inserta(LIST,LIST)
eligeobra(CHAR,INTEGER,STRING)
escribircuadro(obra)
escribirescultura(obra)
nondetermrecorrerlista(LIST,SYMBOL)
nondetermejecutaropcion(INTEGER,LIST,LIST)
programa(LIST)

menu(INTEGER)

En la seccin PREDICATES hemos definido el nombre y el tipo de los


argumentos de todos los predicados que se usarn durante el programa.
En la seccin CLAUSES tenemos el conjunto de reglas o clusulas que
implementan cada predicado.
Vamos a describir brevemente lo que hace cada regla.
CLAUSES
obtenerNS(Serie,Predicado):Predicado=cuadro(Serie,_,_,_),!.
obtenerNS(Serie,Predicado):Predicado=escultura(Serie,_,_).

La regla obtenerNS tiene dos parmetros: un INTEGER y una obra. El segundo


parmetro es de entrada y el primer parmetro es de salida. Cuando unificamos la
variable Predicado que tras la llamada a la regla estar instanciada, sta
almacenar o un cuadro o una escultura. Si almacena un cuadro la
comparacin Predicado=cuadro(Serie,_,_,_) ser cierta y la variable Serie se
instanciar con el valor del nmero de serie del cuadro. Si almacena una
escultura, la primera regla fallar y pasaremos a comparar el Predicado con el
objeto escultura(Serie,_,_). La unificacin ser posible ya que si no es un cuadro
es una escultura y en este caso estaremos obteniendo el nmero de serie de una
escultura.
insorden(E,[],[E]):!.
insorden(E,[X|Y],[X|Cola]):obtenerNS(Serie1,E),
obtenerNS(Serie2,X),
Serie1>Serie2,
insorden(E,Y,Cola),!.
insorden(E,LOr,[E|LOr]).

El predicado insorden admite tres parmetros: un elemento de entrada de


tipo obra y otro de tipo LIST y por ltimo un elemento de salida tambin de
tipo LIST.
El predicado est implementado mediante tres reglas:

La primera regla satisface los objetivos en los que se


pretenda insertar un elemento en una lista vaca.
La segunda regla satisface los objetivos en los que se
pretenda insertar un elemento que es mayor que el que
est a la cabeza de la lista en ese instante. En este caso es
necesario seguir recorriendo la lista mediante una llamada
recursiva para insertar el elemento en la posicin correcta.
La tercera regla satisface los objetivos en los que se
pretenda insertar un elemento inmediatamente porque ya
se ha encontrado el lugar adecuado para el mismo.
pedirdatoscuadro(Estilo,Dimensiones):nl,write("Estilo:"),
readln(Estilo),
write("Dimensiones:"),
readln(Dimensiones).

El predicado pedirdatoscuadro acepta dos parmetros de salida: el estilo y las


dimensiones del cuadro. La regla que lo implementa simplemente rellena las
variables con los contenidos capturados a travs del teclado.
pedirdatosescultura(Material):nl,write("Material:"),
readln(Material).

El predicado pedirdatosescultura acepta un parmetro de salida: material de la


escultura. La regla que lo implementa simplemente rellena la variable con el
contenido capturado a travs del teclado.
insertar(L,NuevaL,Seleccion,NS,Autor):Seleccion='c',
pedirdatoscuadro(Estilo,Dimensiones),
Registro=cuadro(NS,Autor,Estilo,Dimensiones),
insorden(Registro,L,NuevaL),!.
insertar(L,NuevaL,Seleccion,NS,Autor):Seleccion='e',
pedirdatosescultura(Material),
Registro=escultura(NS,Autor,Material),
insorden(Registro,L,NuevaL).

El predicado insertar acepta cinco parmetros, todos de entrada


salvo NuevaL que es de salida. Las reglas que implementan este predicado
funcionan de modo similar. Si el parmetro Seleccion contiene el carcter "c" en
el objetivo propuesto, ejecutaremos la primera regla, de modo que estaremos
insertando un cuadro. Si el parmetro Seleccion contiene el carcter "e",
ejecutaremos la segunda regla, de modo que estaremos insertando una escultura
en la lista NuevaL.
eligeobra(Seleccion,NS,Autor):write("EscribeelNmerodeSerie:"),
readint(NS),
write("EscribeelNombredelAutor:"),
readln(Autor),
write("Selecciona[c]=Cuadroo[e]=Escultura>"),
readchar(Seleccion).

El predicado eligeobra acepta tres parmetros de salida. En la regla que lo


implementa las variables se rellenan con los contenidos obtenidos a travs del
teclado.
inserta(L,NuevaL):eligeobra(Seleccion,NS,Autor),
insertar(L,NuevaL,Seleccion,NS,Autor).

El predicado inserta acepta dos parmetros de tipo LIST, el primero de entrada y


el segundo de salida. La regla que lo implementa se satisface mediante la
resolucin de la regla eligeobra y posteriormente con una llamada a insertar con
los resultados obtenidos de la resolucin de la regla precedente.
escribircuadro(cuadro(NS,Autor,Estilo,Dimensiones)):
write("ObradeArte=>CUADRO"),nl,
write("NmerodeSerie:"),Aux1=NS,write(Aux1),nl,
write("Autor:"),Aux2=Autor,write(Aux2),nl,
write("Estilo:"),Aux3=Estilo,write(Aux3),nl,
write("Dimensiones:"),Aux4=Dimensiones,write(Aux4),nl,
write(""),nl,
write("Pulsaparacontinuar..."),

readint(_).

El predicado escribecuadro acepta por parmetro un elemento de tipo obra, luego


la regla que lo implementa acepta como parmetro un objeto compuesto de
tipo cuadro que est englobado dentro del dominio obra. Esta regla simplemente
actualiza los parmetros del objeto compuesto con los contenidos obtenidos
desde teclado.
escribirescultura(escultura(NS,Autor,Material)):
write("ObradeArte=>ESCULTURA"),nl,
write("NmerodeSerie:"),Aux1=NS,write(Aux1),nl,
write("Autor:"),Aux2=Autor,write(Aux2),nl,
write("Material:"),Aux3=Material,write(Aux3),nl,
write(""),nl,
write("Pulsaparacontinuar..."),
readint(_).

El predicado escribeescultura acepta por parmetro un elemento de tipo obra,


luego la regla que lo implementa acepta como parmetro un objeto compuesto de
tipo escultura que est englobado dentro del dominio obra. Esta regla
simplemente actualiza los parmetros del objeto compuesto con los contenidos
obtenidos desde teclado, como en el caso anterior.
recorrerlista([],_):!.
recorrerlista([X|Y],Que):Que=cu,
escribircuadro(X),
recorrerlista(Y,Que),!.
recorrerlista([X|Y],Que):Que=es,
escribirescultura(X),
recorrerlista(Y,Que),!.
recorrerlista([_|Y],Que):recorrerlista(Y,Que).

El predicado recorrerlista acepta dos parmetros de entrada. Est implementado


mediante cuatro reglas:

La primera satisface el objetivo en el que la lista a recorrer


est vaca.
La segunda y tercera regla satisfacen objetivos en los que
el parmetro Que decide que tipo de obra de arte hay que
visualizar, bien un cuadro o bien una escultura.
La cuarta regla satisface objetivos en los que no hemos de
visualizar el elemento cabeza de la lista en ese instante
porque no coincide con el tipo de elemento que deseamos
mostrar.
ejecutaropcion(0,L,L):recorrerlista(L,cu),!.
ejecutaropcion(1,L,L):recorrerlista(L,es),!.
ejecutaropcion(2,L,NuevaL):inserta(L,NuevaL).

El predicado ejecutaropcion admite 3 parmetros, de los cuales los dos primeros


son de entrada y el ltimo de salida. Tres posibles reglas implementan el
predicado:
La primera se satisface cuando el usuario selecciona la
opcin 0 a travs del men. Eso significa que hay que
visualizar todos los cuadros de la lista.
La segunda se satisface cuando el usuario selecciona la
opcin 1 a travs del men. En este caso hay que mostrar
todas las esculturas.
La tercera regla es satisfecha cuando el usuario selecciona
la opcin 2, y permite insertar un nuevo elemento en la
lista mediante una llamada al predicado inserta.
menu(Opcion):write("MENU"),nl,
write("0.ListadodeCuadros"),nl,
write("1.ListadodeEsculturas"),nl,
write("2.Insertarelementos"),nl,
write("3.Salir"),nl,
write(""),nl,

write("Opcin:"),
readint(Opcion),
write(""),nl.

El predicado menu acepta un parmetro de salida. La regla que lo implementa


muestra al usuario el conjunto de posibles opciones y almacena en la
variable Opcion el contenido seleccionado a travs de teclado.
programa(L):menu(Opcion),
Opcion<>3,
ejecutaropcion(Opcion,L,NuevaL),!,
programa(NuevaL),!.
programa(_):write("Hastapronto..."),nl.

El predicado programa admite como parmetro de entrada una lista de obras de


arte. Est implementado mediante dos reglas:
La primera que presenta el men de opciones y comprueba
si se ha seleccionado la opcin 3. En ese caso falla y pasa a
satisfacer la segunda regla que implementa este
predicado. Si la opcin seleccionada no es la 3, se llama al
predicado ejecutaropcion para tratar la lista, y por ltimo
se hace una llamada recursiva a programa para que esta
vez acte sobre la nueva lista obtenida.
La segunda regla implementa lo que debe satisfacerse en
caso de que el usuario haya elegido la opcin de salir de la
aplicacin.
GOAL
programa([]).

La meta definida es una llamada a programa pasndole por parmetro una lista
vaca, esta llamada se unificar con la primera regla del predicado programa y
dispondremos ya de la variable local L iniciada para comenzar a trabajar con
nuestra lista de obras de arte.
[NDICE]

El entorno de desarrollo de Visual Prolog


El entorno de desarrollo de Visual Prolog nos proporciona la capacidad de
generar aplicaciones lgicas orientadas a eventos para Windows 95 y 98 de forma
sencilla. Disponemos de capacidades de creacin de programas de forma visual y
esto implica que el cdigo que implementa la interfaz de usuario sea generado en
su mayor parte por el propio Experto del entorno de desarrollo.
De lo que se tiene que encargar el programador, por tanto, es de especificar las
tareas que se deben llevar a cabo como respuesta a los sucesos o eventos que se
producen en el sistema.
Antes de profundizar en el estudio de este entorno, demos un repaso breve a los
conceptos sobre los que se apoya la programacin orientada a eventos.
[NDICE]

Aplicaciones orientadas a eventos


En una aplicacin DOS, el programador fija la secuencia de operaciones en
tiempo de diseo. No existe apenas interaccin entre la aplicacin diseada y
otras aplicaciones y el sistema operativo no produce interferencias.
Las aplicaciones DOS suelen comunicarse directamente con el usuario y se basan
en una filosofa de implementacin esttica.
Los sistemas Windows, en cambio, soportan una filosofa dinmica. En estos
casos, el sistema operativo provee a las aplicaciones de una capa de servicios
para su comunicacin con el usuario, de este modo el sistema operativo se
convierte en un objeto activo que el programador debe conocer ya que participa
en la ejecucin y secuenciacin de las aplicaciones dentro de un mbito
multitarea. Las aplicaciones deben contemplar esta caracterstica y la
metodologa de construccin de las mismas se denomina diseo orientado a
eventos.
Cuando el usuario realiza una operacin para interactuar con el sistema (pulsar
una tecla, mover el ratn,...), se produce un suceso o evento. Dicho evento es
generado desde el interfaz hardware y el sistema operativo lo traduce a un
mensaje con formato estndar y enva una notificacin de evento al propietario
correcto que generalmente es la ventana activa (la que tiene el foco).

Los eventos pueden llegar a la aplicacin de forma asncrona, por ello es


necesario escribirla cuidadosamente, notando en cada momento que nos
movemos en un entorno multitarea donde el resto de aplicaciones y el sistema
operativo son objetos plenamente activos, para conseguir que se mantenga la
integridad tanto de procesos como de datos.
Para cada evento debe existir un manejador de evento, que contiene el cdigo que
se ha de ejecutar tras producirse el suceso al que se encuentra vinculado.
Cuando el programador escribe el programa asocia un manejador a cada evento
que desea que se trate. Los manejadores, normalmente, son rutinas con una
cabecera preestablecida y un cuerpo vaco que debe ser rellenado con las
instrucciones apropiadas.
Si el programador no define un manejador propio para un evento determinado,
dicho evento es tratado por defecto por el sistema.
[NDICE]

Aplicaciones orientadas a eventos en Visual Prolog


La interfaz de un programa en Visual Prolog va a ser simplemente un conjunto de
ventanas de aspectos y tipos distintos organizadas mediante una jerarqua.
La ventana principal se denomina ventana de tareas o Task Window.
Cada ventana tiene un nmero que la identifica dentro del sistema, ese nmero se
denomina manejador (handler) de la ventana.
Dado que las ventanas se encuentran organizadas en un sistema jerrquico
podemos hablar de que cada ventana tiene un padre.
Cada ventana lleva asociado un predicado que maneja todos los eventos para la
misma. Dicho predicado pertenece al dominio EHANDLER y tiene dos
argumentos importantes:
El manejador de la ventana: handler.
Un predicado que describe el evento producido, de ahora
en adelante evento.

Adems los predicados del dominio EHANDLER pueden devolver valores a


travs de un parmetro de retorno del dominio LONG que se usan en muy pocos
casos. Normalmente, se devuelve 0.
El entorno de desarrollo de Visual Prolog proporciona un dilogo llamado
Experto a partir del cual se generar parte del cdigo que tiene que ver con la
implementacin de la interfaz de la aplicacin.
Los predicados manejadores de evento para cada ventana deben ser generalmente
declarados y creados a travs del Experto. El programador debe escribir
personalmente el cdigo a incluir en el cuerpo de los manejadores de evento ya
declarados por el Experto para los eventos que desee controlar de forma explcita.
El resto de eventos sern manejados por defecto por el sistema.
[NDICE]

Tipos de ventanas en Visual Prolog


Como hemos comentado anteriormente, la interfaz de una aplicacin no es ms
que un conjunto de ventanas organizadas de modo jerrquico.
Sin embargo, no todas las ventanas tienen la misma finalidad: un botn no es lo
mismo que un dilogo.
Veamos los diferentes tipos de ventanas que existen:
Windows: Existen distintos tipos de ventanas dependiendo del lugar que ocupen
en la jerarqua, Tabla 2.
Tipo

Descripcin

Task Window

Es una abstraccin de la aplicacin en s misma. Es la ventana principal del


programa y la inicializacin y finalizacin de ste estn siempre asociados a
dicha ventana. Bajo el modo MDI (Multiple Document Interface) la ventana
principal acta como contenedor de las ventanas hijas.

Screen Window

Es una abstraccin que representa la pantalla entera. Esta ventana siempre


es el padre de la Task Window.

Top-Level
Window

Se trata de un documento normal de Windows cuyo padre puede ser


la TaskWindow o la Screen Window. Pueden almacenar ventanas hijas y
controles y, a menudo, contienen mens y pueden ser maximizadas y

minimizadas.

Child Windows

Estn restringidas a permanecer dentro del su ventana padre. Cuando la


ventana padre es cerrada, destruida, minimizada, etc., tambin lo son las
ventanas hijas.

Print

Ventana interna usada durante el proceso de impresin

Picture

Ventana interna usada durante el proceso de creacin de un grfico, imagen


o dibujo.

Metafile

Ventana interna usada durante la creacin de un metafile.


Tabla 2

Dialogs: Los dilogos son un tipo especial de ventanas, cuya funcionalidad est
reducida con respecto a las ventanas normales. Los dilogos normalmente se
rellenan con controles, que puede interactuar con el usuario para visualizar
salidas, aceptar entradas, ofrecer mtodos de seleccin de opciones o permitir la
edicin de texto. Los dilogos pueden ser de dos tipos, Tabla 3:
Tipo

Descripcin

Dilogo modal

Hasta que el dilogo no es cerrado no se puede acceder a las ventanas de la


aplicacin que se encuentran debajo de dicho dilogo.

Dilogo no modal

Es posible acceder a lo que est debajo del dilogo antes de haberlo cerrado.
Tabla 3

Controls: Son pequeas ventanas con una apariencia especial y una funcionalidad
fija proporcionada por el sistema operativo. Se usan dentro de conjuntos fijos de
controles dentro de otras ventanas, principalmente como componentes de
dilogos. Los controles proveen al usuario la capacidad de escribir texto, llamar a
comandos o elegir opciones. Los eventos que se generan por la manipulacin de
los controles causan notificaciones de mensajes que se envan al manejador de
eventos de la ventana padre. Existen varios tipos de controles, Tabla 4:
Tipo

Descripcin

PushButton

Botn tpico que puede apretarse y soltarse.

RadioButton

Botn de aspecto redondo que suele estar agrupado con otros de la misma clase
y slo uno de ellos permanece activo simultneamente.

CheckBox

Botn de aspecto cuadrado que puede estar o no marcado.

HScroll

Barra de scroll horizontal.

VScroll

Barra de scroll vertical.

Edit

Cuadro o ventana de edicin de texto.

Text

Etiqueta de texto esttico.

LBox

Lista de opciones o cadenas que pueden ser seleccionadas.

LBoxButton

Lista desplegable de opciones.

LBoxEdit

Lista desplegable de texto que puede editarse.

Icon

Icono.

Custom

Control personalizado.
Tabla 4

Los identificadores de los tipos de ventanas pertenecen al dominio WINTYPE y


tienen w_ delante del nombre especificado para las ventanas, wc_ para los
controles y wd_ para los dilogos.
Cuando se crea cualquier tipo de ventana o dilogo existen varios flags que
determinan la apariencia del dilogo y que permiten conocer el estado del objeto
sobre el que se est actuando.
[NDICE]

El dilogo Experto del entorno de desarrollo VPI


Cuando desarrollamos cualquier aplicacin en Visual Prolog el proceso de
generacin de los ficheros que van a componer el programa se realiza siempre de
un modo similar.

Para ello accedemos a la opcin New Project del men principal Project, ver
Figura 3 .
El dilogo que aparece nos permite configurar el mtodo de desarrollo de nuestra
aplicacin de una forma muy sencilla. Los pasos a seguir son los siguientes:
1. Establecer un nombre para la aplicacin en la caja de
texto Project Name.
2. Seleccionar un directorio base para la aplicacin mediante
la utilizacin de la caja de texto Base Directory.
3. Accionar la pestaa Target. A travs de ella se configura el
tipo de plataforma donde se ejecutar el programa, el tipo
de estrategia de interfaz de usuario que se utilizar, si lo
que se pretende generar es una aplicacin exe o una dll y
por ltimo, seleccionar el lenguaje de programacin que se
usar para generar el programa principal. De no
seleccionar VPI como estrategia de generacin de la
interfaz de usuario las opciones de la pestaa VPI
Options aparecern desactivadas, en caso contrario se
permitir seleccionar el conjunto de paquetes que se
incluirn en la aplicacin para montar la interfaz.
4. Accionar el resto de pestaas para configurar otros objetos
ms avanzados como el tipo de generacin de cdigo, la
inclusin de objetos para manejar bases de datos, la
introduccin de los datos personales del programador y la
colocacin de elementos de ayuda en la aplicacin.

Figura 3
Aspecto del Experto de creacin de una aplicacin

Si se genera una aplicacin sin entorno VPI, el mtodo de programacin no ser


ni visual ni orientado a eventos y deberemos comportarnos como en la escritura
de cualquier aplicacin realizada para DOS.
Vamos a considerar, sin embargo, aplicaciones con entorno VPI por tanto, lo
primero que debemos saber es que VPI integra un conjunto de libreras en
lenguaje Prolog que podemos usar y llamar para utilizar los servicios de interfaz
proporcionados por el sistema Windows. Nos interesa conocer el uso de VPI, no
cmo est construido por dentro.
La arquitectura en la que nos vamos a mover se muestra a continuacin:

Conocemos, hasta ahora, el concepto de programacin orientada a eventos, la


estructuras de Prolog, los tipos de ventanas que ofrece VPI y la arquitectura de
comunicacin entre aplicacin-VPI-Windows. Tambin conocemos como crear
una aplicacin en vaco. Veamos, a continuacin, cmo se utiliza el Dilogo
Experto para colocar, configurar y crear las cabeceras de los manejadores de
evento de los elementos implicados en la interfaz y funcionamiento de la
aplicacin con un ejemplo sencillo.
[NDICE]

El primer programa VPI


[FUENTES EN FORMATO ZIP] [EJECUTABLE EXE]

Nuestro primer programa VPI va a ser el sistema experto de clculo de


velocidades en funcin de las caractersticas de la va y el vehculo que hemos
estudiado en teora. Vamos a especificar, a continuacin, todos los pasos de
diseo e implementacin a realizar.
Nuestro diseo descendente se muestra en el siguiente grfico:

El diseo de la interfaz de usuario puede ser como se muestra a continuacin.


La pantalla principal mostrar dos apartados:
para describir cmo es la va
para seleccionar el tipo de vehculo

Cuando se pulsa el botn Calcular aparece un dilogo que muestra la velocidad


para esa configuracin de va y vehculo.

Ya tenemos el diseo descendente y el diseo de pantallas, pasemos ahora a la


implementacin del programa.
Lo primero es crear con el Experto una aplicacin en vaco con todos los
componentes VPI necesarios, en este caso: Task Window con men y la
posibilidad de generar dilogos.
A continuacin aparece el siguiente dilogo:

En la parte izquierda tenemos activos los botones que nos permiten crear nuevos
componentes para la aplicacin. En la parte derecha aparecen los botones que
permiten editar y borrar componentes aadidos, as como editar sus atributos, y
acceder a la ventana de cdigo experto que nos permitir crear fcilmente las
cabeceras de nuestros manejadores de evento.

Si ejecutamos la aplicacin aparece una ventana vaca con tres elementos de


men: File, Edit y Help. Como ninguno de esos elementos nos interesa los vamos
a eliminar y pondremos en su lugar una pestaa con el nombre Men que va a
contener la opcin Salir.
Para ello pulsamos sobre el botn Menu del Experto y
seleccionamos Task Menu con doble click. A travs del dilogo que sigue,
eliminamos las opciones no interesantes.

Antes de eliminar las opciones del men nos tenemos que asegurar de eliminar
tambin todo el cdigo asociado a cada evento producido por la seleccin de
cualquiera de las opciones. Para ello es necesario observar la ventana de Cdigo
Experto y buscar en ella los eventos asociados al men para eliminar las
clusulas manejadoras introducidas automticamente por el sistema.

Si seleccionamos en el Dilogo Experto la Task Window y hacemos doble click


obtenemos un panel y una serie de componentes que podemos pegar sobre la
ventana.

Controls nos proporciona un conjunto de controles que podemos pegar en la


ventana. Layout provee herramientas para colocar los elementos dentro de la
ventana.
La ventana principal de nuestra aplicacin tiene el siguiente aspecto tras haber
pegado los controles adecuados, en el esquema mostrado se especifica los
nombres de los controles dinmicos, es decir, aquellos que van a permitir
interactuar al usuario con el sistema. El resto de controles son etiquetas estticas
de informacin.

Vemos, ahora, el dilogo ya diseado que debe aparecer tras la pulsacin del
botn Calcular. Posee tres elementos: dos etiquetas, una de informacin y otra
para volcar el valor de la velocidad en ella y un botn de aceptacin. Como el
dilogo es modal, hasta que no lo cerremos no podremos actuar sobre la ventana
principal.

Ya tenemos el diseo de los formularios preparados. Con slo pegar los


elementos en la ventana principal se ha ido incluyendo el cdigo necesario para
que los controles funcionen adecuadamente. Necesitamos adems incluir el
cdigo del dilogo en el fichero del programa. Para ello accedemos a su cdigo
experto y especificamos que deseamos que dicho cdigo se incluya en el fichero
adecuado que ser, en este caso, el archivo autowin.pro.

Como se observa, el cdigo debe actualizarse en autowin.pro a partir de la


primera vez que se haya pulsado el botn Update Code.
Cada vez que haya que generar un manejador de evento o editar uno ya existente
podemos utilizar este tipo de dilogo para cualquier ventana que tengamos
definida.
Vamos a observar ahora cual es la jerarqua de ventanas del programa y cules
son las dependencias entre elementos.

El manejador de ventana de la Task Window recoge todos los eventos y se


encarga de probar los subobjetivos correspondientes en funcin del evento
pasado por parmetro, que puede provenir del botnCalcular o de la pulsacin
del men.
El manejador del dilogo recoge los eventos de la ventana que lo enmarca y del
botn de aceptacin.
Nosotros debemos incluir cdigo al manejar el evento de creacin de la Task
Window, en el evento de pulsacin del botn Calcular y en el evento de creacin
del Dilogo. El resto de eventos son manejados automticamente por el sistema.
[NDICE]

Manejo del evento de creacin de la Task Window.


El cdigo que hemos de aadir es el que est resaltado en cursiva:
%BEGINTaskWindow,e_Create
task_win_eh(_Win,e_Create(_),0):!,
%BEGINTaskWindow,InitControls,14:04:044.10.2000,Codeautomaticallyupdated!
...
...
...
%BEGINInicializacindelaLISTBOX
W=win_GetCtlHandle(_Win,id_senales),

L=["autopista","autovia","viarapida","de_via_urbana","de_travesia","nohay"],
lbox_Add(W,L),
%ENDInicializacindelaLISTBOX
!.
%ENDTaskWindow,e_Create

Como la ListBox es hija de la Task Window y el predicado lbox_Add aade una


lista de cadenas a la ListBox siempre que conozcamos el manejador del control,
necesitamos obtener el manejador del control a travs del manejador del padre
_Win que viene pasado por parmetro. Para ello utilizamos el
predicado winGetHandle que devuelve el manejador del control a partir del
manejador de ventana del padre y del identificador del control que en este caso
es id_senales.
Rellenamos una lista con los items deseados y se la pasamos a lbox_Add.
[NDICE]

Manejo del evento de pulsacin del botn Calcular.


%BEGINTaskWindow,idc_calcular_CtlInfo
%Manejadordecdigoparalapulsacindelbotn
task_win_eh(_Win,e_Control(idc_calcular,_CtrlType,_CtrlWin,_CtlInfo),0):
W_lbox=win_GetCtlHandle(_Win,id_senales),
lbox_GetSel(W_lbox,LS,_),%Obtencindeltipodecarretera
LS=[Senal|_],
W_CBox1=win_GetCtlHandle(_Win,idc_ms_de_1_carril),
Mas_de_1_carril=win_IsChecked(W_CBox1),%Obtencindelnmerodecarriles
W_CBox2=win_GetCtlHandle(_Win,idc_carril_de_adelantamiento),
Carril_de_adelantamiento=win_IsChecked(W_CBox2),%Obtencindeinf.sobrecarrilde
adelantamiento
W_Edicion=win_GetCtlHandle(_Win,idc_editaarcen),
ArcenStr=win_GetText(W_Edicion),
str_int(ArcenStr,Arcen),%Obtencindeltamaodelarcn

tipovehiculo(_Win,Veh),%Obtencindeltipodevehculo
obtenernumerocarriles(Mas_de_1_carril,Carril_de_adelantamiento,Carriles),
velocidad(Veh,Arcen,Carriles,Senal,VelocidadMaxima),
assert(la_velocidad(VelocidadMaxima),misdatos),
dlg_calculo_Create(_Win),
!.
task_win_eh(_Win,e_Control(idc_calcular,_CtrlType,_CtrlWin,_CtlInfo),0):dlg_Error("Selecciona
adecuadamentelosparmetros"),!.
%ENDTaskWindow,idc_calcular_CtlInfo

La cabecera del evento ha sido generada por el sistema:


task_win_eh(_Win,e_Control(idc_calcular,_CtrlType,_CtrlWin,_CtlInfo),0)
y el objeto e_Control(idc_calcular,_CtrlType,_CtrlWin,_CtlInfo) nos informa de
que ha sido el botn el que ha producido el evento.
Este evento se va a tratar de dos maneras, si la primera falla es porque el
programa no puede hacer los clculos correctamente y alguna clusula falla
debido a una mala introduccin de los datos por parte del usuario, por tanto la
mquina Prolog busca la siguiente clusula para satisfacer que en este caso es la
que visualiza un pequeo dilogo de error.
Cuando el sistema genera automticamente la cabecera de un manejador de
evento, la forma del cuerpo suele ser generalmente vaca:
cabecera(argumentos):-!, #punto para insertar cdigo#
!.
Se puede observar que hay dos cortes uno al principio y otro al final. Esto debe
dejarse as si el manejo de eventos se realiza con una sola clusula, sin embargo
si se realiza con varias como es el caso deCalcular hay que eliminar el primer
corte para permitir la bsqueda de nuevas soluciones a travs del proceso de
backtracking.
Los subobjetivos planteados en la primera clusula que compone el manejador,
recogen los datos de los controles de la ventana principal, que el usuario debe

haber rellenado. Una vez que los tiene, ejecuta el predicado velocidad que ya
vimos en el caso de la aplicacin no VPI en teora. El predicado devuelve
un integer en la variable local VelocidadMaxima.
Como en Prolog no existen las variables globales no podemos pasar el contenido
de dicha variable a la etiqueta que debe visualizarlo en el dilogo de un modo
sencillo. Podemos intentar conseguir el manejador del dilogo a travs de su
padre, y a continuacin intentar obtener el manejador del control a travs del
obtenido del dilogo, aunque esta opcin es un poco complicada.
Otra posibilidad es hacer uso de hechos que pueden ser generados
dinmicamente. Podemos generar un hecho del tipo la_velocidad(INTEGER) que
sea single. As pues en el manejador de botn almacenamos un hecho con la
velocidad calculada mediante assert, y en el evento de creacin del dilogo
podemos capturar esta velocidad extrayendo el argumento del hecho almacenado.
[NDICE]

Manejo del evento de creacin del Dilogo de Clculo.


%BEGINcalculo,e_Create
dlg_calculo_eh(_Win,e_Create(_CreationData),0):!,
la_velocidad(V),
W_Texto=win_GetCtlHandle(_Win,idct_calculo_1),
str_int(V_text,V),
win_SetText(W_Texto,V_Text),
!.
%ENDcalculo,e_Create

El resto de cdigo est perfectamente comentado e implementado en el fichero


fuente que podis encontrar en la pgina de la asignatura.
El aspecto de la aplicacin diseada se muestra a continuacin:

TEMA 2
Aritmtica, datos y estructuras en Visual Prolog

1 Sintaxis Bsica de VISUAL PROLOG


1.1 Aritmtica de VISUAL PROLOG
2 Datos simples y Estructuras de Datos: DOMINIOS
[2.1 OBJETOS COMPUESTOS] [2.2 RBOLES] [2.3 LISTAS] [2.4
MATRICES]
3 Bibliografa

Sintaxis Bsica de VISUAL PROLOG


Hemos visto ya un buen nmero de convenciones que debemos utilizar para
escribir programas en Prolog. La ltima parte de este tema la dedicaremos a
conocer detalladamente las reglas sintcticas que hemos de seguir para que
nuestras bases de conocimientos sean reconocidas por Visual Prolog.
Como ya hemos estudiado, un programa Prolog no es ms que la especificacin
de una base de conocimientos lgica con las caractersticas siguientes:
Consta de una secuencia de oraciones, todas ellas verdaderas, que
expresan un conjunto de realidades sobre los objetos del mundo
representado, as como sobre sus relaciones. Todas las variables tienen
cuantificacin universal implcita y cuando las variables aparecen en
oraciones distintas se consideran tambin distintas.
Se aceptan nicamente oraciones en forma de Clusula de Horn, es decir,
las oraciones son atmicas, o bien una implicacin con un antecedente no
negado y un consecuente generalmente"expresiones" separados por comas
o por puntos y comas. Las comas significan conjuncin y los puntos y
comas significan disyuncin.
En vez de utilizar antecedentes negados en sus implicaciones, en Prolog se
emplea un operador de negacin basado en el fallo: una meta no P se
considera demostrada si el sistema no logra demostrar P.
[NDICE]

Aritmtica de VISUAL PROLOG


Las expresiones aritmticas en Visual Prolog se componen de operandos
(nmeros y variables), operadores (+, -, *, /, div, y mod) y parntesis: A = 1 + 6 /
(11 + 3) * Z. Ver Tabla 1.
Los nmeros "0x" o "0o" significan hexadecimal y octal respectivamente: 0xFFF
= 4095; 86 = 0o112 + 12.
El valor de una expresin se puede calcular si todas las variables estn unificadas
en el momento de la evaluacin. El clculo ocurre entonces en un orden
determinado por la prioridad de los operadores aritmticos. Los operadores de
mayor prioridad son evaluados primero. Ver Tabla 2.

[NDICE]

Operaciones
Operando 1

Operador

Operando 2

Resultado

entero

+, -, *

entero

entero

real

+, -, *

entero

real

entero

+, -, *

real

real

real

+, -, *

real

real

entero real

entero real

real

entero

div

entero

entero

entero

mod

entero

entero

Tabla 1
[NDICE]

Orden de evaluacin
Si la expresin contiene subexpresiones entre parntesis, las subexpresiones se
evalan primero.
Si la expresin contiene multiplicacin o divisin, estas operaciones son
realizadas trabajando de izquierda a derecha a travs de la expresin.

Las operaciones de suma y resta son llevadas a cabo de izquierda a derecha


tambin.
En el orden de evaluacin se tiene en cuenta, lgicamente, la precedencia de los
operadores.
Operador

Prioridad

+-

* / mod div

- + (unario

Tabla 2
[NDICE]

Funciones y predicados
Visual Prolog posee una gran cantidad de funciones y predicados matemticos
para realizar las ms variadas operaciones. La lista completa se ofrece en la Tabla
3.
Nombre

Descripcin

X mod Y

Resto de X dividido entre Y.

X div Y

Cociente de X dividido entre Y.

abs(X)

Valor absoluto de X.

cos(X)

Coseno de X.

sin(X)

Seno de X.

tan(X)

Tangente de X.

arctan(X)

Arcotangente de X.

exp(X)

e elevado al valor almacenado en X. (Exponencial).

ln(X)

Logaritmo neperiano de X.

log(X)

Logaritmo en base 10 de X.

sqrt(X)

Raz cuadrada de X.

random(X)

Almacena en X un nmero aleatorio real entre 0 y 1.

random(X, Y)

Almacena en Y un nmero aleatorio en el intervalo 0 <= Y <


X.

round(X)

Valor redondeado de X. El resultado es un nmero real.

trunc(X)

Valor truncado de X. El resultado es un nmero real.

val(domain,X)

Conversin explcita entre dominios numricos.

Tabla 3
[NDICE]

Comparaciones
En Visual Prolog podemos comparar expresiones aritmticas, caracteres, cadenas
de caracteres y smbolos.
Las comparaciones de este tipo se realizan a travs de operadores relacionales.
Ver Tabla 4.
Smbolo

Relacin

<

menor que

<=

menor o igual que

igual que

>

mayor que

>=

mayor o igual que

<> o ><

distinto

Tabla 4
[NDICE]

Comparacin de caracteres, cadenas de caracteres y smbolos


Adems de las expresiones numricas, podemos comparar caracteres, cadenas y
smbolos: 'a' < 'b'; "antony" > "antonia" y P1 = peter, P2 = sally, P1 > P2.
Caracteres: Visual Prolog convierta la comparacin 'a' < 'b' a su expresin
aritmtica correspondiente 97 < 98, usando el cdigo ASCII
correspondiente a cada carcter.
Cadenas de caracteres: Cuando se comparan dos cadenas o smbolos, la
comparacin se realiza carcter a carcter en sus correspondientes
posiciones. El resultado es el mismo que se consigue comparando el
carcter inicial a menos que los dos sean iguales en cuyo caso se pasa al
siguiente. Cuando se encuentran dos caracteres iguales, el proceso de
comparacin termina y se produce el resultado.
Smbolos: No pueden ser comparados directamente debido a la sintaxis.
Primero deben ser unificados a variables o escritos como cadenas de
caracteres.
[NDICE]

Datos simples y Estructuras de Datos: DOMINIOS


En cualquier lenguaje de programacin necesitamos representar datos complejos.
Podemos definir dato complejo como la agrupacin homognea o heterognea de
otros datos que a su vez pueden ser tambin complejos o simples. As pues, a
partir de esta definicin, los datos se pueden organizar de mltiples formas que
ya conocemos: vectores, registros, listas, rboles, grafos, etc.
Un programa en Visual Prolog utiliza distintas secciones para las declaraciones
de tipos o dominios con el fin de crear estructuras complejas de datos
(DOMAINS), predicados (PREDICATES), reglas y hechos que forman los
predicados (CLAUSES) y metas (GOAL).
En la seccin de predicados se definen las cabeceras de los predicados que vamos
a utilizar en nuestros programas, es decir el nombre del predicado y el dominio o
tipo de los argumentos del mismo.
En la seccin de clusulas se define la implementacin de cada predicado
declarado en PREDICATES.

En la seccin GOAL se establece la meta principal del programa.


Centrmonos ahora en la seccin DOMAINS y en cmo crear estructuras
complejas: objetos compuestos, rboles, listas y matrices.
[NDICE]

OBJETOS COMPUESTOS
Los objetos compuestos estn formados por un functor y un conjunto de
argumentos. Por ejemplo, cuadro(NS, Autor, Estilo, Dimensiones) representa una
estructura que almacena los datos ms relevantes para describir este tipo de obra
de arte. El nombre cuadro es el functor y los elementos entre parntesis son los
argumentos del objeto compuesto. Los argumentos (campos), de un objeto
compuesto pueden ser datos simples o datos complejos.
Para definir objetos compuestos es necesario introducirnos en el concepto
de DOMINIO o DOMAINS. Como veremos en la seccin de prcticas, la
seccin DOMAINS de un programa en Visual Prolog agrupa los dominios (tipos),
no estndares en el sistema.
Definir un dominio no es ms que establecer qu forma tendrn los objetos que
pertenecen a dicho dominio o tipo, por ejemplo, para el caso del cuadro, el
dominio sera as:
un_cuadro= cuadro(INTEGER, STRING, STRING,
STRING)
Como hemos dicho, los argumentos de un objeto compuesto pueden ser
complejos:
un_comprador= comprador(STRING, un_cuadro)
El dominio o tipo del ejemplo define a un comprador de un cuadro. Los objetos
compuestos de este tipo almacenan una cadena que puede representar el DNI y el
cuadro que posee.
Veamos varios objetos de tipo un_comprador:
comprador("111111111", cuadro(1239, "Martn
Jimnez", "leo", "39x23")).

comprador("122111111", cuadro(1449, "Surez


Jimnez", "acuarela", "130x50")).
comprador("111133331", cuadro(2232, "Martn
Prez", "carboncillo", "100x100")).
[NDICE]

RBOLES
Un rbol es una estructura con una definicin puramente recursiva, ya que se
puede considerar como el elemento raz cuyos hijos son, a su vez, rboles. Si el
rbol tiene nicamente dos hijos se denomina rbol binario. Este modelo
especfico de rbol se utiliza mucho para resolver gran cantidad de problemas en
aspectos de programacin.
Un rbol se puede considerar, a su vez, un caso particular de grafo, donde todos
los caminos son acclicos.
La Figura 1 muestra un ejemplo de rbol.

Figura 1
Ejemplo de rbol

Muchos problemas de Inteligencia Artificial donde interviene el concepto de


bsqueda se resuelven mediante la implementacin de rboles. Los rboles de
juego o los utilizados en la resolucin de problemas relacionados con el
procesamiento de lenguaje natural son casos muy concretos y descriptivos. Por lo

tanto, podemos notar que el manejo eficiente de estas estructuras es sumamente


importante para conseguir programas de calidad en este mbito de la Ciencia.
Ya vimos que Prolog es un lenguaje que se adapta adecuadamente a este tipo de
problemas. De hecho la tcnica de resolucin que utiliza Prolog se basa en la
construccin de un rbol de bsqueda de soluciones, luego podemos concluir que
el conocimiento de esta estructura es clave para este tipo de metodologa
declarativa.
Como en cualquier lenguaje, lo que necesitamos saber es la forma de declarar el
rbol, ya que su implementacin se puede realizar de muchas formas, por
ejemplo, aunque una lista es un caso particular de rbol, un rbol se puede
representar a travs de listas, aunque en el caso de Visual Prolog, estudiaremos la
construccin de rboles utilizando objetos compuestos recursivos.
Dado que un rbol est formado por la raz y un conjunto de hijos, podemos
representarlo utilizando la siguiente notacin:
oracin(sujeto(artculo(el),sustantivo(hombre)),predicado(verbo(come),CD(pan)))

El rbol generado se muestra en la Figura 2.

Figura 2

rbol de anlisis de una frase en espaol

Como se observa, el uso de un predicado con dos argumentos en el caso de rbol


binario o N argumentos en el caso de rbol N-ario es una forma sencilla de
representar un rbol.
Mediante objetos compuestos recursivos del tipo arbol(nodo, hijoizq, hijoder),
donde hijoizq e hijoder son tambin rboles, podemos representar un rbol
binario. El rbol vaco se representa a travs del hecho vacio:
arbol(1,arbol(2,arbol(4,vacio,vacio),arbol(5,vacio,vacio)),arbol(3,vacio,vacio))
En la seccin DOMAINS podemos crear un tipo rbol de enteros del modo
siguiente:
mi_arbol= arbol(INTEGER, mi_arbol, mi_arbol); vacio
Operaciones con rboles representados mediante objetos compuestos recursivos

domains
arbol=nodo(integer,arbol,arbol);vacio
lista=integer*
predicates
concatenar(lista,lista,lista)
preorden(arbol,lista)
inorden(arbol,lista)
postorden(arbol,lista)
clauses
concatenar([],[],[]):!.
concatenar([],L2,L2):!.
concatenar(L1,[],L1):!.
concatenar([X|Y],L2,[X|Aux]):concatenar(Y,L2,Aux).
preorden(vacio,[]):!.

preorden(nodo(X,Izq,Der),[X|L]):preorden(Izq,L1),
preorden(Der,L2),
concatenar(L1,L2,L).
inorden(vacio,[]):!.
inorden(nodo(X,Izq,Der),L):inorden(Izq,L1),
inorden(Der,L2),
concatenar(L1,[X|L2],L).
postorden(vacio,[]):!.
postorden(nodo(X,Izq,Der),L):postorden(Izq,L1),
postorden(Der,L2),
concatenar(L1,L2,L3),
concatenar(L3,[X],L).
goal
inorden(nodo(1,nodo(2,nodo(4,vacio,vacio),nodo(5,vacio,vacio)),nodo(3,vacio,vacio)),L1),
preorden(nodo(1,nodo(2,nodo(4,vacio,vacio),nodo(5,vacio,vacio)),nodo(3,vacio,vacio)),L2),
postorden(nodo(1,nodo(2,nodo(4,vacio,vacio),nodo(5,vacio,vacio)),nodo(3,vacio,vacio)),L3).

[NDICE]

LISTAS
Una lista se puede considerar como un caso particular de rbol del modo que se
muestra en la Figura 3.

Figura 3
Lista implementada en forma de rbol

A su vez, una lista se puede considerar de forma recursiva. Es decir, siempre est
formada por un elemento seguido de otra lista (ver Figura 4). Cuando la lista
tienen un slo elemento podemos considerar que est formada por dicho
elemento y la lista vaca. Esta definicin es muy interesante, ya que su
conocimiento nos permitir llevar a cabo todos las operaciones que se pueden
realizar sobre las listas con poco esfuerzo.

Figura 4
Definicin recursiva de una lista

Hemos de recordar que en Prolog no existen estructuras para realizar bucles


luego todo los algoritmos que representemos se definirn de forma recursiva. El

hecho de que la implementacin de la lista sea tambin recursiva facilita la


construccin de operaciones sobre la misma.
Es necesario comprender este tipo de estructura para construir algoritmos
eficientes. La mayor parte de las operaciones que se realizan sobre una lista
implica un recorrido de la misma, luego hemos de centrarnos en conocer cmo se
lleva a cabo este algoritmo utilizando tcnicas de recursividad.
Una lista se puede especificar en un predicado o en un objetivo a travs de:
una constante: [a, b, c, 1, pepe]
una variable: L
la estructura [Cabeza|Cola] que almacenar el primer elemento en la
variable Cabeza y el resto en la variable Cola.
Las listas pueden ser homogneas o heterogneas, es decir, almacenar elementos
del mismo tipo, o elementos de distinto tipo.
Para definir un tipo de lista en particular es necesario declararla en la
seccin DOMAINS.
lista= elementos* (lista de una dimensin)
lista2= elementos** (lista de dos dimensiones)
lista3= elementos*** (lista de tres dimensiones)...
Es interesante observar la sintaxis de definicin de una
lista: elementos representa el dominio o tipo de los elementos que componen la
lista.
El tipo elementos puede representar un dominio simple, es decir, slo un tipo de
elementos se corresponde con dicho dominio o un dominio complejo, donde
varios tipos de elementos se corresponden con dicho dominio.
Por ejemplo, una lista homognea de elementos simples estara definida como:
lista= integer*
Una lista heterognea de elementos estara definida como:

listaenteros=integer*
elementos= i(integer); s(symbol); c(char); le(listaenteros)
lista= elementos*
Ejemplo:

domains
listaenteros=integer*
elementos=i(integer);c(char);s(symbol);le(listaenteros)
lista=elementos*
predicates
recorrer(lista)
clauses
recorrer([]):!.
recorrer([X|Y]):write(X),nl,recorrer(Y).
goal
recorrer([i(1),c('a'),s(pepe),i(5),c('b'),le([1,2,3])]).

Se observa que la lista puede contener cuatro tipo de elementos distintos: enteros,
caracteres, smbolos y listas de enteros. En la seccin de declaracin del dominio
o tipo elementos no podemos escribir:
elementos=integer;char;symbol;listaenteros

para expresar que dicho dominio agrupa a cuatro tipos de elementos distintos
sino que la sintaxis a utilizar es aquella que representa que elementos agrupa a
cuatro tipos de objetos compuestos distintos.
El resultado de la ejecucin de la meta es el siguiente:
i(1)

c('a')
s("pepe")
i(5)
c('b')
le([1,2,3])
yes

Las operaciones tpicas que se pueden realizar sobre listas son: la insercin de
elementos al principio, al final, en orden; borrado, bsqueda de elementos,
recorrido, eliminacin de duplicados y, en general, todas las de las que se pueden
realizar sobre conjuntos de elementos tales como: interseccin, unin, diferencia,
pertenencia, comprobacin de lista vaca, concatenacin, etc.
Las listas se pueden utilizar para implementar otras estructuras tales como listas
circulares, vectores, pilas, colas, rboles, grafos y matrices.
De cada estructura nos interesa saber cules son los algoritmos para acceder a
ellas. Una vez que conocemos, perfectamente, el tipo de operaciones que las
definen, cualquier tipo de implementacin es vlida. Por ejemplo, es frecuente
usar una implementacin mediante listas para plasmar matrices.
Por otro lado, es fundamental aplicar tcnicas de diseo descendente para
resolver todos nuestros problemas e implementar las estructuras necesarias en
nuestras aplicaciones.
MATRICES
Podemos definir matrices a partir de listas, primero de 2 dimensiones y, ms
tarde, generalizar matrices de dimensin N.
En un lenguaje imperativo, recorrer una matriz de dos dimensiones implica el uso
de un par de bucles anidados, que proporcionan una complejidad
computacional O(n2). Sin embargo, en Prolog, no disponemos de este tipo de
estructuras de control, por tanto, cualquier operacin debe ser resuelta de forma
recursiva mediante la declaracin formal de su enunciado.
Un tratamiento elemento a elemento de las matrices tal y como se realiza en un
lenguaje imperativo no es adecuado en Prolog, por tanto, conviene entender la
estructura matriz como una lista de listas, y aplicar los algoritmos diseados
sobre listas para resolver problemas matriciales.

Una matriz de cuatro dimensiones se puede ver como la secuencia de un conjunto


de matrices de tres dimensiones, una matriz de tres dimensiones como un
conjunto de matrices de dos dimensiones, una matriz de dos dimensiones como
un conjunto o lista de matrices de una dimensin (vector o lista), por ltimo, un
vector o lista no es ms que una secuencia de elementos simples.
Las definiciones dadas son recursivas, luego los algoritmos que debemos
construir para realizar operaciones sobre este tipo de estructuras, as definidas,
tambin sern recursivos.
Operaciones con matrices bidimensionales

domains
fila=integer*
matriz=fila*
predicates
sumafila(fila,fila,fila)
sumar(matriz,matriz,matriz)
clauses
/*Predicadoparacalcularlasumadeloselementosdeunafila*/
sumafila([],[],[]):!.
sumafila([],L2,L2):!.
sumafila(L1,[],L1):!.
sumafila([C1|Cola1],[C2|Cola2],Res):S=C1+C2,
sumafila(Cola1,Cola2,ColaRes),
Res=[S|ColaRes].
/*Predicadoderecorridodelasfilasparasumarloselementosmedianteelusodelpredicado
anterior*/
sumar([],[],[]):!.
sumar([],L2,L2):!.
sumar(L1,[],L1):!.

sumar([C1|Cola1],[C2|Cola2],LR):sumafila(C1,C2,Res),
sumar(Cola1,Cola2,ColaRes),
LR=[Res|ColaRes].
goal
sumar([[1,2,3],[2,2,2],[4,4,4]],[[1,1,1],[2,1,2],[1,2,3]],R).

[NDICE]

Bibliografa
[Adarraga, 1994] Adarraga, Pablo. Zaccagnini Jos Luis. "Psicologa e
Inteligencia Artificial". Editorial Trotta. 1994.
[NDICE]

Tutorial de visual prolog 7.3

Contenido
[ ocultar ]

1 Conceptos
2 El Programa de
3 de dilogo no modal: Aspectos Conceptuales
4 El paquete FamilyData
5 Interfaces
6 El paquete FamilyDL
7 del Cdigo para el paquete de familyDL
8 del Cdigo para el paquete de familyBLL
9 Caractersticas de una capa de datos
10 Conclusin

11 Referencias

Conceptos
Hay un proverbio chino que dice as: "Dale a un hombre un pescado y lo alimentars por un da
Ensale a pescar y lo alimentars toda la vida.". Hay una leccin en la programacin de all. A
veces es mejor sustituir los datos ( un pescado ) con un mtodo ( el procedimiento de la pesca )
que puede conducir a los datos.
Este concepto se puede ampliar an ms un poco ms. Por ejemplo, si antes de ensear la pesca
persona directamente, el hombre se le ensea los principios de la obtencin de alimentos de la
naturaleza, entonces la persona tiene una mejor oportunidad de conseguir alimentos para su
familia.
Pero aqu hay una advertencia: explicar las cosas con analogas puede ser un poco problemtico,
porque, cuando se estira una analoga demasiado lejos, se rompe! En el ejemplo anterior, si se le
da al pescador una capa ms , entonces l puede morir de hambre antes de que pueda cosechar
los frutos de su buena educacin!
Esta forma de conexin en cadena de reunir una serie de actividades para lograr el objetivo final
que se puede hacer tambin en la programacin. Pero entonces, esto tiene que hacerse de
manera inteligente, de acuerdo con las exigencias que plantea la complejidad del problema de
software que est tratando de manejar. Aunque se puede decir que ms las capas que se
introducen, mejor es el control al llegar a la meta final; se necesita para configurar las capas
despus de la previsin cuidadosa.
Si usted ve el patrn que ha evolucionado a travs de toda la familia de la serie de tutoriales
(Prolog fundamental Visual, Visual Prolog Fundamental - GUI, Visual Prolog fundamental - la
capa de negocio lgico), se dara cuenta de lo mismo: las capas ms y ms refinadas eran
presentacin que finamente controlado el comportamiento del programa. Al mismo tiempo, no
existan las capas innecesarias - si as fuera, sera slo han aumentado la complejidad y la
burocracia que conlleva el programa.
En este tutorial, vamos a introducir la capa de datos. El ncleo de la capa de datos no es ms
que una clase, y los objetos de esa clase se puede utilizar para acceder y configurar los datos
reales. En el tutorial anterior, tenga en cuenta que la capa de lgica de negocios (BLL) maneja
los datos tambin. Esta vez, el CSP se manejar solamente la lgica.

El Programa de
Pero en primer lugar, vamos a entender las distintas partes del programa con la ayuda del
archivo family4.zip suministrado. En este tutorial, no estamos presentando el cdigo que se
necesita (cosa este tutorial ser demasiado larga). Todo el cdigo est presente en el ejemplo

para el tutorial. Usted puede leer el cdigo desde el IDE, cuando se carga el proyecto
all. Algunos parcial de cdigo es, sin embargo, aqu presentes, para una referencia rpida.
Cuando se carga el proyecto ( family4 ) en el IDE de Visual Prolog, te dars cuenta de cuatro
paquetes separados, como se muestra a continuacin:

Estos paquetes son los FamilyBLL, FamilyData , FamilyDL y paquetes TaskWindow. El ltimo
paquete (es decir, TaskWindow) se crea automticamente por el IDE, cuando se crea el
proyecto. El mtodo para crear los otros paquetes se explica en un tutorial anterior.
El proyecto fue creado de una manera similar que se explica en un tutorial anterior. No hay
sorpresas all. Pero aqu hay un poco de explicacin de algo nuevo.
Hay una ms de dilogo que se introduce en el TaskWindow paquete en comparacin con
el tutorial anterior. Este es elNewPersonDialog , que se muestra a continuacin. (Ya
hemos incluido este cuadro de dilogo en el proyecto. Sin embargo, la explicacin a
continuacin pretende que se est creando este cuadro de dilogo por su cuenta en el
proyecto.)

Este dilogo es un dilogo modal, que se utiliza para recoger la informacin de una
nueva persona que va a ser insertado en la base de datos actual. Como se puede ver
en la imagen de arriba, hay un campo de edicin de texto (idc_name) para recoger el
nombre, una serie de botn de radio (idc_male y idc_female) para encontrar el
gnero, y otros dos campos de texto de edicin (idc_parent1 y idc_parent2) a
encontrar a los padres de la persona que se aade a la base de datos. Un cuadro de

dilogo modal es uno, que puede permanecer abierta y activa, sin interferir en el
funcionamiento de otras partes de la interfaz grfica de usuario.
No hay ninguna diferencia entre un modal y no modal de dilogo cuando se est
creando. Sin embargo, al establecer sus atributos que debe tener cuidado de
especificar que es de hecho un modal uno, como se muestra a continuacin:

Ahora slo tienes que crear un dilogo no es de ninguna utilidad si no hay


manera por la cual se puede invocar desde el cuadro de dilogo TaskWindow. Por
lo tanto tenemos que insertar un nuevo elemento de men en eso y asociar un
controlador de eventos con ese elemento de men. Una vez que se crea el
elemento de men correspondiente, el asistente de cdigo que nos permitir
crear un controlador en el que podemos introducir el cdigo requerido. La
imagen se muestra a continuacin:

Tenga en cuenta que en un tutorial anterior (Prolog fundamental Visual GUI), que haba mostrado cmo crear un controlador de eventos para un
elemento de men mediante el asistente de cdigo anterior.

Modal de dilogo: Aspectos Conceptuales


Este programa utiliza un cuadro de dilogo modal con el fin de insertar la
informacin relativa a las personas nuevas en lafamilia de base de
datos. Como se indica en un tutorial anterior, la codificacin de los
acontecimientos que suceden a partir de un dilogo no modal a veces
puede ser complicado. Esto se puede entender si se sabe exactamente por
qu un cuadro de dilogo modal funciona de la manera que lo hace. En un
cuadro de dilogo modal, el sistema operativo suspende los
acontecimientos que suceden en todas las otras partes de la interfaz grfica
de usuario de la misma aplicacin, y se concentra slo en las que surgen
del cuadro de dilogo modal. La lgica necesaria para ser manejados por el
programador en ese punto en el tiempo se vuelve bastante simple, ya que
el programador est muy seguro de que no hay eventos adversos que
ocurren de manera simultnea en otras partes del mismo programa.
Por otro lado, cuando un dilogo modal est en uso, el programa es
receptiva a los acontecimientos, incluso de las partes del programa , junto

con los que se producen desde el dilogo dijo. Las permutaciones y


combinaciones de control de eventos necesidad requerida para ser
cuidadosamente analizados por el programador. Por ejemplo, el programa
podra abrir una base de datos, y luego tener un modal de dilogo abierto,
el cual trabaj en la base de datos. Se lanzara un error, cuando el dilogo
se pone en uso, si en el fondo de la base de datos se cerr sin cerrar el
cuadro de dilogo. A menos, claro, que haba previsto un curso de los
acontecimientos y programado para este tipo de situaciones.
Si ve el cdigo fuente que se ocupa de los acontecimientos que suceden a
partir de este dilogo en NewPersonDialog.pro, ver que el cdigo
cuidadosamente las capturas de una gran cantidad de situaciones de
error. Incluso tiene un verificador de integridad que intenta rastrear lo que
puede hacer que un pedazo de cdigo para provocar un error.
Los predicados que pueden conducir a errores en tiempo de ejecucin se
llaman desde dentro de un especial integrado en el predicado, llamado
trap . Por ejemplo, vase el siguiente cdigo:

idc_name ) ) ,
Nombre "" ,
MaleBool = vpi :: winIsChecked ( VPI :: winGetCtlHandle
( thisWin, tratar ,
!,

stdio :: write ( "insertado" , Nombre , " \ n " ) .


onControlOK ( _Ctrl , _CtrlType , _CtrlWin , _CtrlInfo )
manejado ( 0 ) .

En el cdigo anterior, el programador no est seguro de si la adicin de una


persona en la base de datos es realmente posible (porque no se permite la
incorporacin de una persona ya existente). As, el addPerson no se llama
directamente, sino a travs de la trampa de predicado. El predicado de la
trampa acepta tres variables: la primera de las cuales es el predicado de
ser llamados a hacer el trabajo real en ese punto en el cdigo, el segundo
es el nmero de error que se genera en el caso se activa un error, y es la
tercera un predicado que se llama en la activacin del error. Ese predicado
tercera puede ser utilizado por el programador para que el programa de
forma segura de nuevo en el control.

El paquete de FamilyData
En este ejemplo, vamos a crear un paquete de FamilyData, que tiene todo
el cdigo necesario para el manejo de los dominios que se necesitan por el
programa. Los mismos dominios estara disponible para el plomo en

sangre (la capa de lgica de negocios), cuando se comunica con la capa de


datos.
En esta clase, vamos a escribir el siguiente cdigo:

clase familyData
abierto central
dominios
de gnero = femenino ( ) , macho ( ) .
dominios
persona = cadena.
person_list = persona * .
dominios
optionalPerson = noPerson ( ) ; persona ( persona Persona ) .
predicados
toGender :
gnero .

( cadena de GenderString )

predicados
toGenderString :
GenderString .

-> de gnero de

( de gnero de gnero )

-> string

predicados
ClassInfo : ncleo :: ClassInfo .
fin de la clase familyData
Si te fijas, la clase anterior contiene las definiciones de dominio que van a
ser compartidos entre varias clases. Por lo tanto, el propsito de este
paquete es actuar como un lugar de reunin entre la capa de datos y
la capa de negocios .

Interfaces
La capa , que se encargar de los datos, ser a travs de los objetos
creados a partir de una clase en el paquete de FamilyDL.Sin embargo,
antes de llegar a los contenidos reales de dicho paquete, tenemos que
entender un concepto llamado de una interfaz .
Una interfaz puede ser visto como una declaracin de intenciones sobre qu
esperar en los objetos que se adhieren a la interfaz, dijo. Est escrito en un
archivo separado utilizando el IDE y puede contener predicados que se
pueden esperar ser encontrado en los objetos de una clase.

Una interfaz tambin puede ser utilizado para las definiciones de algunos
ms que no se explican en este tutorial. Usted puede aprender sobre el uso
de los avance en un tutorial futuro.
La razn para escribir las intenciones por separado en una interfaz diferente
es una una elegante: Una clase puede ser escrito para adherirse a las
declaraciones se encuentran en una interfaz. La interfaz ofrece una
definicin abstracta de la funcionalidad proporcionada por los objetos de la
clase. La definicin es "abstracto", ya que slo expresa parte de la
funcionalidad de los objetos. En resumen, una clase de forma declarativa se
puede afirmar que los objetos se comportan de acuerdo a la interfaz.
Varias clases pueden implementar la misma interfaz, cada uno de ellos
proporcionando un especfico y concreto (es decir, no abstracto) la
aplicacin de la abstraccin. Esto reduce la carga de mantenimiento del
cdigo enormemente. Ms tarde, cuando ms sofisticacin se va a
introducir en el mismo programa, el programador / s puede trabajar en
estas interfaces y luego trabajar su camino a partir de ah metdicamente.

El paquete de FamilyDL
Este ejemplo tambin contiene otro paquete llamado el paquete
FamilyDL. Este paquete contiene la clase principal, cuyos objetos se
ocupara de los datos reales.
Este paquete contiene una interfaz - la interfaz familydl. El propsito
principal de este interfaz es definir los predicados que son proporcionados
por la capa de datos a la capa de lgica de negocios. Como tal, juega un
papel importante en la capa de datos. Esta interfaz se basa en los dominios
del paquete FamilyData.

interfaz de familyDL
abierto central, familyData
predicados
person_nd : ( persona Nombre ) nondeterm ( o ) .
predicados
de gnero : ( persona que nombre ) -> de gnero de gnero .
predicados
parent_nd : (
persona persona ,
persona de Padres )
nondeterm ( i, o ) .

predicados
addPerson : ( persona persona , el gnero de gnero ) .
predicados
addParent : ( persona persona , persona de Padres ) .
predicados
personExists : ( persona Persona ) determ .
predicados
salvar a : ( ) .
finales de interfaz familyDL
En el cdigo anterior, la palabra clave abierto se utiliza para indicar que las
declaraciones tanto en el ncleo y los paquetes familyData se utilizan en
esta interfaz.
El paquete contiene dos clases: family_exception y family_factfile. La
mayor parte del trabajo ser realizado por family_factfile .Ese archivo
contendr el cdigo, lo que trae en el pescado (si se fuera a utilizar de
nuevo la metfora del proverbio chino se mencion al principio de este
tutorial). Se crea sistemticamente la base de datos que es utilizado por el
programa, y, al hacerlo, as que comprueba para cualquier situacin de
error que puede ocurrir. En caso de que haya un error, sera utilizar los
predicados de la clase family_exception para sealar el error de forma
sistemtica.

Cdigo para el paquete de familyDL


El paquete tiene una interfaz de familyDL familydl.i archivo, el cdigo que
se le dio antes. El paquete tambin contiene dos archivos. Profesionales
que contienen las implementaciones de los dos. Cl (clase) de los
archivos. Las dos clases de este paquete son familydl_exception y
familydl_factfile. El cdigo de familydl_factfile puede examinarse desde el
archivo family4.zip que se puede descargar por separado para este
tutorial. Los predicados de ese archivo son para la manipulacin de los
datos, y hemos cubierto que en nuestro tutorial anterior.
El cdigo de familydl_exception tampoco se presenta aqu en este
tutorial. Por favor, lea desde el archivo family4.zip. Los predicados
contienen predicados de apoyo de servicios pblicos que se utilizan para
mostrar los mensajes correctos de error, cuando los datos incorrectos y / o
errores (conocidos como excepciones En informtica) son capturados por el
programa.Muchas de estas situaciones de error ocurrir sin el control del
programador (por ejemplo, una puerta de la unidad de ser abierta es una
excepcin que no se puede predecir), pero a veces, se requiere para hacer

un error de pasar. Esto significa que el programador de forma deliberada


genera un error (para usar la jerga informtica aqu). As, la utilidad de los
predicados de error empezar con el trmino raise_ como usted puede
notar en el cdigo.
Ntese que familydl_exception no contiene la lgica para la manipulacin
de las excepciones s mismos. Son predicados de servicios pblicos que
permiten que el programa muestre el cuadro de dilogo de error correcto,
cuando las excepciones son a suceder.
Aqu est un ejemplo de cmo estos predicados raise_ deliberadamente
invocado por el programador para sealar una situacin de error.
En el familydl_factfile.pro usted encontrara un predicado de la adicin de
un padre. En el cuerpo clusula, en primer lugar, pasa a travs de dos
cheques para ver si tanto a la persona, as como el padre de la persona son
los actuales. Si alguno de ellos no existe, entonces familyDL_exception ::
raise_personAlreadyExists se llama. Esto plantea la excepcin y el
programa mostrar un cuadro de dilogo especial de error en ese
punto. Afortunadamente, ese cuadro de dilogo de error en particular no
tiene que ser construido por el programador. El trabajo de creacin de
dilogo se lleva a cabo por las bibliotecas de Visual Prolog cuando se
vincula el programa. No sera la creacin de un dilogo de error por
separado la forma en que lo hizo para otros dilogos.

% Nota: El siguiente es slo parcial,


el cdigo% a partir de familydl_factfile.pro
clusulas
addParent ( Persona , padre ) : check_personExists ( Persona ) ,
check_personExists ( Padres ) , los
assertz ( parent_fct ( Persona , los padres ) ) .
clusulas
personExists ( Persona ) : person_fct ( Persona , _ ) y
!.
predicates
check_personDoesNotExist : (string Person).
clauses
check_personDoesNotExist(Person) :personExists(Person),
!,
familyDL_exception :: raise_personAlreadyExists ( ClassInfo,
Persona ) .
check_personDoesNotExist ( _ ) .

...

Cdigo para el paquete de familyBLL


El cdigo de la familyBL.i archivo de interfaz es la siguiente. Esto es muy
similar a la interfaz de la capa de negocio que fue desarrollado para el
tutorial anterior. Pero hay diferencias importantes: los dominios se han
desplazado fuera de este paquete y ahora son comnmente compartidos
entre la capa de datos y la capa de negocio. Este es un paso obvio, porque
en el tutorial anterior que haba mantenido tanto la capa de negocio y la
capa de datos en una sola pieza de cdigo. Al separar estas dos capas, que
todava se necesitara algn punto en comn a travs del cual estas dos
capas se puede hablar el uno al otro, y la decisin obvia sera hacer que los
dominios utilizados por ellos comunes a los dems.
El segundo cambio que se puede notar es que los predicados no tiene
varios de los flujos. Cada predicado hace exactamente una cosa con los
parmetros que maneja. Esto hace que el programa se mueven lejos del
tradicional prlogo y se convierte en similar al de los programas escritos en
otros idiomas. A menudo, esta estrategia conduce a mejores resultados, ya
que hace ms fcil entender el programa cuando uno lee el cdigo
fuente. Sin embargo, el mtodo anterior de tener mltiples flujos de hace
resultado en el cdigo fuente ms corta y es a menudo preferido por los
programadores que vinieron despus de usar en el prlogo tradicional.

interfaz de familyBL
abierto central, familyData

predicados
personWithFather_nd : ( persona persona , persona Padre )
nondeterm ( O, O ) .
predicados
personWithGrandfather_nd : ( persona persona , persona Abuelo
)
nondeterm ( O, O ) .
predicados
ancestor_nd : ( persona persona , persona que los antepasados
)
nondeterm ( i, o ) .
predicados

addPerson : ( persona persona , el gnero de gnero ,


optionalPerson Parent1 , optionalPerson parent2 ) .
predicados
salvar a : ( ) .
finales de interfaz familyBL
El cdigo fuente para el familyBL clase no se presenta aqu. Usted puede
leer una vez que se carga el cdigo del ejemplo suministrado en el IDE. No
debe haber sorpresas. Lo hace las mismas actividades que se llevaron a
cabo en la capa de negocio del tutorial anterior (Prolog visual fundamental la capa de negocio lgico). Sin embargo, hay dos diferencias importantes:
all donde el acceso a datos o la creacin de los datos que se necesita, los
predicados de la clase familyDL se utilizan. Adems, los predicados de esta
clase de comprobar la validez de la informacin y crear excepciones en el
caso de los errores lgicos se encuentran.
El paquete contiene una clase ms: familyBL_exception . Esta clase es
similar a la que nos encontramos en la capa de datos.Pero esta vez,
contiene los predicados de servicios pblicos que se utilizan para crear
excepciones, cuando los predicados de capa de negocio est en el trabajo.

Caractersticas de una capa de datos


La caracterstica principal de una capa de datos, es que implementa un
conjunto de predicados referidos colectivamente como los descriptores de
acceso de datos en lenguajes orientados a objetos. Un acceso de
datos desacopla de acceso a datos de la aplicacin subyacente. En trminos
ms simples, se utiliza predicados a establecer y obtener los datos
utilizados por el programa. Los datos reales se mantendra privado e
inaccesible desde el exterior.
De acceso de datos tambin puede proporcionar una interfaz uniforme para
acceder a los atributos de los datos, dejando la organizacin concreta de
los atributos ocultos.
La ventaja de utilizar de acceso de datos es que los algoritmos
implementados en otras reas del programa puede ser escrito
independiente del conocimiento sobre la estructura de datos exacta que se
utiliz en la capa de datos. En el siguiente tutorial de esta serie, se vera
que los datos pueden ser fcilmente trasladado a un sistema ms slido
(con la base de datos de Microsoft Access, acceso a travs de una capa
ODBC), manteniendo todo lo dems exactamente lo mismo.
Casi no hay obstculos a este enfoque, pero cualesquiera que sean, estas
trampas debe ser entendido. La principal es que los dos niveles ms
sofisticados de entendimiento tiene que ser alcanzado por el programador

al escribir la capa de datos .Una de ellas sera para determinar las


estructuras de datos internas que se mantendr en privado dentro de la
capa de datos.(El tipo de pensamiento, necesarios para desarrollar las
estructuras de datos, se discuti en el tutorial de Visual Prolog fundamental
en relacin con funtores). Pero despus de eso, el programador tambin
tendr que pasar tiempo en el diseo eficiente de acceso de datos a fin de
que los predicados de las otras capas son capaces de reproducirse sin
problemas con lacapa de datos . El diseo incorrecto de los datos de
acceso predicados a menudo pueden crear un montn de dolores de
cabeza, cuando un equipo de programadores es en el trabajo. Sobre todo,
cuando el programa se requiere para pasar de una simple a una ms
compleja ... como usted se dara cuenta en el siguiente tutorial.

Conclusin
En este tutorial se utiliz una estrategia de " ensear a la pesca del
programa y no darle el pescado "en nuestro programa. Esto no es sino
modularizacin del cdigo fuente del software inteligente para que el
mantenimiento del cdigo y la extensin del cdigo se convierte en
extremadamente simple. Nos separamos de la capa de negocios antiguo del
tutorial anterior en dos partes: una lgica contenida negocio puro y el otro
maneja slo los datos. Esto nos permite extender el programa ms tarde y
simplemente reemplazar la capa de datos con otras formas de tcnicas de
manejo de datos (por ejemplo, a travs de los datos obtenidos a travs de
un protocolo ODBC, oa travs de Internet, etc) Este tutorial tambin el
manejo cubierta excepcin y descubrimos que , lo fcil que es escribir
nuestra propia excepcin elevar los predicados, y las usar para mostrar
mensajes de error inteligentes para el usuario.

También podría gustarte