[mercury-users] Problem with mmake

Richard A. O'Keefe ok at atlas.otago.ac.nz
Fri Jun 8 10:27:47 AEST 2001

Concerning the way environment variables have metastasised in Mercury,
Fergus Henderson <fjh at cs.mu.OZ.AU> wrote:
	I'm afraid I remain unenlightened.
Sigh.  It seems that everyone is out of step except Mercury.

	I don't see how changing N environment variables into N
	configuration file commands would reduce complexity.  I also
	remain unconvinced that it would increase convenience.

How can anyone argue with the brute fact that it *IS* much more convenient
to create and run Haskell programs using GHC than to create or run Mercury
programs?  I don't recall when I've _ever_ had so much trouble with the
compilation interface for some programmung language on UNIX.

The core of the problem is that environment variables are promiscuous.
If you set MERCURY_OPTIONS, then _every_ Mercury program you run will be
affected, presumably including the Mercury compiler itself.  For things
like $USER, $TERM, $HOME, $SHELL, $TERM, locale, timezone, and so on,
things can reasonably be taken as constant for this-user-at-this-terminal-
this-session, environment variables make sense.  For things like "what
directories should be searched for libraries", environment variables do
NOT make sense, and LD_LIBRARY_PATH has abundantly proved this in practice.
Fortunately, ld(1) has an option "-R" (some UNIX systems) or "-rpath" (some
other UNIX systems) to enable that information to be bound with the program,
as it should be.  Basically, good design has it that

 - stuff which is the same for almost every program can go in
   environment variables
 - stuff which depends on the program but is the same for almost every
   execution of that program is bound into the executable or can go in
   runtime configuration files (.mailrc, .indent.pro, and so on)
 - stuff which depends on the program but is only used as compile time:
 - stuff which is likely to be different for different executions can go in
   command line options and arguments.

The complexity I am alluding to is not the complexity of *setting up*
a configuration, but the complexity of *selecting* a configuration.

	At the implementation level I think it might well *increase*
	complexity.  Environment variables are very easy to access from
	shell scripts.  Any other mechanism is likely to be more complex.
I am writing as a Mercury *user*.  My concern is not with the difficulty
of implementing Mercury, but the difficulty of *using* it.  Having written
a configuration file parser (you could write sh, csh, Prolog, or even Lisp
configuration files that it could read, with a little care), I am totally
unimpressed by the argument that this might be complex; it wasn't.

More generally, all you need is something like
    mmconfig {program} {key}
and then a shell script (in any shell dialect) can do
    FOO_OPTION=`mmconfig $thisprog whatsit`
using the syntax appropriate to the shell.

	(Hmm... I guess we could use configuration files in shell syntax,
	and parse them using the shell's source command (`.' in Bourne shell).
	That would be simple enough.  But I'm still not convinced that doing
	this would be worth the hassle that such a change would entail.)
What hassle?  More to the point, *whose* hassle?

	> The mechanism is already groaning in every joint with some variables
	> having more-or-less simple values and other variables having structured
	> values (complete with rather pointless, given the context, double dashes).
	For the Mercury runtime system we use the getopt_long() routine
	to parse the runtime options.

Once again, *whose* hassle?

	It seemed pointless to invent a new options syntax and to write
	a parser for it, just because we were passing options via an
	environment variable rather than on the command line.
But that is an argument for using the UNIX standard "getsubopt()" syntax!
(Free versions of getsubopt() are available, including one from me.)
In fact, in terms of "whose hassle", it would be noticeably easier for the
Mercury implementors to use getsubopt() than getopt_long() there.

	> It is the simplest thing that can possibly work.
	> Amongst other things, if I want to flip from one configuration to
	> another, there is *ONE* thing to change; there is no possibility
	> of an "incomplete edit" leaving me part way between two configurations.
	OK, that is one thing that would be more convenient with the approach
	that you suggest.
Right, and it is the major thing, because if you have a collection of
Mercury programs, they will want different configurations and you want
to give each program its correct configuration as easily as possibhle.

	But the drawback of your approach is that changing a single configuration
	parameter while leaving the others unchanged is more difficult.
	And that is in my experience a significantly more common operation.
All I can say as a Mercury user, not implementor, is that it isn't mine.

Apparently if I want GC to work, I am going to have to switch LD_LIBRARY_PATH
every time I switch grade.

I have already pointed out that switching a single parameter need not be
hard.  Is there room for a compromise?

(1) Let there be configuration files.
(2) Let mld/mmake be able to bind a particular program to either a particular
    configuration file or the contents of a particular configuration file at
    build time.
Then people can deploy and use their Mercury programs without any environment
variable setting whatsoever, and what could be less complex or more
convenient than that?
(3) Let the programs still check whether the environment variables are
    defined, and if they are, heed them.
