[m-users.] use of list.chunk and head clause determinism

Zoltan Somogyi zoltan.somogyi at runbox.com
Sat Nov 20 21:41:30 AEDT 2021


2021-11-20 21:24 GMT+11:00 "Sean Charles (emacstheviking)" <objitsu at gmail.com>:
> This is the fifth and final attempt at posing this question so I apologise in advance for its potential display of rambling incoherence, because the more I thought about it the more confused I became having spent some considerable life hours coaxing the compiler with my horrid source code.
> 
> I have a type called snode and one of its constructors is map(). A map is guaranteed to have either no elements or an even number of elements as they are intended to be key-value pairs during final code rendering phase.
> 
> At the point of finishing parsing I currently have this code:
> 
>                         (if even(length(Terms)) then
>                             Res = term(map(Pos, Terms))
> 			:
> 
> On the highlighted line, I started thinking should I use the library pair() to make processing of them in some way ‘easier’ further along the processing pipeline ? At the time, I decided that it would not really help but, having spent some time on this now, I seek advice as I am going around in thought-spirals that end in a walk in the woods.

A list of pairs sounds like *exactly* what you want in this case. This is a data structure
so useful that it has an entire module in the Mercury library: assoc_list.m.

Using a list with the odd elements being keys and the even elements being values
is doing things the hard way, not just because you have to put in code to handle
the cases you know (or at least believe) to be impossible, such as odd-length lists,
because also it is far too easy to make mistakes that the compiler can't catch for you
(which it *could* and *would* catch with the assoc_list representation). It is also more
future proof, in that it would allow a future change to make the type of the values
be different from the type of the keys.

In general, with very few exceptions, I have found it a good idea to express any
structural invariants that apply to a data structure in the type of that data structure
whenever possible.

> but I have failed to find a way to indicate via use of mode+inst instructions to the compiler that the list I expect to be given to the called predicate is guaranteed to be a list of two things, hence my earlier comment about wondering if the use of pair.pair() now may be a good idea BUT that feels like doing something earlier on just because I now can’t figure out how to tell the compiler, if it is possible at all, is some kind of giving up instead of this being another great Mercury learning opportunity.
> 
> I’ve tried using list.foldl on the chunked list and then calling the predicate with two distinct values:
> 
> 	list.foldl(
> 		(pred(KV::in, … ) is det :- 
> 			list.det_index0(KV, 0, K),
> 			list.det_index0(KV, 1, V),
> 			handler( K, V, ...
> 		),
> 	),
> 	list.chunk(RHS,2), … )
>
> but that screams ugly and smells like a bucket of two day old fish soup.

There is a standard set of fold predicates on assoc_lists
in the standard library that don't scream or smell ...

I hope that helps.

Zoltan.


More information about the users mailing list