Title: Sin ttulo de diapositiva
1VI. Meta-cláusulas
Jorge Cabrera Gámez Departamento de Informática y
Sistemas Universidad de Las Palmas de Gran Canaria
2- Índice.
- Manipulación de la base de datos
- Declaración de propiedades de predicados
- Construcción y descomposición de términos
- Como obtener todas las respuestas sin
- backtracking bagof, setof y findall
-
3Manipulación de la base de datos
Programa Prolog lt----gt Base de datos
Base de datos Conjunto de cláusulas que hemos
ensamblado antes de iniciar la ejecución
del programa.
Prolog dispone de un conjunto de predicados
predefinidos para modificar la base de datos de
forma dinámica
4asserta(X) Añade la cláusula X como la
primera cláusula de este predicado. Como
otros predicados de E/S siempre falla en el
backtracking y no deshace sus propios cambios.
assertz(X) Como asserta/1, sólo que
añade la cláusula X como la última cláusula
del predicado. retract(X) Borra la
cláusula X de la base de datos. Como en los
casos anteriores no es posible deshacer los
cambios debidos a este predicado en el
backtraking.
5Ejemplo
?- más_lento(A,B). A juan B ana No
?- más_lento(A,B). A juan B ana A
juan B patricia No
?- más_rápido(A,B). A ana B juan A
patricia B juan No
?- listing(rápido). rápido(patricia). Yes ?-
más_rápido(A,B). A patricia B juan No
?- más_rápido(A,B). A patricia B juan A
patricia B tomás No
?- más_rápido(A,B). No
?- más_lento(A,B). WARNING Undefined predicate
más_lento/2' No
rápido(ana). lento(juan). más_lento(X,Y)-
lento(X), rápido(Y).
?- assert((rápido(patricia))). Yes ?-
listing(rápido). rápido(ana). rápido(patricia). Ye
s
?- assert( (más_rápido(X,Y)-
rápido(X),lento(Y))). ?- listing(más_rápido). más
_rápido(A, B) - rápido(A),
lento(B). Yes
?- listing(rápido). rápido(ana). rápido(patricia).
Yes ?- retract(rápido(ana)). Yes
?- assertz(lento(tomás)). Yes ?-
listing(lento). lento(juan). lento(tomás). Yes
?- retract( (más_lento(X,Y)-
lento(X), rápido(Y))). X _G339 Y _G340 Yes
?- retractall(lento(X)). Yes ?-
listing(lento). Yes
6Es posible definir variables globales en Prolog?
Ejemplo adaptado del tutorial de Amzi
Prolog -dynamic aquí/1. ir(Lugar)-
puedo_ir(Lugar), moverse(Lugar). puedo_ir(
Lugar)- aquí(X), conectado(X,
Lugar).
conectado(cocina, recibidor). conectado(recibidor,
cocina). conectado(cocina, despensa). conectado(d
espensa, cocina). conectado(cocina,
comedor). conectado(comedor, cocina). conectado(co
medor, estar). conectado(estar,
comedor). aquí(cocina).
moverse(Lugar)- retract(aquí(_)),
asserta(aquí(Lugar)).
SWI-Prolog
7M (a to b), (a to c), (b to c), (a to b),
(c to a), (c to b), (a to b)
M (a to b), (a to c), (b to c), (a to b),
(c to a), (c to b), (a to b)
M (a to b), (a to c), (b to c), (a to b),
(c to a), (c to b), (a to b)
M (a to b), (a to c), (b to c), (a to b),
(c to a), (c to b), (a to b)
M (a to b), (a to c), (b to c), (a to b),
(c to a), (c to b), (a to b)
M (a to b), (a to c), (b to c), (a to b),
(c to a), (c to b), (a to b)
M (a to b), (a to c), (b to c), (a to b),
(c to a), (c to b), (a to b)
A
B
C
Torres de Hanoi
8Otro uso interesante Memorización
hanoi_nm(N,A,B,C,Movimientos) Movimientos es la
secuencia de movimientos requeridos para mover N
discos del poste A al poste B usando el poste C
como intermediario de acuerdo con las reglas del
puzzle de las Torres de Hanoi / Sin
memorización / - op(1000, xfx,
to). hanoi_nm(1,A,B,C,A to B). hanoi_nm(N,A,B,C
,Movimientos) - N gt 1, N1 is
N-1, hanoi_nm(N1,A,C,B,Ms1), hanoi_nm(N1,C,B,A,M
s2), append(Ms1,A to BMs2, Movimientos).
SWI-Prolog
9Otro uso interesante Memorización
hanoi_nm(N,A,B,C,Movimientos) Movimientos es la
secuencia de movimientos requeridos para mover N
discos del poste A al poste B usando el poste C
como intermediario de acuerdo con las reglas del
puzzle de las Torres de Hanoi / Con memorización
/ - dynamic hanoi/5. - op(1000, xfx,
to). hanoi(1,A,B,C,A to B). hanoi(N,A,B,C,Moves
) - N gt 1, N1 is N-1, hanoi(N1,A,C,B,Ms1), h
anoi(N1,C,B,A,Ms2), append(Ms1,A to BMs2,
Moves), lema(hanoi(N,A,B,C,Moves)). lema(P) -
asserta((P - !)).
SWI-Prolog
10Aún con la memorización, la solución no es
perfecta, pues las soluciones que se memorizan
son soluciones de N discos y una secuencia
determinada de postes. Por ejemplo, la solución
de hanoi_ng(3,a,b,c,Moves) generará las
siguientes definiciones hanoi_ng(3, a, b, c,
(a to b), (a to c), (b to c), (a to
b), (c to a), (c to b), (a to b)) -
!. hanoi_ng(2, c, b, a, (c to a), (c to b), (a
to b)) - !. hanoi_ng(2, a, c, b, (a to b), (a
to c), (b to c)) - !. Es fácil advertir que
cuando se tenga que resolver el problema con 4
discos, hanoi_ng(4,a,b,c,Moves), no será posible
utilizar el problema de orden 3 ya resuelto
porque las identidades de los postes no
coinciden. Concretamente, Sería necesario tener
resueltos estos dos problemas hanoi_ng(3,a,c,b,M
s) y hanoi_ng(3,c,b,a,Ms) Nótese como el
programa memoriza dos soluciones diferentes para
el problema de dos discos.
11Para resolver este problema debemos
generalizar la solución descubierta para un
problema concreto (cierta secuencia de
postes) Sustituye en la secuencia de
movimientos (solución) el nombre de un poste
por una variable equivalente. subsWithVariable(
,_,)-!. subsWithVariable((X to
Y)Ms,Assocs,(VX to VY)VMs)- find_assoc(X,As
socs,VX), find_assoc(Y,Assocs,VY), subsWithVaria
ble(Ms,Assocs,VMs). find_assoc(A,(A,VA)_,VA)-
!. find_assoc(A,_Assocs,VA)- find_assoc(A,Ass
ocs,VA). Por ejemplo 6 ?- hanoi_nm(2,a,b,c,M1s)
, subsWithVariable(M1s,(a,A),(b,B),(c,C),
Moves). M1s (a to c), (a to b), (c to
b), Moves (A to C), (A to B), (C to B).
12-------------------------------------------------
Con memorización y generalización ------------
------------------------------------- hanoi(1,A,B,
_,A to B)- !. hanoi(N,A,B,C,Moves) - N gt
1, N1 is N-1, hanoi(N1,A,C,B,Ms1), hanoi(N1,C,B
,A,Ms2), append(Ms1,A to BMs2,
Moves), lema(hanoi(N,A,B,C,Moves)). lema(hanoi(N
,P1,P2,P3,Moves)) - subsWithVariable(Moves,(P1
,A),(P2,B),(P3,C),VMoves), asserta((hanoi(N,A,B,
C,VMoves)- !)).
13Otro ejemplo de Memorización
---------------------------- Computes the
next prime number and updates the list of
prime numbers ---------------------------- find_n
ext_prime(P,NP)- primes(Ps), NP is P1,
\is_div(NP,Ps), !, append(Ps,NP,EPs), updat
e_primes(EPs). find_next_prime(P,NP)- NC is
P1, find_next_prime(NC,NP). ------------------
---------- Updates (memoizes) a new list of
prime numbers ---------------------------- update
_primes(Ps)- ignore(retract(primes(_))), assert
(primes(Ps)).
- dynamic primes/1. ---------------------------
- An initial list of prime numbers. It grows
as needed ---------------------------- primes(2,
3,5,7,11,13,17,19). --------------------------
-- next_prime(P,NP) returns in NP the first
prime number that is greater than
P ---------------------------- next_prime(P,NP)-
primes(Ps), append(_,P,NP_,Ps), !. next_pr
ime(P,NP)- find_next_prime(P,NP).
14Otros predicados para manipulación de la base de
datos (SWI-Prolog)
retract/assert modificar la base de datos de
cláusulas. compilan el término que se les pasa
como argumento. son costosas. recorda/erase pe
rmiten grabar/borrar una base de datos de
términos. mecanismo más rápido que
assert/retract, pero no son cláusulas del
programa
15recorda(Key, Term) recorded(Key, -Valor,
-Referencia)
?- progenitor(A,B). WARNING Undefined
predicate progenitor/2' No ?-
listing(progenitor). WARNING No predicates for
progenitor' No
?- recorded(prg,V,R), Vprogenitor(luis,_),er
ase(R). V progenitor(luis, pedro) R 1733389
No ?- recorded(prg,V,R). V
progenitor(maría, pedro) R 1734589 No
?- recorded(prg,V,R), assert(V). V
progenitor(maría, pedro) R 1734589 No ?-
progenitor(X,Y). X maría Y pedro No
?- recorda(prg,(progenitor(maría,pedro))). Yes ?-
recorda(prg,(progenitor(luis,pedro))). Yes ?-
recorded(prg,Valor,Referencia). Valor
progenitor(maría, pedro) Referencia 1734589
Valor progenitor(luis, pedro) Referencia
1733389 No
16erase(Referencia) Puede emplearse tanto con
términos, como con cláusulas. abolish(PredicateI
ndicator) Elimina todas las cláusulas de un
predicado de functor Functor y aridad Aridad de
la base de datos. Todos los atributos de
predicado (dynamic, multifile, index, etc.)
toman su valor por defecto. Abolir un predicado
importado sólo elimina el enlace importado el
predicado mantendrá su antigua definición en el
módulo donde se define. De acuerdo con el
estándar ISO, abolish/1 sólo puede emplearse
sobre predicados dinámicos. Esto es extraño, ya
que para manejar este tipo de predicados ya se
dispone de retract/1 y retractall/1. El
predicado abolish/1 se introdujo en el DEC-10
Prolog precisamente para operar con definiciones
estáticas. En SWI-Prolog, abolish/1 funciona
sobre procedimientos estáticos, a menos el flag
iso se fije a true. Se aconseja emplear
retractall/1 para borrar todas las cláusulas de
un predicado dinámico.
17- flag(Key, -Old, New)
- Key is an atom, integer or term. As with
the recorded database, - if Key is a term, only the name and arity
are used to locate the flag. - Unify Old with the old value associated
with Key. If the key is - used for the first time Old is unified with
the integer 0. Then - store the value of New, which should be an
integer, float, atom - or arithmetic expression, under Key.
flag/3 is a fast mechanism - for storing simple facts in the database.
The flag database is - shared between threads and updates are
atomic, making it suitable - for generating unique integer counters.
- clause(?Head, ?Body)
- Succeeds when Head can be unified with a
clause head and Body - with the corresponding clause body.
Gives alternative clauses - on backtracking. For facts Body is
unified with the atom - true. Normally clause/2 is used to find
clause definitions for a - predicate, but it can also be used to find
clause heads for some - body template.
18Síntesis dinámica de reglas
- dynamic testme/0. knot(1, fetch(Variable)). kno
t(2, write(Variable)). dynrule - knot(1,
Rule1), knot(2, Rule2), assert(( testme -
Rule1, Rule2 )), listing(testme), testme. fetch
(A) - A 4.
?- dynrule. testme - fetch(A), write(B
). _L114 Yes
19- dynamic testme/0. knot(1, X,
fetch(X)). knot(2, X, write(X)). dynrule
- knot(1, X, Body1), NOT Rule1, because it
isn't a rule knot(2, X, Body2), NOT Rule2,
because it isn't a rule assert(( testme -
Body1, Body2 )), listing(testme), testme. fetch
(4).
?- dynrule. testme - fetch(A), write(A
). 4 Yes
20Declaración de propiedades de predicados
- dynamic - multifile - index(Head)
- dynamic aquí/0,
baz/2. dynamic Functor/Arity, \ldots Informa
al intérprete que la definición de los predicados
puede cambiar durante la ejecución (mediante
assert/retract)
- multifile antepasados/2. multifile
Functor/Arity, \ldots Informa al intérprete
que la definición de los predicados involucra más
de un fichero. Esto evita la redefinición un
predicado cuando se encuentra una nueva
definición en otro fichero.
21Fichero uno.pl - multifile p/1. -ensure_loaded
(dos.pl'). p(a). p(b). p(X) - q(X),
b(_). q(a). b(c). Fichero dos.pl p(_) -
b(d). b(d).
?- uno. dos.pl compiled, 0.05 sec, 620
bytes. WARNING (c/uno.pl9) Redefined
b/1 c/uno.pl compiled, 0.05 sec, 1,296 bytes.
?- listing(p). p(A) -
b(d). p(a). p(b). p(A) - q(A),
b(B) Yes
?- listing(b). b(c). Yes
22Declaración de propiedades de predicados
- dynamic - multifile - index(Head)
- index(sub_type(1, 1)). sub_type(horse,
animal). ... ...
- index(Head) Indiza las cláusulas del
predicado con el mismo nombre y aridad que el
argumento utilizando los valores de los
argumentos. Permite especificar sobre qué
argumentos se indiza este predicado (de los 32
primeros, máx. 4). Útil en predicados definidos
mediante numerosos hechos.
23Construcción y descomposición de términos
Existen tres predicados predefinidos para
descomponer términos o construir nuevos
términos Term .. L functor(Term, F,
N) arg(N, Term, A)
24?- f(a,b) .. L. L f, a, b ?- T ..
progenitor, miguel, maría T
progenitor(miguel, maría) ?- Z .. p, X, g(X,Y)
. Z p(X, g(X,Y))
Por qué nos puede interesar descomponer un
término en sus componentes?
Por qué nos puede interesar construir un nuevo
término a partir de un functor y sus argumentos?
25Ejemplo Consideremos un programa que manipula
figuras geométricas como cuadrados, círculos, ...
, que se representan por un functor que indica el
tipo de figura y unos argumentos que la
definen cuadrado(Lado) triángulo(Lado1, Lado2,
Lado3) círculo(Radio) Una de las operaciones a
realizar sobre las figuras aumenta(Fig, Factor,
Fig1)
26Ejemplo (Cont.) Una posibilidad aumenta(cuadra
do(A), F, cuadrado(A1)) - A1 is
AF. aumenta(círculo(R), F, circulo(R1)) - R1
is RF. aumenta(rectángulo(A,B), F,
rectángulo(A1,B1)) - A1 is AF, B1 is
BF. ... Funcionaría, pero no es elegante.
Especialmente si el número de figuras es grande.
27Ejemplo (Cont.) Un intento para agrupar todas
figuras que estén parametrizadas por un único
parámetro aumenta(Tipo(Par), F, Tipo(Par1)) -
Par1 is ParF. No está permitido en Prolog
ya que el functor debe ser un átomo y no una
variable.
28Ejemplo (Cont.) La solución aumenta(Fig, F,
Fig1) - Fig .. Tipo Parámetros, multiplica
_lista(Parámetros, F, Parámetros1), Fig1 ..
Tipo Parámetros1. multiplica_lista( ,_,
). multiplica_lista( X L, F, X1 L1)
- X1 is FX, multiplica_lista( L, F, L1).
29Ejemplo Intentemos definir el
predicado sustituye(Subterm, Term, Subterm1,
Term1) Term1 se obtiene de la sustitución de
todas las ocurrencias de Subterm en Term por
Subterm1. ?- sustituye(sen(x),
2sen(x)f(sen(x)), p, F). F 2pf(p)
30Ejemplo ?- sustituye(ab, f(a, AB), v, F). A
a B b F f(a, v) ?- sustituye(ab, AB, v,
F). A a B b F v
31Ejemplo
sustituye(Subterm, Term, Subterm1, Term1)
Si Subterm Term entonces Term1 Subterm1 en
otro caso Si Term es atómico entonces Term1
Term en otro caso la sustitución debe
realizarse en los
argumentos de Term
?- 2sen(x)f(sen(x)) .. F Args. F Args
2sen(x), f(sen(x))
32?- 2sen(x)f(sen(x)) .. F Args. F Args
2sen(x), f(sen(x))
?- sustituye(mi, mi,perro, en,mi,casa, tu,
F). F tu, perro, en, tu, casa Yes
Ejemplo
sustituye(Term, Term, Term1, Term1)-
!. sustituye(_, Term, _, Term)-
atomic(Term),!. sustituye(Sub, Term, Sub1,
Term1)- Term .. F Args, sust_lista(Sub,
Args, Sub1, Args1), Term1 .. F
Args1. sust_lista(_, ,_, ). sust_lista(Sub,
TermTerms, Sub1, Term1Terms1)
- sustituye(Sub, Term, Sub1, Term1), sust_lista
(Sub, Terms, Sub1, Terms1).
33Por qué no funciona sustituye/4 en el este caso?
?- sustituye(sen, sen(x), p, F). F sen(x)
?- sustituye(sen, sen(x), p, F). F p(x)
sustituye(Term, Term, Term1, Term1)-
!. sustituye(_, Term, _, Term)-
atomic(Term),!. sustituye(Sub, Term, Sub1,
Term1)- Term .. F Args, sustituye(Sub,
F, Sub1, F1), sust_lista(Sub, Args, Sub1,
Args1), Term1 .. F1 Args1. sust_lista(_,
,_, ). sust_lista(Sub,TermTerms, Sub1,
Term1Terms1) - sustituye(Sub, Term, Sub1,
Term1), sust_lista(Sub, Terms, Sub1, Terms1).
34Más ejemplos con univ (..) ...
- op(100, xfx, isf). R isf OPs - (
OPs .. F, A, C/D, integer(A) -gt OPs1 .. F,
A/1,C/D OPs .. F, A/B, C,
integer(C) -gt OPs1 .. F, A/B,C/1 ), !, R
isf OPs1. R isf OPs - OPs .. _, A,
B, integer(A), integer(B), !, R is OPs. R
isf OPs- OPs ..F,A,B, R1 isf A, R2 isf
B, OPs1 ..F,R1,R2, R isf OPs1.
35Un uso habitual de .. es el de sintetizar
nuevos objetivos obtener(Functor), calcular(ArgL
ist), Objetivo .. Functor ArgList Objetivo o
alternativamente, si sintácticamente se requiere
que el functor principal de un objetivo sea un
átomo, call(Objetivo)
36Otras veces nos interesará extraer el
functor principal de un término Se puede
emplear .., pero suele ser más práctico y
eficiente emplear functor y arg. functor(Term,
F, N) es cierto si F es el functor principal de
Term y N es la aridad de F arg(N, Term, A) es
cierto si A es el N-ésimo argumento de
Term cuando los argumentos se numeran de izda a
dcha empezando por 1.
37Ejemplo
?- functor( t( f(X), X, t), Fun, Arity). Fun
t Arity 3
?- arg( 2, f( X, t(a), t(b)), Y). Y t(a)
?- functor( D, fecha, 3), arg(1,D,29),
arg(2,D, junio), arg(3,D,1998). D fecha(29,
junio, 1998)
38Cómo cambiar un argumento (I) setarg/3 deshace
las asignaciones en el backtraking
?- F f( X, t(a), t(b)), setarg(2,F,t(c)). F
f(X, t(c), t(b)) Yes
setarg(Arg, Term, Value) Extra-logical
predicate. Assigns the Arg-th argument of
the compound term Term with the given Value.
The assignment is undone if backtracking
brings the state back into a position before
the setarg/3 call. See also nb_setarg/3.
This predicate may be used for destructive
assignment to terms, using them as an
extra-logical storage bin. Always try hard
to avoid the use of setarg/3 as it is not
supported by many Prolog systems and one
has to be very careful about unexpected copying
as well as unexpected not copying of terms.
39Cómo cambiar un argumento (II) nb_setarg/3 NO
deshace las asignaciones en el backtraking
?- F f( X, t(a), t(b)), nb_setarg(2,F,t(c)). F
f(X, t(c), t(b)) Yes
nb_setarg(Arg, Term, Value) Assigns the
Arg-th argument of the compound term Term
with the given Value as setarg/3, but on
backtracking the assignment is not
reversed. If Term is not atomic, it is
duplicated using duplicate_term/2. This
predicate uses the same technique as
nb_setval/2. We therefore refer to the
description of nb_setval/2 for details on
non-backtrackable assignment of terms.
This predicate is compatible to GNU-Prolog
setarg(A,T,V,false), removing the
type-restriction on Value. See also
nb_linkarg/3. Below is an example for
counting the number of solutions of a goal.
Note that this implementation is
thread-safe, reentrant and capable of
handling exceptions. Realising these features
with a traditional implementation based on
assert/retract or flag/3 is much more
complicated.
40Como obtener todas las respuestas sin backtracking
Una forma de obtener todas las respuestas
Agotar las posibilidades de vuelta-atrás
Otra Emplear los predicados bagof, setof y
findall
41?- bagof(Verdura, item(Verdura,Precio),
L). Verdura _G315 Precio 300 L coliflor
Verdura _G315 Precio 275 L pimiento
Verdura _G315 Precio 115 L lechuga
Verdura _G315 Precio 120 L tomates,
cebolla No
?- bagof(Verdura, item(Verdura,Precio),
L). Verdura _G315 Precio 300 L
coliflor Verdura _G315 Precio 275 L
pimiento Verdura _G315 Precio 115 L
lechuga Verdura _G315 Precio 120 L
tomates, cebolla No
bagof(X, P, L) Produce la lista L de todos los
objetos X que satisfacen el objetivo P.
Normalmente X es una variable en P.
item(tomates, 120). item(coliflor,
300). item(pimiento, 275). item(lechuga,
115). item(cebolla, 120).
?- bagof(Verdura, item(Verdura,120), L). Verdura
_G297 L tomates, cebolla Yes
?- bagof(Verdura, Precio item(Verdura, Precio),
L). Verdura _G351 Precio _G352 L tomates,
coliflor, pimiento, lechuga, cebolla
?- bagof(Precio,Verdura item(Verdura,Precio),
L). Precio _G352 Verdura _G351 L 120, 300,
275, 115, 120
?- bagof(Precio,Verdura item(Verdura,50),L). No
bagof(Verdura, item(Verdura,115), L).
42?- setof(Precio,Verdura item(Verdura,Precio),
L). Precio _G352 Verdura _G351 L 115, 120,
275, 300 (nótese la eliminación de duplicados y
la ordenación de menor a mayor)
?- setof(Verdura,Precio item(Verdura,Precio),
L). Verdura _G351 Precio _G352 L cebolla,
coliflor, lechuga, pimiento, tomates (nótese la
ordenación alfabética)
setof(X, P, L) Produce la lista L de todos los
objetos X que satisfacen el objetivo P.
Normalmente X es una variable en P.
Similar a bagof, pero ahora se eliminan los
duplicados y los elementos de la lista se
ordenan alfabéticamente y de menor a mayor.
item(tomates, 120). item(coliflor,
300). item(pimiento, 275). item(lechuga,
115). item(cebolla, 120).
43?- findall(Verdura,item(Verdura,_),L). Verdura
_G273 L tomates, coliflor, pimiento, lechuga,
cebolla Yes
?- findall(Verdura,item(Verdura,50),L). Verdura
_G279 L Yes
findall(X, P, L) Produce la lista L de todos los
objetos X que satisfacen el objetivo P. Si el
objeto X no verifica P, findall se verifica con L
?- findall(Precio,item(_,Precio),L). Precio
_G262 L 120, 300, 275, 115, 120 Yes
Similar a bagof y setof, pero ahora se incluyen
en la lista todos los elementos, incluso aquellas
soluciones que difieren en otras variables de P
item(tomates, 120). item(coliflor,
300). item(pimiento, 275). item(lechuga,
115). item(cebolla, 120).
44Otro ejemplo inspirado en el ejemplo del
restaurante
Problema Definir el predicado calorias_conocidas/
0 que indique todos los platos que no disponen de
la correspondiente definición de calorias
menu entrada(paella). entrada(gazpacho). entrad
a(langostinos). entrada(consome). entrada('sopa
de fideos'). carne(filete_de_cerdo). carne(solom
illo). carne(pollo_asado). pescado(trucha). pesca
do(bacalao). postre(flan). postre(natilla). postr
e(nueces_con_miel). postre(naranja).
Valor calorico de una racion calorias(paella,
200). calorias(gazpacho, 150). calorias(consome,
300). calorias(filete_de_cerdo,
400). calorias(pollo_asado, 280). calorias(trucha,
160). calorias(bacalao, 300). calorias(flan,
200). calorias(nueces_con_miel,
500). calorias(naranja, 50).
457 ?- calorias_conocidas. No hay definición
de calorias para "langostinos". No hay definición
de calorias para "sopa de fideos". No hay
definición de calorias para "solomillo". No hay
definición de calorias para "natilla". Yes
Verificación de que todos los platos
disponen de la correspondiente definición de
calorías calorias_conocidas - verifica_plato(
entrada), verifica_plato(carne), verifica_plato(
pescado), verifica_plato(postre). verifica_plato
(Plato)- P ..Plato, E, setof(E,P,Es), verif
ica_cal(Es). verifica_cal(EEs)- (
calorias(E,_) -gt true format('No
hay definición de calorias para
\w\.n',E) ), verifica_cal(Es). verifica_c
al().
46Sumario.
- Las implementaciones de Prolog proporcionan un
- conjunto de predicados metalógicos sumamente
útiles. - Que permiten construir o descomponer términos
- utilizando el operador .., functor o arg.
- Que permiten modificar la base de datos clausal
- utilizando assert, retract y sus variantes.
- Que proporcionan listas de objetos que
satisfacen una - cierta condición empleando bagof, setof o
findall.