[m-users.] How do you go about logging?

Paul Bone paul at bone.id.au
Mon Apr 7 15:05:05 AEST 2014


On Sun, Apr 06, 2014 at 09:20:54AM +0300, Left Right wrote:
> Thanks for reply! But wouldn't you mind elaborating a bit? Here's what
> I've tried, with the error message that resulted:
> 
> % e3.m:011: Error: trailed mutable in non-trailing grade.
> % e3.m:018: In clause for `nonedivides(in, out)':
> % e3.m:018:   in argument 2 of call to predicate `io.write_string'/3:
> % e3.m:018:   unique-mode error: the called procedure would clobber
> its argument,
> % e3.m:018:   but variable `STATE_VARIABLE_IO_9' is still live.
> % e3.m:020:   The goal could not be reordered, because it was followed by an
> % e3.m:020:   impure goal.
> % e3.m:016:   This is the location of the impure goal.
> 
> :- mutable(logging_level, int, 0, ground, []).
> 
> :- pred nonedivides(int::in, list(int)::out) is semidet.
> nonedivides(_, []).
> nonedivides(Test, [Factor | Factors]):-
>     trace [io(!IO), state(logging_level, !LoggingLevel)]
>     (!.LoggingLevel > 1 ->
>      io.write_string("Factor = ", !IO),
>      io.write(Factor, !IO),
>      io.nl(!IO) ; true),
>     Factor mod Test \= 0, nonedivides(Test, Factors).
> 

it might be simplier to avoid module local mutables for now.

Try making the trace goal conditional on either a runtime or compile time
flag instead.  For example:

:- pred nonedivides(int::in, list(int)::out) is semidet.

nonedivides(_, []).
nonedivides(Test, [Factor | Factors]) :-
    trace [io(!IO), compile_time(flag("debug"))] (
        ( !.LoggingLevel > 1 ->
            io.write_string("Factor = ", !IO),
            io.write(Factor, !IO),
            io.nl(!IO)
        ;
            true
        )
    ),
    Factor mod Test \= 0, nonedivides(Test, Factors).

Then add --trace-flag debug to the mmc command line to enable this trace
goal.  One of the benifits of trace goals (rather than unchecked impurity)
is that they 1) cannot bind variables 2) Can eaisly be turned off.  Combined
this means that they're less likely to affect the program's semantics,
unlike conditional compilation in languages like C.

Note that this clearer syntax also makes the control flow of your
if-then-else goal clearer to the reader (future you).

Also your 3 calls to write out the status can be replaced with a single
call:
    io.format("Factor = %d\n", [i(Factor)], !IO)

Thanks.


-- 
Paul Bone



More information about the users mailing list