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

Sean Charles (emacstheviking) objitsu at gmail.com
Sat Nov 20 21:24:09 AEDT 2021


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.

I have another language instruction called typemap:

	(#f:typemap {
		“variables” {…}
		“types” {…}
	})

which allows both inline code and external files to be loaded prior to composition of the final code and each typemap defines the final output type of a variable in the final code. Given that I (‘I’, not the compiler yet) know the list is empty or even for the “variables” or “types” value, I then do:

    else if Lslot = "variables" then
        parse_variables(
            list.chunk(RHS,2),   % RHS is the content between {…}
            !Map,
            !Errors)

As I know the list is either empty or even, I know that the chunked list is always going to be -pairs- of snode entries

    [ snode, snode ]

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. Trying

	list.foldl(
		(pred([K,V]::in, … )  is det :-
			list.det_index0(KV, 0, K),
			list.det_index0(KV, 1, V),
			handler( K, V, ...
		),
	),
	list.chunk(RHS,2), … )

just moves the same problem, that the unification of the [K,V] term can fail and so I am back to square one. The current handler looks like this:

:- pred parse_variables(list(lsnode)::in, tm_index::in, tm_index::out,
    lserror::in, lserror::out) is det.

parse_variables([], !_Map, !_Errors).

parse_variables([ KV | RHS ], !Map, !Errors) :-
    % I then use det_index0 to split KV into K and V
    % but would like to declare the predicate as
    % parse_variables( [ [K,V] |

So I guess the question is, should I use pair() right back at the start of the process or how would I inform the compiler in its language that I absolutely know and can guarantee that the received parameter is a list of size 2, always, for ever. Except when it’s empty. If I use pair() it affects other code that performs string conversions.

Just looking for guidance, insights, educating etc.

Thanks, I hope that makes sense.
What a terrible email.
Sorry.
Sean.




-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.mercurylang.org/archives/users/attachments/20211120/8065efc4/attachment.html>


More information about the users mailing list