prolog format dcg

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