質問: [] で全ての行が終了した時点で 述語も真で終わりたいからです。その問題がなければ、member/2 で良い筈です。 ``` 一行ずつ表示する(Outstream,LL) :- member(L,LL), concat_atom(L,_区切り符号,_行表示), swritef(_改行付き行表示,'%t\n',[_行表示]), write(Outstream,_改行付き行表示), fail. 一行ずつ表示する(_,_). ``` このスタイルを嫌ったのが上記の append/3 を使った定義ということになります。さて、他に これに代わる表現はないでしょうか?
回答: forall/2とmember/2を組み合わせて繰り返し処理を行うことができます。 ``` save_as_csv_file(File, Separator, Table) :- open(File, write, Out), forall(member(Row, Table), write_csv_line(Out, Separator, Row)), close(Out), !. write_csv_line(Out, Separator, Row) :- concat_atom(Row, Separator, Line), swritef(LineNL, '%t\n', [Line]), write(Out, LineNL). ``` この書き方では、TableのそれぞれのメンバーRowに対してwrite_csv_lineの処理を行うことが、素直に表現できています。 もちろん、これを読む人間はforall/2の使い方を知っていなければ内容を理解できません。しかし失敗駆動を直接使ったループでは、失敗の後どこまでバックトラックするのかをプログラムから読み取るのは容易でなく、プログラムを読む人間に負担を強いることになります。