[m-users.] Creating an interface module

Volker Wysk post at volker-wysk.de
Fri Jul 14 21:52:37 AEST 2023


Am Freitag, dem 14.07.2023 um 19:09 +1000 schrieb Zoltan Somogyi:
> On 2023-07-14 10:02 +02:00 CEST, "Volker Wysk" <post at volker-wysk.de> wrote:
> > I can think of a solution that looks easy to implement.
> 
> Everything is simple and easy when you don't have to do it.
> Obligatory example: Dilbert's boss.

My thought was, that you just have to add the list of reexported modules to
the list of the modules being imported by the first one.

> 
> > In a module there
> > could be some statement ":- import_as_well(...)", which tells the compiler
> > to import some other modules as well, when the module with the statement is 
> > being imported.
> 
> This means that the set of modules your code says to import (e.g. module A and B)
> is not the set of modules you *will* import (which will be A, B, C, D, E and F if B contains
> an import_as_well for C, C contains one for D etc). This can reduce compiler performance
> more than people may expect, and it will definitely add extra complication to the
> build system. It also means that the set of modules that a module imports
> can now include itself, if module X imports Y, and Y contains an import_as_well for X.
> What is the semantics of *that*?

Importing oneself should be a no-op.

> All of this is begging the questions: what problem does reexport solve, and is it the
> best solution of that problem? I have never seen a thorough attempt at answering
> those questions. Most answers amount to "this is the approach I am used to, and I don't
> want to learn another". The one use case people always bring up is that it allows
> several modules in a library to be presented to users as a single unified entity.

Yes, that's my use case here.

> However, I don't see how reexport makes an useful difference in that case.
> Without reexport, users of the library have access to
> 
> library.module1.pred1
> library.module1.pred2
> library.module2.pred1
> 
> and so on. With reexport, they have access to
> 
> library.module1_pred1
> library.module1_pred2
> library.module2_pred1
> 
> and so on. Without reexport, the module structure within the library
> is visible. With reexport, it is technically not visible, but the renaming
> required to prevent name clashes *makes* it visible anyway, at least
> in some cases. For example, the Mercury compiler has a gazillion
> functions named "init": map.init, set.init and so on, and the same is true
> for predicates named insert, remove, map, foldl, foldr etc. If the module
> structure is exposed, the module qualifiers on calls can be optional
> if the right choice is dictated by the types of the arguments. With
> the reexport with renaming approach, the module qualifiers must
> become part of the name, and are no longer optional. This means that
> *even in a language that supports reexport*, there is a good argument
> for not using it.

That's right, such renaming would make nonsense out of it. 

But Haskell does't do any such renaming. The reexported identifiers are
named like if they originated from the reexporting module. When there are
name clashes, the identifier must be qualified. A module can also be
imported as "qualified", meaning that its identifies must always be
qualified. You can even rename some identifiers when you import them.

You may say that I think like "this is the approach I am used to, and I
don't want to learn another". But I asked for the best practice. I want to
know how to do it the Mercury way.

Now it looks like there's any more to know.

> Peter said that Mercury's module system is pretty basic. That is a statement
> of fact, but it is not a value judgement. Among the languages I know about,
> the most powerful module system belongs to the ML family of languages.
> Everyone acknowledges that it allows people to do things with modules
> that other languages can't support. However, to a first approximation,
> no newer langage has copied its approach to module system design.
> I am pretty sure that this means that language designers don't consider
> the extra power to be worth the extra cost. Your post considers cost
> in the form of implementation effort (in a somewhat cavalier fashion),
> but does not consider cost in the form of extra conceptual complexity
> for users of the language, which can be even more significant,
> and which (unlike implementation effort) has to be paid over and over,
> whenever a new person learns the language.

I believe you're right. My idea wasn't very well-considered...


Cheers,
Volker
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 833 bytes
Desc: This is a digitally signed message part
URL: <http://lists.mercurylang.org/archives/users/attachments/20230714/a7946194/attachment-0001.sig>


More information about the users mailing list