[m-dev.] Is this a bug?
Jonathan Morgan
jonmmorgan at gmail.com
Mon Jun 18 14:57:30 AEST 2007
On 6/18/07, Peter Schachte <schachte at csse.unimelb.edu.au> wrote:
> Ralph Becket wrote:
> > Ralph Becket, Monday, 18 June 2007:
> >> I'm trying to use field update syntax to update a map of maps, but it
> >> isn't working:
> >>
> >> ::: map_map_update_test.m :::
> >>
> >> :- module map_map_update_test.
> >> :- interface.
> >> :- import_module io.
> >>
> >> :- pred main(io::di, io::uo) is det.
> >>
> >> :- implementation.
> >> :- import_module map.
> >>
> >> main(!IO) :-
> >> A0 = map.init,
> >> A = A0 ^ elem(42) ^ elem(99) := 123,
> >> io.write_int(A ^ det_elem(42) ^ det_elem(99), !IO),
> >> io.nl(!IO).
> >>
> >> ::: end of map_map_update_test.m :::
> >
> > Ah, I've understood the problem:
> >
> > A = A0 ^ elem(42) ^ elem(99) := 123
> >
> > expands according to the following rule in the reference manual
> >
> > transform(Term ^ Field(Arg1, ...) := FieldValue) =
> > 'Field :='(Arg1, ..., Term, FieldValue)).
> >
> > transform(Term0 ^ Field(Arg1, ...) ^ Rest := FieldValue) = Term :-
> > OldFieldValue = Field(Arg1, ..., Term0),
> > NewFieldValue = transform(OldFieldValue ^ Rest := FieldValue),
> > Term = 'Field :='(Arg1, ..., Term0, NewFieldValue).
> >
> > The OldFieldValue uses the `elem' field access function which is
> > semidet.
> >
> > This is somewhat counterintuitive.
>
> Yes, and a bit annoying to work around. Just switching to det_elem() won't
> help. (BTW: why is the semidet version the default (the one with the
> convenient name)? Didn't we decide a while back that semidet functions were a
> bad idea?)
>
> The only solution I can think of would be to use a variation on maps that have
> a default value that is returned when looking up an unmapped key. Elem() would
> be det for that type, so you could use it for the outer map, with default value
> map.init.
If I write something like the following:
Map = default_map.init(map.init),
_ = Map ^ elem(42).
and the default value is used, then does Map now have an element 42,
set to map.init? In either case, I think that the result is a little
strange. Also, are you expecting the default to be a value, or a
function taking the value of the element we wish to have a default
value for? The second method is more general, but is also a little
more complicated to use.
All these problems (and more, because of its imperative nature and
lack of a type system) occur with Python's default_map, such that it
is generally advised that users be extremely careful when using it.
On the Mercury side, there is no danger of accidentally adding
additional values to a map when looking up a value, but there is the
potential problem of creating redundant data structures and using more
memory. In many ways I think that a getter with default values is
more transparent, though not necessarily as nice. How this integrates
with returning the map altered I'm not really sure.
Jon
--------------------------------------------------------------------------
mercury-developers mailing list
Post messages to: mercury-developers at csse.unimelb.edu.au
Administrative Queries: owner-mercury-developers at csse.unimelb.edu.au
Subscriptions: mercury-developers-request at csse.unimelb.edu.au
--------------------------------------------------------------------------
More information about the developers
mailing list