[m-users.] IO and global state.

Sean Charles (emacstheviking) objitsu at gmail.com
Mon Apr 26 16:51:57 AEST 2021


Zoltan, Julien,

Thank you for your replies. I don’t think my application will remain ’small’ going forward but the one mitigating feature is that the values I want to save into the IO state are never going to change; they are the option_table values from a successful call to getopt, i.e. one where there were no unrecognised options and none that required immediate service and then termination e.g. help / version / list targets.

Excellent then, I shall happily save my constant data into IO state and see how it goes.

I do have one error I cannot figure out yet… I attempted to re-code my ‘debug_on’ predicate to use IO instead of the Options and I get an error I cannot yet figure out ( again :| )…

The exports:

:- func debug_on(felt_options) = bool.
:- func debug_on(io::di, io::uo) = bool.   % LINE 28, see error message below.


and the code:

    % helper: is debug_mode on or off ?
    %
debug_on(Options) = Mode :-
    Mode = getopt.lookup_bool_option(Options, options.debug_mode).

debug_on(!IO) = Mode :-
    io.get_globals(Options, !IO),
    Mode = getopt.lookup_bool_option(Options, options.debug_mode).


and I get the error message:

➜  f2 git:(develop) ✗ make
mmc -s hlc.gc -O4 -E --make felt
Making Mercury/int3s/options.int3
options.m:028: Error: some but not all arguments have modes.
options.m:028:   The argument without a mode is the return value.
** Error making `Mercury/int3s/options.int3'.
make: *** [felt] Error 1


Help! I am confused because it looks identical to the declaration on the previous line except it uses IO not the option_table...




> On 26 Apr 2021, at 07:36, Zoltan Somogyi <zoltan.somogyi at runbox.com> wrote:
> 
> 
> 
> On Mon, 26 Apr 2021 07:16:52 +0100, "Sean Charles (emacstheviking)" <objitsu at gmail.com> wrote:
>> Is it a —wise— idea to consider using globals on the IO State?
> 
> We initially thought so, and wrote the compiler that way.
> 
> We later realized that beyond a certain complexity, it was simply
> less error-prone to pass the globals explicitly to every part of the code
> that needed it, even though it required writing more code.
> The compiler now consistently passes the globals *separately*
> from the I/O state, except maybe in the very initial startup code.
> (I don't know for sure, I haven't looked at that code in a long time.)
> 
> The problem with consistently storing the globals in the I/O state
> is debugging. When you are looking at a call that updates the
> I/O state, you cannot be certain whether that call also updated
> the globals, unless you inspect both the callee *and its entire
> call tree*. In a small program, that is not too much of a burden;
> in a large program, it is. Getting such things wrong can cause bugs
> that are annoyingly hard to track down. Writing explicit code
> to pass the globals is a tiny bit of extra work in the usual case,
> but can save a lot unpleasant debugging.
> 
> So the answer to your question is: if you are sure that your program
> will always remain small, then yes; otherwise, no.
> 
> Zoltan.
> 

-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.mercurylang.org/archives/users/attachments/20210426/9a7141d4/attachment-0001.html>


More information about the users mailing list