[m-dev.] op/3 syntax and semantics

Peter Schachte schachte at csse.unimelb.edu.au
Mon Feb 20 16:56:53 AEDT 2006


On Wed, Feb 01, 2006 at 04:35:40PM -0500, doug.auclair at logicaltypes.com wrote:
> 
> Fergus asked for a semantic and syntactic definition of the op/3
> declaration.  Since it is implemented the same way in Mercury as it is
> in Prolog (except the extent of the effect: in Mercury I've limitted
> its extent to the module in which it is declared.

This seems too restrictive to me.  I've never found an operator useful
enough to bother to define it if I just want it in one module.
However, I've defined many operators to be used in clients of a module
I've developed.

Limiting an operator to the module that defines it means that every
client of a module that defines an operator for an exported predicate,
function, or constructor will have to include an op declaration in
addition to importing the module (or else not use the operator).  This
seems stylistically wrong:  to use the features of a module, I
shouldn't have to do anything but import it.

> Prolog's op/3 has
> universal extent (I consider this to be a misfeature, but this cannot
> be helped: the Prolog module system was an afterthought, added long
> after op/3, so there is a corpus of Prolog code that depend on this
> misfeature.  Ugh!)).

Prolog definitely got it wrong.  A big problem in Prolog is that, eg,
if module b defines operator o and some other module m says:

	:- use_module(a).
	:- use_module(b).
	:- use_module(c).

then operator o is visible in c when loaded by m, but not when
separately compiling c.  Worse yet, if the user reloads m, then o is
visible when loading a.  If a or c uses o as an ordinary symbol, this
may cause syntax errors in a or c when compiling m that do not occur
when compiling them separately.  This has caused me trouble more than
once.  But what Prolog does get right is that the rest of module m can
use operator o.  This can't cause problems because m depends on b.

The correct thing for Mercury, I believe, is for operators defined in
the interface section to be usable in terms appearing later in that
file, as well as terms appearing after an import of that module in
other files.  Basically, the operator defintion of a symbol should be
visible everywhere its predicate, function, or constructor definition
is.  Eg, if the interface section of module m contains

	:- op(700, xfx, !=).
	:- pred T:in != T:in is semidet.

	X != Y :- \+ X = Y.

then any file that contains

	:- import_module m.

should be able to use operator != anywhere after the import_module
declaration.  I would expect this could be implemented by including
the op declaration in the interface file for m.

I believe what you're proposing is the right thing to do for operators
declared in the *implementation* section, though.

-- 
Peter Schachte              Re graphics: A picture is worth 10K words -- but
schachte at cs.mu.OZ.AU        only those to describe the picture. Hardly any
www.cs.mu.oz.au/~schachte/  sets of 10K words can be adequately described with
Phone: +61 3 8344 1338      pictures. 
--------------------------------------------------------------------------
mercury-developers mailing list
Post messages to:       mercury-developers at cs.mu.oz.au
Administrative Queries: owner-mercury-developers at cs.mu.oz.au
Subscriptions:          mercury-developers-request at cs.mu.oz.au
--------------------------------------------------------------------------



More information about the developers mailing list