[m-dev.] Adding Loops to Mercury
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
> 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)
> > 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
> > 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,
> > are merely specifying existing variables from the outer scope
> > 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
> > 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
> do this that I can describe later).
> 9. It can handle multiple outputs (not just accumoators) like list.map
> 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).
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.
-------------- next part --------------
An HTML attachment was scrubbed...
More information about the developers