Turning failure based loop into DCG recursion

Hello,

I have a simple failure based loop that backtracks over all solutions of a predicate. The loop is part of an export routine with a header and the failure based loop exporting a table one row at a time.

I’d like to use DCG instead, but can’t figure out how to “advance” backtracked solution in DCG …

Something like this:

export_all :- open_file(Out), print_header(Out), print_lines(Out), close_file(Out).

instead i want:

export_all → open_file(Out), print_header(Out), print_lines(Out), close_file(Out).
open_file → { open_file(Out) }
print_header(Out) → {print_header(Out}
print_lines → {print_line(Out), print_lines(Out)}
close_file(Out) → close_file(Out).

print_line(Out) :- get_line(Line), format(Out, ‘~w’, [Line]).

So, how do I advance get_line(Line) via backtracking and while letting the DCG do the backtracking.

any thoughts would be great.

Dan

Add another print_lines predicate, and another print_line predicate, for when the end of the file is reached.

Simple example: SWI-Prolog predicate for reading in lines from input file - Stack Overflow

Thank you.

I don’t grasp it … with external input there seems to be some lazy read – i.e. the next read state is handled by each read.

Whereas within prolog what advances to the next line in get_line(Line) …

Note: get_line(Line) basically recalls prolog facts.

In that case, a DCG won’t work.

Could use e.g. forall/2 to loop over the facts.

I am not sure how forall could be used in combination with DCG …

Also, I rather want to avoid loading all solutions into memory just to get it to work with DCG

One idea i had was to look at lazy lists to turn a fact look up into a lazy list, in the hope that every new get_line(Line) would retrieve a next fact from a lazy list … not sure if this can be done.

https://www.swi-prolog.org/pldoc/doc/_SWI_/library/lazy_lists.pl

I think your scenario description is missing some pieces. Such as:

  • What’s the data source? A text file?
  • Why are you ending up with facts, to iterate through?

If your input is a text file, then presumably you want to write a DCG to parse the lines in that, and which also outputs the processed line, before moving on to the next line.

Indeed, I now realize, I didn’t give full information – adding to confusion.

DCG can be used in more than one “mode”. Typically, DCG is used to parse input text. However, DCG can as well be used to generate output text.

In my case, i want to use DCG to specify an structure that generates for exporting tables into a file.

So, the source is the prolog internal fact base that DCG is supposed to read as it generates tables.

There is foreach//2 and foreach//3. That might help you. But your questions are really hard to decipher. You don’t even use code blocks for your code…

?- [user].
|: t(one). t(two). t(four).
|: ^D% user://1 compiled 0.00 sec, 3 clauses
true.

?- use_module(library(dcg/basics)), use_module(library(dcg/high_order)).
true.

?- portray_text(true).
true.

?- phrase(("header--", foreach(t(X), atom(X), ";"), "--footer"), Codes).
Codes = `header--one;two;four--footer`.

thank you.

Could you deconstruct the example so it looks like a DCG declaration that is the parsed …

I do not understand your question :man_shrugging:t2:

Boris,

In your example you included DCG syntax inside of phrase, how would this look like if the syntax is placed external to phrase in the file.