Then people who want to frob one parameter the same way for a dozen
programs can do so the same way they do now.

	> I am really confused that anyone would find this a difficult concept to
	> grasp.  The more knobs there are, and the more places they are, the harder
	> it is to get them right.
	But we're not talking about reducing the number of nobs,
	or even about reducing the number of places where they are,
	just about moving them!
We _are_ talking about the number of places they are.  Instead of being in
.cshrc or .login or .profile or this shell script or that shell script or
typed in by hand or in the sh command line, I was proposing that they would
all be set in a single configuration file (one per program).

And we are most definitely talking about the reducing the number of knobs
*that have to be set by Mercury users*.

	> A quick check turned up fourteen MERCURY_ environment variables:
	> Netscape gets by with one.
	I don't think counting the number of environment variables
	is always the best way to measure complexity.

It is when you're talking about the complexity of setting up the right
configuration of environment variables!

	Netscape probably has more than fourteen different configuration files,
	each of which contain many different configuration settings.

It has more configuration _settings_ that one, but as far as I can tell by
poking around in ~/.netscape they are in one _file_.

	I don't think that changing environment variables into configuration
	commands will by itself reduce complexity, unless you choose to
	measure complexity simply be the number of environment variables.
I am measuring complexity by the number of inconsistent states I can get
into and by the number of things I as a Mercury user have to worry about.

	But the Mercury runtime system's use of MERCURY_OPTIONS isn't an example of
	the "one variable *points to* a complete configuration" approach.
	Rather, it is a "one variable *contains* a complete configuration" approach.
I have no problem with that.  Put _everything_ in there, and make it possible
to bind that into a program when it is built, and I'll be happy.

	This is actually a quite significant difference, because this approach
	makes it much easier to selectively override individual seetings.

	Another approach which is about half way between what you are proposing
	and what we use with MERCURY_OPTIONS would be to have a single environment
	variable which contains that contained a *list* of configuration files.

That's very close to one of the alternatives I suggested.

FJH doesn't understand why I see the present interface as difficult.
I don't understand why it would be *common* to frob a single parameter.
This probably means I don't know how to use the Mercury tools anywhere
near as effectively as he does.  Perhaps an example of why this is
a *commonly* useful thing to do would clarify matters.

	It *is* possible to override a single configuration setting selectively
	using MERCURY_OPTIONS, as explained above.
This was not obvious from reading the documentation.  If it is a common
thing to do, perhaps it should be spelled out in the User's Guide with
an example.

	> The claim that pointing-to-configuration-files would mean that there would
	> be "no easy way to selectively override a single configuration setting" is,
	> as I explained in a previous message, simply false.  That's what a "source"
	> mechanism is for.
	That doesn't work, as I explained, because you don't know the name of
	the previous configuration file to source:
So tell us, and then that problem disappears, no?

	> You are assuming that it is common to twiddle one configuration parameter
	> *in a way you'll never want again*.
	No, just in a way that preserves the rest of the current environmen's
	configuration parameter settings, whatever that environment is.
	> In the unlikely event that this *shold* be common practice in the Mercury
	> world, I have now spent the last 20 minutes writing and testing a UNIX
	> utility
	>     setvar variable value command...
	> that creates a temporary file, copies $CONFIG (if that exists) or
	> ~/.config (if that exists) to it, adds
	> 	export variable; variable="value"
	> _with_ appropriate backslashes in "value", runs command, and then deletes
	> the temporary file.  It took just 70 SLOC.  I don't call that hard.
	Now *you're* kidding *me*, right? ;-)
No.  There is something I have _never_ wanted to do, but you say it is
_common_.  Wearing an implementor's hat, I proved that it is easy for me
as an implementor to provide a utility that lets you do what you want.

Note the difference between
    set oldx="$MERCURY_x"
    setenv MERCURY_x "new x value"
    myprog <in >out
    setenv MERCURY_x "$oldx" 

which is how you temporarily change one environment variable in the C
shell, and

    setvar MERCURY_x "new x value" myprog <in >out

which is how you'd do it using configuration files and my 70-SLOC C utility.
I don't call setvar hard to use, and I don't call a 70-SLOC C program hard
to write (once, as an implementor, and provide with Mercury).

Admittedly, if you use sh, the choice is between

    MERCURY_x="new x value" myprog <in >out


    setvar MERCURY_x "new x value" myprog <in >out

but the sh syntax doesn't work in csh.
mercury-users mailing list
post:  mercury-users at cs.mu.oz.au
administrative address: owner-mercury-users at cs.mu.oz.au
unsubscribe: Address: mercury-users-request at cs.mu.oz.au Message: unsubscribe
subscribe:   Address: mercury-users-request at cs.mu.oz.au Message: subscribe

More information about the users mailing list