[m-users.] Reasoning behind a compile failure on list destructuring

Dirk Ziegemeyer dirk at ziegemeyer.de
Sat May 22 00:10:11 AEST 2021


Hi Sean,

I’m not completely sure if I understand the intention behind your code. Assuming you want to pass a list of options together with their values to a predicate you have several possibilities:

If there are always six options, you can define a record:

:- type env_variables
    --->    env_variables(
                felt_inst   :: string,
                felt_pager  :: string,
                felt_editor :: string,
                felt_repl   :: string,
                felt_lex    :: string,
                felt_ast    :: string
            ).


Alternatively, you could use a key-value collection type like a map:

:- type env_variables == map(env_variable_name, string).

:- type env_variable_name
    --->    felt_inst
    ;       felt_pager
    ;       felt_editor
    ;       felt_repl
    ;       felt_lex
    ;       felt_ast.


Dirk.


> Am 21.05.2021 um 15:23 schrieb Sean Charles (emacstheviking) <objitsu at gmail.com>:
> 
> I wanted a list of environment variables in one hit so I wrote a predicate to do it…I initially a lambda in list.map but IO was complaining etc and so I wrote my version:
> 
> get_env_str(Vars, Out, !IO) :-
>     get_env_str_list_(Vars, [], Out, !IO).
>     % Aux.
> :- pred get_env_str_list_(
>     list(string)::in, list(string)::in, list(string)::out,
>     io::di, io::uo) is det.
>     % done, reverse.
> get_env_str_list_([], Acc, Out, !_IO) :-
>     Out = list.reverse(Acc).
>     % find, prepend.
> get_env_str_list_([V|Vs], Acc, Out, !IO) :-
>     get_env_str(V, "", Val, !IO),
>     get_env_str_list_(Vs, [Val|Acc], Out, !IO).
> 
> Then I called it like this:
> 
>     utils.get_env_str([
>         "FELT_INST", "FELT_PAGER", "FELT_EDITOR",
>         "FELT_REPL", "FELT_LEX", "FELT_AST"],
>         [Inst, Pager, Editor, Repl, Lex, Ast],
>         !IO),
> 
> And got this:
> 
> repl.m:248: In `run_info'(di, uo):
> repl.m:248:   error: determinism declaration not satisfied.
> repl.m:248:   Declared `det', inferred `semidet'.
> repl.m:253:   In argument 2 of call to predicate `utils.get_env_str'/4:
> repl.m:253:   in argument 2 of functor `[|]/2':
> repl.m:253:   in argument 2 of functor `[|]/2':
> repl.m:253:   in argument 2 of functor `[|]/2':
> repl.m:253:   in argument 2 of functor `[|]/2':
> repl.m:253:   in argument 2 of functor `[|]/2':
> repl.m:253:   unification with `V_60' can fail.
> repl.m:253:   In argument 2 of call to predicate `utils.get_env_str'/4:
> repl.m:253:   in argument 2 of functor `[|]/2':
> repl.m:253:   in argument 2 of functor `[|]/2':
> repl.m:253:   in argument 2 of functor `[|]/2':
> repl.m:253:   in argument 2 of functor `[|]/2':
> ... error log truncated, see `repl.err' for the complete log.
> ** Error making `Mercury/cs/repl.c’.
> 
> It took me a while to figure it out, but I reasoned that despite the fact I know I passed in six variable names, the compiler could not know how many values might well be in the returned list, despite me knowing that the internal implementation would always return the same number of strings, even a blank one. That then made sense of the error message, my final code then is:
> 
>     utils.get_env_str([
>         "FELT_INST", "FELT_PAGER", "FELT_EDITOR",
>         "FELT_REPL", "FELT_LEX", "FELT_AST"],
>         Vars, !IO),
>     ( Vars = [Inst, Pager, Editor, Repl, Lex, Ast]
>     -> do stuff
>     ; apologise to user
>     ).
> Is that the correct reasoning behind the error? I hope so becaise I can’t really think of any other cause!
> 
> Thank you,
> Sean.
> 
> _______________________________________________
> users mailing list
> users at lists.mercurylang.org
> https://lists.mercurylang.org/listinfo/users



More information about the users mailing list