[m-rev.] diff: Add 99 bottles of beer sample

Paul Bone paul at bone.id.au
Fri Nov 20 17:58:52 AEDT 2015


On Fri, Nov 20, 2015 at 05:48:36PM +1100, Julien Fischer wrote:
> 
> Hi Paul,
> 
> On Fri, 20 Nov 2015, Paul Bone wrote:
> 
> >Add 99 bottles of beer sample
> >
> >samples/beer.m
> >   Add this sample.
> >
> >   I found the original version of this sample on 99-bottles-of-beer.net.
> >   I've updated it, _tried_ to post a comment to 99-bottles-of-beer.net,
> >   added it to rosetta code and thought, being a small example, that it
> >   should also belong here.
> 
> Oooh, can I play this game too?  If your aim is to provide a more
> idiomatic version, I'd suggest:
> 
> - not using explicit recursion where the standard library already
>   provides a procedure (int.fold_down) that does the same thing.
> - use if-then-else rather that (C->T;E)
> - there's lots of string appending using ++ going on in your version, I'd
>   call append_list instead.
> 
> I've attached an alternative  version.

Feel free to update it.

> % vim: ts=4 et ft=mercury
> 
> :- module beer2.
> :- interface.
> 
> :- import_module io.
> 
> :- pred main(io::di, io::uo) is det.
> 
> :- implementation.
> 
> :- import_module int.
> :- import_module list.
> :- import_module string.
> 
> main(!IO) :- int.fold_down(beer, 0, 99, !IO).

Yeah, I should have used fold_down

> :- pred beer(int::in, io::di, io::uo) is det.
> 
> beer(N, !IO) :-
>     ( if N = 0 then
>         io.print_line("Go to the store and buy some more!", !IO)
>     else
>         bottles(N, " on the wall,\n", !IO),
>         bottles(N, ".\nTake one down, pass it around,\n", !IO),

It's easier to follow if you start a new source code line, probably with a
new call to write_string, for the new-line in the song.

>         bottles(N - 1, " on the wall.\n\n", !IO)
>     ).
> 
> :- pred bottles(int::in, string::in, io::di, io::uo) is det.
> 
> bottles(N, T, !IO) :-
>     ( if N = 0 then
>         io.format("No more bottles of beer%s", [s(T)], !IO)
>     else if N = 1 then
>         io.format("1 bottle of beer%s", [s(T)], !IO)
>     else
>         io.format("%d bottles of beer%s", [i(N), s(T)], !IO)
>     ).

Why pass the IO state through everything?  I try to avoid this where
conveinent.  I think append_list would have been better, it avoids the
repeated string appends and keeps the code declrative.  Maybe Mercury should
optimise that as a special case rather than relying on programmers to
understand the costs of ++.


-- 
Paul Bone



More information about the reviews mailing list