3

The following meta-predicate is often useful. Note that it cannot be called maplist//2, because its expansion would collide with maplist/4.

maplistDCG(_P_2, []) -->
   [].
maplistDCG(P_2, [A|As]) -->
   {call(P_2, A, B)},
   [B],
   maplistDCG(P_2, As).

There are several issues here. Certainly the name. But also the terminal [B]: should it be explicitly disconnected from the connecting goal?

Without above definition, one has to write either one of the following - both having serious termination issues.

maplistDCG1(P_2, As) -->
   {maplist(P_2, As, Bs)},
   seq(Bs).

maplistDCG2(P_2, As) -->
   seq(Bs),
   {maplist(P_2, As, Bs)}.

seq([]) -->
   [].
seq([E|Es]) -->
   [E],
   seq(Es).
false
  • 10,264
  • 13
  • 101
  • 209
  • I don't get fully your question: I can see that [dcgutils](http://www.swi-prolog.org/pack/list?p=dcgutils):[seqmap](http://www.swi-prolog.org/pack/file_details/dcgutils/prolog/dcg_core.pl?show=src) family take a different approach than yours... – CapelliC Oct 31 '15 at 19:49

1 Answers1

2

Does {call(P_2,A,B)}, [B] have advantages over [B], {call(P_2,A,B)}?
(And, if so, shouldn't maplist/3 get something like that, too?)

Let's put corresponding and non- variants side-by-side1:

  1. [B],{call(P_2,A,B)} and non- Bs0 = [B|Bs], call(P_2,A,B)

    maplistDCG(_,[]) --> [].        %     maplist(_,[],[]).          
    maplistDCG(P_2,[A|As]) -->      %     maplist(P_2,[A|As],Bs0) :- 
       [B],                         %        Bs0 = [B|Bs],    
       {call(P_2,A,B)},             %        call(P_2,A,B),
       maplistDCG(P_2,As).          %        maplist(P_2,As,Bs).     
    
  2. {call(P_2,A,B)},[B] and non- call(P_2,A,B), Bs0 = [B|Bs]

    maplistDCG(_,[]) --> [].        %     maplist(_,[],[]).
    maplistDCG(P_2,[A|As]) -->      %     maplist(P_2,[A|As],Bs0) :-
       {call(P_2,A,B)},             %        call(P_2,A,B),
       [B],                         %        Bs0 = [B|Bs],
       maplistDCG(P_2,As).          %        maplist(P_2,As,Bs).
    

Above, we highlighted the goal ordering in use now:

If we consider that ...

  • ... termination properties need to be taken into account and ...

  • ... and non- variants should better behave the same2 ...

... we find that the variable should not be explicitly disconnected from the connecting goal. The natural DCG analogue of maplist/3 is maplistDCG//2 defined as follows:

maplistDCG(_,[]) -->
   [].
maplistDCG(P_2,[A|As]) -->
   [B],
   {call(P_2,A,B)},
   maplistDCG(P_2,As).

Footnote 1: To emphasize commonalities, we adapted variable names, code layout, and made some unifications explicit. Footnote 2: ... unless we have really good reasons for their divergent behaviour ...

Community
  • 1
  • 1
repeat
  • 18,496
  • 4
  • 54
  • 166