Re: [m-users.] Free and Ground in the same error line?
"Zoltan Somogyi" <[email protected]> Tue, 31 Oct 2023 23:41:20 +1100 (AEDT)
| Newsgroups | gmane.comp.lang.mercury.general |
|---|---|
| Message-ID | <[email protected]> |
On 2023-10-31 23:13 +11:00 AEDT, "Julien Fischer" <[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 ... 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. 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. 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