[m-dev.] Re: Visual vs total arity clash example [fwd]

Peter Schachte schachte at cs.mu.OZ.AU
Fri Jan 28 16:48:41 AEDT 2000


On Thu, Jan 27, 2000 at 08:52:12AM -0800, Ralph Becket wrote:

> Can someone remind me again why EDCGs are not just a simple
> source transformation and hence why there should be any problem
> with integrating EDCG code with plain code?  I really don't
> have a problem (in fact I think it's a Good Thing) that the
> hidden arguments be expanded in the order in which they are
> declared.

Yes, I was wrong about that one.  The order doesn't matter, as long as
a predicate p with hidden arguments a and b can all q with hidden
arguments b and a.  My implementation made this easier by sorting the
globals, but it's not necessary.

> > :- htype(list_acc, list(char)).
> > :- hmode(list_acc, changed(in, out)).
> > 
> > :- pred app(list(char)) +hidden(changed(list_acc)).
> > :- mode app(in) is det.
> > 
> > app([]).
> > app([C | Cs]) -->>
> >         app(Cs),
> >         $=list_acc = [C | $list_acc].
> 
> I hope this is just a demonstration and not a suggested coding
> style :)  Here EDCGs have made things worse rather than better.

Most EDCG predicates won't be so simple, so the benefit will be
clearer.  But I think your reaction is largely due to your mental
model.  From your comments, I infer that your mental model is that
this definition is just syntactic sugar, and not so sweet at that, for
the usual definition of append/3.  To understand it, you think about
the extra pair of arguments threading through the clause.  Put another
way, you might envision a clause as a bunch of black boxes each with a
number of sockets.  Variables in clauses stand for wires running among
the sockets of the various boxes.  I believe you're thinking of EDCGs
as just letting you avoid running some of those wires.

I suggest a different model.  Instead, think of $list_acc as a
location outside the clause which holds some value, in this case a
list.  A clause is no longer just a collection of boxes wired
together, it's a sequence of boxes, each specifying a step in a
procedure.  Some of these steps may work by replacing the contents of
$list_acc with a new value.

Ok, you're thinking I've just described FORTRAN or something equally
horrible.  Not so.  The main problems with procedural programming like
this are that data structures intended as inputs may be modified
without your knowing it, and since side effects can't be predicted,
compilers can't optimize code very well.  With EDCGs, you only need
look at the predicate declaration to know what a predicate call might
change.  And since the compiler has this information as well, it's
free to optimize.

So for predicates where the collection of wired-up boxes works ok,
stick with that.  When the wiring gets too complicated to understand
easily, and thinking of the predicate as a sequence of operations
possibly changing the data stored in some locations, switch to EDCGs.

I think with this model, the above code is a lot easier to understand
than if you try to think of how it will be expanded.  Think of it as
this:  in order to put [C|Cs] on the front of $list_acc, we first put
Cs on the front, and then put C on the front of that.  But note that
this predicate should really have been called prepend/1, or maybe
accumulate_front/1.

In fact, a more useful predicate than this might be:

	:- pred append(list(T)) +hidden(changed(list_acc(T))).
	:- mode(in) is det.

	append(L) -->> append($list_acc, L, $=list_acc).

> {REQUEST: can we change `changed' to `changes'?  It's a
> declaration, not a statement.)

Good point.  How about `uses' `changes' and `produces'?  Or even `in'
`out' and `inout'?

> > > ...Yes, this can all be explained,
> > > and it's not terribly difficult, but I see no reasons for users to
> > > have to understand these complications.  More importantly, by
> > > explaining them, you lock yourself into one implementation strategy
> > > when there may be better approaches.
> 
> I so disagree with this!  All we're doing is providing a means of
> omitting (multiple) state threads when including them would only 
> obfuscate the code.  I feel very strongly that we should keep this
> simple and understandable

That's exactly what I'm trying to do by providing a simpler mental
model.

> if you change the order of
> hidden arguments between one release of the compiler and the next,
> then all sorts of libraries will have to be recompiled in order to
> guarantee that arguments are passed in the right order.

I was thinking of more radical changes, such as not passing "hidden
arguments" as arguments at all, but passing them in memory.  This
would often save a *lot* of argument shuffling.  As soon as you
document how something like this is implemented, you make it very
difficult to change the implementation later.

-- 
Peter Schachte                     I disapprove of what you say, but I will
mailto:schachte at cs.mu.OZ.AU        defend to the death your right to say it.
http://www.cs.mu.oz.au/~schachte/      -- Voltaire 
PGP: finger schachte at 128.250.37.3  
--------------------------------------------------------------------------
mercury-developers mailing list
Post messages to:       mercury-developers at cs.mu.oz.au
Administrative Queries: owner-mercury-developers at cs.mu.oz.au
Subscriptions:          mercury-developers-request at cs.mu.oz.au
--------------------------------------------------------------------------



More information about the developers mailing list