[mercury-users] Mercury programmer required ;-)

Fergus Henderson fjh at cs.mu.OZ.AU
Thu Sep 24 19:50:19 AEST 1998


On 24-Sep-1998, Warwick HARVEY <warwick at cs.mu.OZ.AU> wrote:
> Tyson writes:
> > The people who have the "99 bottles of beer on the wall" program
> > in many different languages have asked for a version of the
> > famous Rot-13 algorithm in Mercury.
> 
> Hmmm, does it have to be clean?  And in true Mercury style?  Or anything
> like that?
> 
> Given that it's for all the world to see, I'd hate to have a poor example of
> Mercury programming get posted.  So in the spirit of mercury-devel, I'm
> posting my program here and requesting that somebody review it.  :-)

> 	% rot13a/2
> 	% A table to map the alphabetic characters to their rot13 equivalents
> 	% (fails if the input is not alphabetic).
> :- pred rot13a(char, char).
> :- mode rot13a(in, out) is semidet.
> 
> rot13a('a', 'n').
...
> rot13a('Z', 'M').

This is good; I had a look at the rot13 programs in C, Ada, and ML,
and none of them would have handled character sets such as EBCDIC correctly.

I was also glad to see that your program reported input errors
(and the Mercury runtime will report output errors, so they're covered too).
Few of the programs in other languages seemed to handle errors properly;
often they were just silently ignored.

I had only one substantive criticism of your program:
the error message in case of an input error really ought
to go to stderr rather than stdout.

However, the big table approach is a bit verbose and arguably a bit
low-level.  The following version is less efficient, but a bit more
concise and high-level.

	% The length of `alphabet' should be a multiple of `cycle'.
	alphabet = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ".
	cycle = 26.

	rot_n(N, Char) = RotChar :-
		char__to_string(Char, CharString),
		(if string__sub_string_search(alphabet, CharString, Index) then
			NewIndex = (Index + N) mod cycle +
					cycle * (Index // cycle),
			string__index_det(alphabet, NewIndex, RotChar)
		else
			RotChar = Char
		).

	rot13(Char) = rot_n(13, Char).

There's also a couple of style questions such as whether to include
type declarations and whether to use `read'/`print' or `io__read_char'
and `io__write_string'.  I notice that for some other languages
there are a couple of different versions of rot13 on the web page;
perhaps it would be good to have two Mercury versions, one taking
all the concise choices (`read'/`print', no unnecessary type decls,
and the shorter algorithm) and the other taking the verbose ones
(`io__read_char'/`io__write_string', explicit type decls everywhere,
and the more efficient table lookup algorithm).

-- 
Fergus Henderson <fjh at cs.mu.oz.au>  |  "I have always known that the pursuit
WWW: <http://www.cs.mu.oz.au/~fjh>  |  of excellence is a lethal habit"
PGP: finger fjh at 128.250.37.3        |     -- the last words of T. S. Garp.



More information about the users mailing list