[m-dev.] Adding Loops to Mercury

Matt Giuca matt.giuca at gmail.com
Sat Jan 4 23:48:33 AEDT 2014


Thanks for deeply considering my suggestion, Paul.

There is another reason I'd like to add in to the discussion, I apologise
> if someone has said this already.  We have many predicates such as foldl,
> foldl2, foldl3 etc in the list module of the standard library. We also have
> map_corresponding and numerous other predicates, each predicate has a
> number of different modes.  It can be painful when you need to use a
> predicate that fits one of these patterns in some ways, but doesn't fit the
> number of accumulators, number of output or input lists (map_corresponding)
> etc.  This is particularly bad when the ADT is abstract (like maps, but
> unlike list) where you cannot write such a predicate without modifying the
> standard library.
>

Yep, this is what Peter Schachte was getting at, I think.

I think that the solution should be something smiliar to Matt's proposal
> (below) that can also work on integers.  Peter Schachte's paper may also be
> useful but I've not read it, John's reference to Visual Prolog might also
> be
> useful.  Additionally, one case where I've seen this done before was SISAL,
> a pure single assignment language that used loops that looked similar to
> imperative loops http://en.wikipedia.org/wiki/SISAL.  Ultimately SISAL was
> not adopted by the programming community because Fortran programmers found
> it difficult to adjust to declrative programming.  More about SISAL:
> http://www2.cmp.uea.ac.uk/~jrwg/Sisal/00.Contents.html  Matt: is there
> something like this in Mars that we should also read?
>

Mars loops are just simple while loops with the same semantics as Python.
Nothing really special. (It isn't really relevant to Mercury because Mars
local variables are re-assignable; in this sense Mars semantics are much
closer to a conventional imperative language.)


>
> On Fri, Jan 03, 2014 at 11:14:29AM +1100, Matt Giuca wrote:
> > I would propose a for loop syntax for Mercury which can be used something
> > like this:
> >
> > :- pred print_key_values(assoc_list(string, string)::in, io::di, io::uo)
> is
> > det.
> > print_key_values(List, !IO) :-
> >     for X-Y in List [!IO] (
> >         io.write_string(X, !IO),
> >         io.write_string(" = ", !IO),
> >         io.write_string(Y, !IO),
> >         io.nl(!IO)
> >     ).
> >
> > The features of this syntax are:
> >
> >    1. Clearly shows that X-Y is the elements of List, and that List is
> the
> >    list being iterated over.
> >    2. Only need to specify the accumulators once (!IO), instead of
> >    specifying them both in the predicate head and as separate arguments.
> >    3. Works naturally with the !S state variable notation, not requiring
> >    the user to break the illusion of S being a single variable and
> specify !.S
> >    and !:S.
> >    4. Does not allow the "invention" of new accumulator names; instead,
> you
> >    are merely specifying existing variables from the outer scope
> (typically
> >    state variables) that may be updated in the body of the loop.
> >    5. Does not require the user to have to decide whether to use foldl,
> >    foldl2, foldl3, etc. It works for any number of accumulator variables.
> >    6. It keeps the idea that the user must explicitly specify which
> >    variables can be updated by the loop body. You can't just go updating
> any
> >    state variable in the outer scope, for example.
> >
>
> This seems good to me, I would like to extend it though so that:
>
>     7.  It can handle any number of input lists.  (like map_corresponding).
>     8.  It can handle things other than lists (I have some ideas about how
> to
>         do this that I can describe later).
>     9.  It can handle multiple outputs (not just accumoators) like list.map
>         does.
>     10. Guards can be added to support filtering.
>

I would support all of these, as long as they can be added cleanly to the
syntax (i.e., all of these features are optional and I don't need to
provide, for example, a "returning" clause when I'm not using it for a map).

SISAL was a pure language that had structures like this that were used for
>  looping and such more often than recursion.  This and your own work show
> that the imperative/declarative dichotomy really is a false one (yes, I
> deliberately paraphrased one of your titles).
>

Thanks :)

Also, because you, and I'm sure others, would have found such a feature
> useful in Mercury means that it is valuable.  If there are good ideas whose
> effort to implement and maintain are worthwhile then there's no reason we
> should reject them.
>

Julian's previous post suggests that something very similar to my
suggestion was attempted thirteen years ago, and was abandoned largely for
implementation reasons. If such a feature *is* going to add significant
implementation overhead, then that is a reason to think twice about it. Not
to say it should be abandoned again, but that the payoff has to be worth
the effort. As I'm not a Mercury developer, I can't speak to the difficulty
of implementing it, so I'll leave it to better minds to discuss.

Matt
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.mercurylang.org/archives/developers/attachments/20140104/0994860b/attachment.html>


More information about the developers mailing list