prolog - DCG para salida de archivo
format (1)
Considere primero una solución pura, utilizando DCG para traducir una lista de cosas que una persona le gusta a una lista de instrucciones de formato que luego pueden interpretarse:
person_likes(Who, Whats) -->
atom(Who), atom('': ''),
likes_(Whats).
likes_([]) --> [newline].
likes_([X]) --> atom(X), [newline].
likes_([X,Y|Rest]) --> atom(X), atom('', ''), likes_([Y|Rest]).
atom(A) --> [atom(A)].
Como puede ver, la idea clave es distinguir los casos según la cantidad de elementos en la lista. Esto le muestra cómo resolver estos problemas muy generalmente.
Ya puedes usarlo así:
?- phrase(person_likes(bob, [cake,pie]), Instrs).
Instrs = [atom(bob), atom('': ''), atom(cake), atom('', ''), atom(pie), newline].
Para el resultado deseado, simplemente interprete estas instrucciones de formato. Por ejemplo:
output(newline) :- nl.
output(atom(A)) :- format("~w", [A]).
Consulta de muestra, con sus hechos de ejemplo:
?- male(M), findall(W, likes(M,W), Whats),
phrase(person_likes(M,Whats), Ts),
maplist(output, Ts), false.
Flexible:
bob: cake, pie, apple
dave: fish, meat, potato, pear
fred: water, beer
dereck: wine, cake
Por supuesto, puede usar el mismo patrón para obtener una versión más corta e impura (usando efectos secundarios) en este caso concreto. ¡Pero entonces no puedes usarlo en la otra dirección! Entonces, vale la pena estudiar la versión pura.
Si tengo un programa como este y quiero el último elemento para que una persona no tenga una coma, ¿cómo puedo hacer esto? ¿Es mejor usar un DCG? ¿Cómo funcionaría eso?
male(bob).
male(dave).
male(fred).
male(dereck).
likes(bob,cake).
likes(bob, pie).
likes(bob, apple).
likes(dave, fish).
likes(dave, meat).
likes(dave, potato).
likes(dave, pear).
likes(fred, water).
likes(fred, beer).
likes(dereck, wine).
likes(dereck, cake).
print:-
forall(
male(Person),
(
format("~w, ",[Person]),
forall(
likes(Person,Item),
format("~w, ",[Item])
),
format("~n~n",[])
)
).
El out put es:
bob, cake, pie, apple,
dave, fish, meat, potato, pear,
fred, water, beer,
dereck, wine, cake, %<I dont want these last commas