Re: [m-users.] Free and Ground in the same error line?
"Sean Charles (emacstheviking)" <[email protected]> Tue, 31 Oct 2023 15:38:13 +0000
| Newsgroups | gmane.comp.lang.mercury.general |
|---|---|
| Message-ID | <[email protected]> |
> On 31 Oct 2023, at 12:41, Zoltan Somogyi <[email protected]> wrote: > > > On 2023-10-31 23:13 +11:00 AEDT, "Julien Fischer" <[email protected] <mailto:[email protected]>> wrote: >> >> On Sat, 28 Oct 2023, Sean Charles (emacstheviking) wrote: >> >>> I rewrote it like this, could it be any leaner? Asking in case I am not as good as I can be yet :D ! >>> 384 get_class_superclass(Class, Super, !X) :- >>> 385 ( if !.X = [ tk(Cp, Cb) | Rest ] then >>> 386 Class = ps(Cp, Cb), >>> 387 Super = no, >>> 388 !:X = Rest >>> 389 else if !.X = [ sexp(_, [ tk(Cp, Cb), tk(Sp, Sb) ]) | Rest ] then >>> 390 Class = ps(Cp, Cb), >>> 391 Super = yes(ps(Sp, Sb)), >>> 392 !:X = Rest >>> 393 else >>> 394 fail >>> 395 ). > > Note that you *can* write the condition of that first if-then-else as > > if !.X = [tk(Cp, Cb | !:X] then ... Intersting! > > I expect that you wrote Rest in place of !:X there because you cannot bind > variables visible from outside the if-then-else in the condition. Yes, exactly that, the compiler has conditioned me. > State variable syntax is not an exception to that, but it looks like an exception. > The reason is that the compiler, of course, knows this rule. Therefore if > the condition updates a state variable, then the compiler will itself > add the unification that corresponds to !:X = Rest in your code. I will do this and see for myself. > > In concrete terms, if the version of !X just before the if-then-else is > version 0 (the initial version, as in this case), and the condition updates it > to the next version, version 1, then the compiler knows that version 1 cannot > be made visible outside the if-then-else. So if the then-part does not itself > update !X to a version later than 1, then the compiler will do so itself, > by adding a unification between versions 1 and N in the then-part, > and will make version N the version visible in the code after the if-then-else. > N will be the maximum of 2 and whatever the current version at the end of > the else part is. > > It is therefore possible, and meaningful, to write code such as > > ( if !.X = ["abc" | :!X] then > true > else > true > ) > > If !.X is a list of strings, then this will remove an initial "abc" > from that list, if the list starts with that string. The then-part > does not have to do anything. The work is done by the condition, > and the then-part just passes its result to the code after the if-then-else. > >>>> I mean, it's fine but in the manual, 2.13 DCG-rules it says "As a >>> matter of style, we recommend that in future DCG notation be reserved >>> for writing parsers and sequence generators, and that state variable >>> syntax be used for passing state threads." >> >> I would not read too much into that recommendation. It was written as >> part of the change that added state variables to the Mercury language. >> At that point, no one had much experience using, for parsers or sequence >> generators, or anthing else. My opinion, with the benefit of twenty >> years of hindsight, is don't use DCGs. (The one exception to that >> might be if I were in the process of porting an existing Prolog >> program to Mercury.) > > I agree with that. I would also add, in response to an earlier email > in this thread, that while you *can* use both DCGs and state variables > in a single clause, you definitely *shouldn't*. That is just asking for > trouble, in that any future maintainer of that code will curse your name :-( > And that will be true even if that maintainer is an future. version of you. > > Zoltan. _______________________________________________ users mailing list [email protected] https://lists.mercurylang.org/listinfo/users