list - programacion - ¿Cómo ''devolver'' un valor en prolog?
programacion en prolog (1)
Lo que intento hacer es agregar elementos de dos listas a otra y al final obtener el valor de la nueva lista en la consola. Mis listas son: A = [a, b]; B (lista de pares) = [(c, cc), (a, aa), (b, bb)] Quiero agregar el segundo elemento del par de la lista B si el primer elemento coincide con el primer elemento del par (diccionario principio) Y quiero que todos esos elementos se agreguen en una lista vacía que la consola generará. Lo que tengo hasta ahora es esto (X sería la lista vacía):
aa(_, [], _) :-
true.
aa([H|T], [(A, B)|T2], X) :-
H == A ->
append([B], X, X2), aa([H|T], T2, X2);
aa([H|T], T2, X).
En la consola estoy escribiendo: read(X), trace,aa([a, b], [(c, cc), (a, aa), (b, bb)], X), write(X).
Pero sigue devolviendo el valor [] de X. ¿Cómo puedo obtener el valor de X2 como salida si estoy pidiendo X? Aquí está el resultado del rastreo:
Call:aa([a, b], [(c,cc), (a,aa), (b,bb)], [])
Call:a==c
Fail:a==c
Redo:aa([a, b], [(c,cc), (a,aa), (b,bb)], [])
Call:aa([a, b], [(a,aa), (b,bb)], [])
Call:a==a
Exit:a==a
Call:lists:append([aa], [], _2110)
Exit:lists:append([aa], [], [aa])
Call:aa([a, b], [(b,bb)], [aa])
Call:a==b
Fail:a==b
Redo:aa([a, b], [(b,bb)], [aa])
Call:aa([a, b], [], [aa])
Exit:aa([a, b], [], [aa])
Exit:aa([a, b], [(b,bb)], [aa])
Exit:aa([a, b], [(a,aa), (b,bb)], [])
Exit:aa([a, b], [(c,cc), (a,aa), (b,bb)], [])
Call:write([])
[]
Exit:write([])
No es una buena idea poner el ;
al final de una línea, es muy fácil pasarlo por alto. Prefiero un formato diferente, ver abajo. En cuanto a su pregunta, tiene los argumentos para append/3
en el orden incorrecto. X2
es el resultado intermedio de la llamada recursiva, y el resultado que desea "devolver" es la combinación de este X2
con el elemento B
:
aa(_, [], _) :-
true.
aa([H|T], [(A, B)|T2], X) :-
( H == A
-> append([B], X2, X), aa([H|T], T2, X2)
; aa([H|T], T2, X) ).
El append([B], X2, X)
objetivo append([B], X2, X)
puede escribirse más claramente como X = [B|X2]
.
Esto soluciona el problema inmediato, pero aún no todo el predicado:
?- aa([a, b], [(c, cc), (a, aa), (b, bb)], X).
X = [aa|_G22] ;
false.
Descompones el primer argumento en [H|T]
pero no realizas una recursión sobre esta lista, por lo que nunca miras b
y su elemento correspondiente en la lista de pares.
Aquí hay una manera simple de hacer todo:
aa([], _Pairs, []).
aa([Key|Keys], Pairs, Values) :-
( member((Key, Value), Pairs)
-> aa(Keys, Pairs, Values0),
Values = [Value|Values0]
; aa(Keys, Pairs, Values) ).
La idea clave aquí es que una vez que conoce una Key
, puede buscar un par (Key, Value)
en su lista de pares. Value
valor aún no está vinculado a un valor y el member/2
creará una instancia si la lista contiene un par cuyo primer elemento es Key
. ¡Este es el poder de la unificación!
Esto parece funcionar:
?- aa([a, b], [(c, cc), (a, aa), (b, bb)], X).
X = [aa, bb].
Finalmente, es probable que no desee tener una read(X)
antes de esto, ya que eso significa que el usuario debe predecir la solución.