[m-users.] Inst error on !IO mode in DCG rule

Sean Charles (emacstheviking) objitsu at gmail.com
Mon May 17 17:47:18 AEST 2021


Excellent explanation as usual Zoltan. I get it now, and the printer paper analogy really really made the light come on about that.
As it turned it, the logic didn’t feel right

> On 17 May 2021, at 02:45, Zoltan Somogyi <zoltan.somogyi at runbox.com> wrote:
> 
> 
> 2021-05-17 06:36 GMT+10:00 "Sean Charles (emacstheviking)" <objitsu at gmail.com>:
>>    execute(Input, !IO) :-
>>        lexer.on_string(chomp(Input), Lx, !IO),
>>        % dump_lexer(Lx, !IO),
>>        ( if lex_error(Lx) = yes(ok_eob) then
>>              io.format("DCG this: %s\n", [s(string(tokens(Lx)))], !IO),
>> 96 ===>       ( if parse_cmd(!IO, tokens(Lx), _) % do I care what's left?
>>              then io.format("DID IT\n", [], !IO)
>>              else io.format("PARSE FAILED\n", [], !IO)
>>              )
>>        else
>>            io.format("%sERROR! %s\n”,
>>                [s(prompt), s(string(lex_error(Lx)))], !IO)
>>        ).
> 
> The condition of that if-then-else does two things.
> 
> 1: It calls parse_cmd, which destroys the old state of the world (call it IO_0)
>    and creates a new state of the world (call it IO_1).  This code is det,
>    i.e. it cannot fail.
> 
> 2: It checks whether the third arg returned by parse_cmd is unifiable
>    with tokens(Lx). This code is semidet, i.e. it can fail.
> 
> You are getting the error because the compiler knows that  if the
> unification with tokens(Lx) fails, then the condition as a whole fails,
> and execution would have to go on to the else case, *with the current
> state of the world being IO_0*. (This is because the semantics of
> an if-then-else is "either execute the conjunction of the condition
> and then then-part, or execute the else-part, depending on whether
> the condition succeeds.) But the compiler also knows that the
> call to parse_cmd destroyed IO_0, and there is no way to get it back.
> It's like you tell a printer to print something, then later tell it
> never mind, give me back the blank paper you started with.
> In other words, you cannot do I/O in places that can be
> backtracked over.
> 
> The fix is simple. Move the call to parse_cmd to *before* the if-then-else,
> and leave only the test of whether the third arg it returns is tokens(Lx)
> in the condition.
> 
> Zoltan.



More information about the users mailing list