[mercury-users] field updates

Ralph Becket rbeck at microsoft.com
Tue Oct 24 19:41:09 AEDT 2000

>From david wallin on 23/10/2000 20:48:11
> Thanks everyone,
> I was obviously still in Java-land because I tried
> Structure ^ fieldname := NewValue

Yes, in an imperative language this would change the value pointed
to by Structure; since destructive update is not referentially
transparent (modulo blah blah rhubarb), in a declarative language
like Mercury this has to return a new object identical to that
bound to Structure except for the value of fieldname.

> However, I managed to get stuck again. I have defined a type with a 
> field of type array, something like:
> :- type game_state ---> game_state(
> 				bank    :: int,
> 				players :: array(player_state),
> 				rounds  :: int
> 			).
> :- pred player_bet_on_number(int, int, game_state, game_state).
> :- mode player_bet_on_number(in, in, in, out) is det.
> player_bet_on_number(Player, Number, GameI, GameO) :-
> 	GameI ^ players = P,
> 	array__size(P) = Size,
> 	(
> 	  Size > Player ->
> 	  array__lookup(P, Player, PlayerState),
> 	  PlayerState2 = PlayerState ^ number := Number,
> 	  array__set(P, Player, PlayerState2, P2),
> 	  GameO = GameI ^ players := P2
> 	;
> 	  GameI = GameO
> 	).
> This is what the compiler has to say about this :
> game.m:112: In clause for `player_bet_on_number(in, in, in, out)':
> game.m:112:   in argument 1 of call to predicate `array:set/4':
> game.m:112:   mode error: variable `P' has instantiatedness `ground',
> game.m:112:   expected instantiatedness was `(array:uniq_array)'.
> I guess I could switch from array__set/4 to array__slow_set/4 and the 
> problems would go away, right ?
> But is there another (better) way to do this ? (I fear this means 
> delving into modes and instantiations, though)

'Fraid so - you've been bitten by the mode problem.  If you want
efficiently updatable arrays - i.e. a la C, Java etc. - they have
to be unique in Mercury.  This means that at any point in your
program there can only ever be one live reference to a particular
mutable array.  This raises problems when you want to nest one
unique object inside another, as your game_state type tries to.
In theory, there's nothing wrong with this; however, the current
mode analysis in the compiler isn't quite up to the job.

There are a number of ways around the problem, including
1. pass around the array separately and not as part of another
2. use, say, a bt_array rather than an array (not as efficient,
but mode-hassle-free);
3. use the C interface to do some grungy hacking to get around
the current mode analysis.

array__slow_set/4 is probably the wrong thing to do since it
copies the entire array.

I'm not sure how close we are to getting nested unique objects,
maybe one of the developers could comment.


Ralph Becket      |      MSR Cambridge      |      rbeck at microsoft.com 

mercury-users mailing list
post:  mercury-users at cs.mu.oz.au
administrative address: owner-mercury-users at cs.mu.oz.au
unsubscribe: Address: mercury-users-request at cs.mu.oz.au Message: unsubscribe
subscribe:   Address: mercury-users-request at cs.mu.oz.au Message: subscribe

More information about the users mailing list