DCG Expansion: Is Steadfastness ignored?

前端 未结 1 1441
名媛妹妹
名媛妹妹 2020-12-10 18:26

Assume I have the following DCG rule:

 factor(X) --> \"(\", expr(X), \")\".

Normally this would be translated to:

 facto         


        
相关标签:
1条回答
  • 2020-12-10 19:27

    Your translation is a valid one. It does not influence steadfastness. However, it still might not be very desirable. But this depends on the precise implementation you employ. Consider:

    opcl --> "".
    opcl --> "(", opcl, ")".
    

    With Prolog flag double_quotes set to chars, the second clause now might be expanded to

    opcl1(['('|S0],S) :-
       opcl1(S0,S1),
       S1 = [')'|S].
    

    or

    opcl2(['('|S0],S) :-
       opcl2(S0,[')'|S]).
    

    Now consider the goal phrase(opcl,"(((())))".

    On common machines like WAM (e.g. YAP, SICStus), ZIP (SWI), TOAM Jr. (B):

    opcl1

    opcl1 will simply test the validity of the list, using the call-stack for the procedural control. On success, no cons-cell will have been created, and the call-stack will be empty again. Actually, above implementations are not able to detect that the goal is determinate, so they will leave one choice-point open. You can see this on the toplevel:

    ?- phrase(opcl,"(((())))").
    true ;
    false.
    

    This choice-point can be cleanly and safely removed with call_semidet/1.

    opcl2

    opcl2 will create four instances of [')'|_] on the heap that need to be reclaimed by GC. But they are saving the call-stack. That is, there will be only tail-recursive calls which are very efficiently handled on WAM, minimally less efficiently on TOAM Jr. and relatively costly on SWI.

    Things become even more costly when we are considering execution with occurs-check. In Qu-Prolog it is always on, and in SWI, XSB, and CX you can enable it with a flag like so:

    ?- phrase(opcl,Xs,Xs).
    true ;
    Xs = ['(',')'|Xs] ;
    Xs = ['(','(',')',')'|Xs] ...
    
    ?- set_prolog_flag(occurs_check,true).
    true.
    
    ?- phrase(opcl,Xs,Xs).
    true ;
    **LOOPS**
    

    SWI does not need to perform a single occurs-check for opcl1. But it does so for each ) in opcl2.

    So for these machines, your translation does not appear favorable. But it might be of interest for another machine, where there is no separate call-stack and which is not based on continuations.

    call//1

    Your translation will change the precise connection within call//1. However, the goal within call//1 must always be written in a manner such that it is steadfast! Otherwise, the difference could be seen already when calling phrase(call(Cont),Xs0,Xs)! For a conforming Cont this will be the same as phrase(call(Cont),Xs0,XsC), XsC=Xs


    As to your quote about steadfastness: It is a very informal definition of the notion. After all, what means "wrongly"?

    The best definition of steadfastness for phrase/3 so far, I am aware of is:

    phrase(NT, Xs0,Xs) and phrase(NT, Xs0, XsC), XsC = Xs with XsC a fresh new variable, are always the same.

    0 讨论(0)
提交回复
热议问题