[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