[m-users.] Free and Ground in the same error line?
Sean Charles (emacstheviking)
objitsu at gmail.com
Wed Nov 1 02:38:13 AEDT 2023
> On 31 Oct 2023, at 12:41, Zoltan Somogyi <zoltan.somogyi at runbox.com> wrote:
>
>
> On 2023-10-31 23:13 +11:00 AEDT, "Julien Fischer" <jfischer at opturion.com <mailto:jfischer at opturion.com>> 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.
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.mercurylang.org/archives/users/attachments/20231031/5955d4d0/attachment-0001.html>
More information about the users
mailing list