[m-users.] Field access functions usage

Mark Brown mark at mercurylang.org
Fri Aug 16 08:06:49 AEST 2019


Hi Dirk,

On Fri, Aug 16, 2019 at 7:17 AM Dirk Ziegemeyer <dirk at ziegemeyer.de> wrote:
>
> Hi,
>
> I’d like to use a field access function as a higher order term. As explained in reference manual section 3.4.1, I declare the function explicitly. This seems to affect the „normal“ field access syntax which does not compile any more.
>
> Example:
>
> :- type foo
>     --->    foo(
>                 field_1 :: int,
>                 field_2 :: string
>             ).
>
>
> :- func field_1(foo) = int.
>
>
> main(!IO) :-
>     Foo = init_foo,
>     _X = field_1(Foo),
>     _Y = list.map(field_1, [Foo]).
>
>
> :- func init_foo = foo.
>
> init_foo = X :-
>     X^field_1 = 5,
>     X^field_2 = "bar".
>
>
> Compiler error:
> field_access_test.m:039: In clause for `init_foo = out':
> field_access_test.m:039:   in argument 1 of call to function
> field_access_test.m:039:   `field_access_test.field_1'/1:
> field_access_test.m:039:   mode error: variable `X' has instantiatedness
> field_access_test.m:039:   `unique(foo(free, unique("bar")))',
> field_access_test.m:039:   expected instantiatedness was `ground’.
>
> As soon as I add the declaration of the compiler-generated function field_1/1, init_foo/0 does not compile any more. What is wrong in my code?

Without the declaration the goal X^field_1 = 5 is just a unification,
for which the compiler can generate whatever mode it needs. You use
the field_1/1 function in two different modes, so the compiler
generates different code in each case. If you wanted the above code to
work, you could add mode declarations for the field access function to
match the ways you use it. However, that would defeat your intent to
use field_1 as a higher order term.

Perhaps you can write the body of init_foo as

    Field1 = 5,
    Field2 = "bar",
    X = foo(Field1, Field2)

so as to avoid needing the unconventional function mode? Note that
that will also result in much more obvious error messages in the case
where you add a field to foo but forget to update init_foo.

Mark


More information about the users mailing list