Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

"C++ Modules Might Be Dead-on-Arrival"

156 views
Skip to first unread message

Lynn McGuire

unread,
Jan 29, 2019, 1:32:14 PM1/29/19
to
"C++ Modules Might Be Dead-on-Arrival"
https://vector-of-bool.github.io/2019/01/27/modules-doa.html

Cool, the author compared C++ to Fortran !

Lynn

Alf P. Steinbach

unread,
Jan 29, 2019, 7:01:52 PM1/29/19
to
Not in a way that said something good about C++ modules. :(

Thanks for sharing this article.


Cheers!,

- Alf


Jorgen Grahn

unread,
Jan 30, 2019, 9:03:28 AM1/30/19
to
On Tue, 2019-01-29, Lynn McGuire wrote:
> "C++ Modules Might Be Dead-on-Arrival"
> https://vector-of-bool.github.io/2019/01/27/modules-doa.html

Summary: he doesn't think modules work well with build tools,
prevent parallelized builds, and thus makes building slower.

I have no opinion on this, but I won't change my build tools
to use a single new C++ feature.

/Jorgen

--
// Jorgen Grahn <grahn@ Oo o. . .
\X/ snipabacken.se> O o .

Juha Nieminen

unread,
Jan 30, 2019, 9:19:58 AM1/30/19
to
Jorgen Grahn <grahn...@snipabacken.se> wrote:
> On Tue, 2019-01-29, Lynn McGuire wrote:
>> "C++ Modules Might Be Dead-on-Arrival"
>> https://vector-of-bool.github.io/2019/01/27/modules-doa.html
>
> Summary: he doesn't think modules work well with build tools,
> prevent parallelized builds, and thus makes building slower.

Also: The standardization committee is deliberately ignoring the
problem, even after numerous attempts to raise awareness.

That being said, who knows if it will actually be a problem.

--- news://freenews.netfront.net/ - complaints: ne...@netfront.net ---

Richard

unread,
Jan 30, 2019, 11:57:24 AM1/30/19
to
[Please do not mail me a copy of your followup]

Jorgen Grahn <grahn...@snipabacken.se> spake the secret code
<slrnq53bl4.4...@frailea.sa.invalid> thusly:

>On Tue, 2019-01-29, Lynn McGuire wrote:
>> "C++ Modules Might Be Dead-on-Arrival"
>> https://vector-of-bool.github.io/2019/01/27/modules-doa.html
>
>Summary: he doesn't think modules work well with build tools,
>prevent parallelized builds, and thus makes building slower.

I only skimmed the article; it seemed to me that his examples revolved
around circular dependencies between user-defined modules. Did I miss
something?
--
"The Direct3D Graphics Pipeline" free book <http://tinyurl.com/d3d-pipeline>
The Terminals Wiki <http://terminals-wiki.org>
The Computer Graphics Museum <http://computergraphicsmuseum.org>
Legalize Adulthood! (my blog) <http://legalizeadulthood.wordpress.com>

Ben Bacarisse

unread,
Jan 30, 2019, 12:19:05 PM1/30/19
to
legaliz...@mail.xmission.com (Richard) writes:

> [Please do not mail me a copy of your followup]
>
> Jorgen Grahn <grahn...@snipabacken.se> spake the secret code
> <slrnq53bl4.4...@frailea.sa.invalid> thusly:
>
>>On Tue, 2019-01-29, Lynn McGuire wrote:
>>> "C++ Modules Might Be Dead-on-Arrival"
>>> https://vector-of-bool.github.io/2019/01/27/modules-doa.html
>>
>>Summary: he doesn't think modules work well with build tools,
>>prevent parallelized builds, and thus makes building slower.
>
> I only skimmed the article; it seemed to me that his examples revolved
> around circular dependencies between user-defined modules. Did I miss
> something?

I think you did. His point seems to be that if source A.cpp uses module
B.cpp, module B.cc must be compiled /before/ A.cpp so that the compiler
will have the binary exports file that the compile of B.cpp requires.
With the traditional "a 'module' is a .cpp file and a .h file" approach
there is no enforced sequencing -- A.cpp and B.cpp can be compiled in
parallel.

[Note: this is simply from reading the cited post -- I know next to
nothing about the module proposal.]

--
Ben.

Manfred

unread,
Jan 30, 2019, 12:40:30 PM1/30/19
to
On 1/30/2019 6:18 PM, Ben Bacarisse wrote:
> legaliz...@mail.xmission.com (Richard) writes:
>
>> [Please do not mail me a copy of your followup]
>>
>> Jorgen Grahn <grahn...@snipabacken.se> spake the secret code
>> <slrnq53bl4.4...@frailea.sa.invalid> thusly:
>>
>>> On Tue, 2019-01-29, Lynn McGuire wrote:
>>>> "C++ Modules Might Be Dead-on-Arrival"
>>>> https://vector-of-bool.github.io/2019/01/27/modules-doa.html
>>>
>>> Summary: he doesn't think modules work well with build tools,
>>> prevent parallelized builds, and thus makes building slower.
>>
>> I only skimmed the article; it seemed to me that his examples revolved
>> around circular dependencies between user-defined modules. Did I miss
>> something?
>
> I think you did. His point seems to be that if source A.cpp uses module
> B.cpp, module B.cc must be compiled /before/ A.cpp so that the compiler
> will have the binary exports file that the compile of B.cpp requires.
> With the traditional "a 'module' is a .cpp file and a .h file" approach
> there is no enforced sequencing -- A.cpp and B.cpp can be compiled in
> parallel.

And circular dependencies are a consequential problem of this scheme,
although not mentioned explicitly in the post. His focus is more on
chained dependencies and how the purpose of modules is defeated:
compilation speed, complex management of build settings and so on.

>
> [Note: this is simply from reading the cited post -- I know next to
> nothing about the module proposal.]
>

The way he puts it, it seems that he has some point, although I am not
familiar with the module proposal either.

With respect to current #includes, I guess there could be some room for
improvement especially for template libraries: #including boost is
costly in terms of compilation time.
But I am somewhat doubtful on how a suitable module interface unit could
be extracted from such a library, and how this could affect
instantiation and optimization of template code.
I am not holding my breath for it.

Bart

unread,
Jan 30, 2019, 12:46:08 PM1/30/19
to
On 30/01/2019 17:18, Ben Bacarisse wrote:
> legaliz...@mail.xmission.com (Richard) writes:
>
>> [Please do not mail me a copy of your followup]
>>
>> Jorgen Grahn <grahn...@snipabacken.se> spake the secret code
>> <slrnq53bl4.4...@frailea.sa.invalid> thusly:
>>
>>> On Tue, 2019-01-29, Lynn McGuire wrote:
>>>> "C++ Modules Might Be Dead-on-Arrival"
>>>> https://vector-of-bool.github.io/2019/01/27/modules-doa.html
>>>
>>> Summary: he doesn't think modules work well with build tools,
>>> prevent parallelized builds, and thus makes building slower.
>>
>> I only skimmed the article; it seemed to me that his examples revolved
>> around circular dependencies between user-defined modules. Did I miss
>> something?
>
> I think you did. His point seems to be that if source A.cpp uses module
> B.cpp, module B.cc must be compiled /before/ A.cpp so that the compiler
> will have the binary exports file that the compile of B.cpp requires.
> With the traditional "a 'module' is a .cpp file and a .h file" approach
> there is no enforced sequencing -- A.cpp and B.cpp can be compiled in
> parallel.

That wouldn't be problem, unless a project only consists of two massive
modules A and B so they could only be compiled in series.

You compile B, and then presumably whatever file is exported can be
reused by a number of modules not just A. The problem of parallel
compiling can be mitigated.

However, circular dependencies CAN be a problem if A.cpp imports B.cpp,
and B.cpp imports A.cpp, neither of which is yet compiled, or the
compiled version has become out of date.

(I've solved the problem in a simpler language, although it's not
entirely satisfactory. And makes parallel code impractical when building
a single executable. Not a problem for me, as projects are small enough
that it doesn't matter.)

Compiling using C-style headers is simpler, and allows parallelism (even
if the same modules need to be repeatedly processed). But at a cost of
not having a module system, and having to construct the headers - what
are effectively the export files of the proposed scheme (I don't know
how it works either) - by hand.

Melzzzzz

unread,
Jan 30, 2019, 2:39:55 PM1/30/19
to
On 2019-01-30, Jorgen Grahn <grahn...@snipabacken.se> wrote:
> On Tue, 2019-01-29, Lynn McGuire wrote:
>> "C++ Modules Might Be Dead-on-Arrival"
>> https://vector-of-bool.github.io/2019/01/27/modules-doa.html
>
> Summary: he doesn't think modules work well with build tools,
> prevent parallelized builds, and thus makes building slower.
>
> I have no opinion on this, but I won't change my build tools
> to use a single new C++ feature.

Build tools have to change for sure. Also having modules unecessites
having .h files.
>
> /Jorgen
>


--
press any key to continue or any other to quit...

Melzzzzz

unread,
Jan 30, 2019, 2:43:24 PM1/30/19
to
I don't know details about module proposal but
void f() { g(); }
void g(){}

should compile and link then.

Lynn McGuire

unread,
Jan 30, 2019, 3:09:57 PM1/30/19
to
Yup. I have yet to use Fortran modules but they do look verbose.

Lynn


Bart

unread,
Jan 30, 2019, 3:11:06 PM1/30/19
to
That's a different problem, which is out-of-order declarations. C
doesn't like those (don't know about C++). Although it doesn't stop C
compilers from accepting code like this (albeit with warnings):

void f(){g("two"); g(&f);}
void g(float x){};

The problem I mean is illustrated here, with a fantasy version of C that
has modules:

==================
A.c:
==================
import B

typedef float Ta; # Ta, Ka, Fa exported
enum {Ka = 711};

static void Ma(void) {
Fb(Kb+4);
}

void Fa(Tb x) {
}


==================
B.c:
==================
import A

typedef int Tb; # Tb, Kb, Fb exported
enum {Kb = 289};

static void Mb(void) {
Fa(Ka+4);
}

void Fb(Ta x) {
}

To compile A requires knowing Tb, Kb and Fb; to compile B requires
knowing about Ta, Ka, and Fa.

If the idea is that compiling B.c automatically generates some file (eg.
B.h or B.hpp), that is the one that 'import A' will use, then that can't
happen because compiling B will first require A.h or A.hpp.

This is the problem. (Or A imports B which imports C that imports A.)

David Brown

unread,
Jan 30, 2019, 3:58:55 PM1/30/19
to
On 30/01/2019 20:39, Melzzzzz wrote:
> On 2019-01-30, Jorgen Grahn <grahn...@snipabacken.se> wrote:
>> On Tue, 2019-01-29, Lynn McGuire wrote:
>>> "C++ Modules Might Be Dead-on-Arrival"
>>> https://vector-of-bool.github.io/2019/01/27/modules-doa.html
>>
>> Summary: he doesn't think modules work well with build tools,
>> prevent parallelized builds, and thus makes building slower.
>>
>> I have no opinion on this, but I won't change my build tools
>> to use a single new C++ feature.
>
> Build tools have to change for sure. Also having modules unecessites
> having .h files.

I can't see why common build tools like "make" would have any problems here.

Sure, you might not be able to compile everything in parallel - but
"make" (or ninja, or whatever) will handle it fine. If you have enough
modules for the build speed and parallel compilation to matter, there
will be plenty of opportunity for parallelising.


David Brown

unread,
Jan 30, 2019, 4:01:05 PM1/30/19
to
It is almost always possible to break your circular dependencies by
using a third module that contains the parts needed by both A and B. If
C++ modules can be made in a way that allows circular dependencies,
great. If not, it's certainly not the end of the module idea.

Scott Lurndal

unread,
Jan 30, 2019, 4:33:40 PM1/30/19
to
Back in the late 70's/early 80's, the Burroughs MCP/IX operating system
had reached a point where it needed to be re-written (being fifteen
years old at that point, and hardware had gotten much more capable in
the intervening years). The MCP at that point was written in
assembler language, some of it over fifteen years old; to write a new,
modern operating system capable of managing the greatly expanded hardware
resources (amount of memory, new MMU, number of processors, I/O controllers, devices)
in assembler would require a great deal of labor, be prone to error and
difficult to maintain.

So, a new language was proposed by the Languages department to use for the
Operating system. This language, based very roughly on Modula, supported
independently compiled modules using a centralized interface definition (called
a MID - Module Interface Definition). Sort of a master include file, if you
will. The MID needed to be compiled _before_ any module that used it; much
like the proposed C++ Modules capability. The new language was called
SPRITE and the new operating system (MCP/VS2.0) was written -mostly- in that
language (with portions of the prior MCP living on as assembler files linked
in with the SPRITE ICMs (Independently Compiled Modules).

In practice, while the concept worked, the MID quickly became a bottleneck
for the developers - every interface change between modules (and early in
the development process, this occured very frequently) needed a MID change.

Now, source code control systems at the time were uncommmon (SCCS became
available for Unix systems about then, RCS came a bit later on BSD systems);
the developers used a Master + patch approach; However, most changes required
patching the MID as well which required careful coordination when the patches
were "checked in" (eventually consolidated into the single master file for
each module) because at the time (the end of the punched card era), each source
code line required a unique sequence number (typically in columns 72-80, but
dependent upon the language); making sure the patches being merged didn't
overlap was a time-consuming process (later, partially automated as part of
the resequencer that needed to be run periodically to expand the gaps between
sequence numbers for future changes).

That experience soured me somewhat on the idea of the type of interface
definition proposed by the C++ Modules proposal.

As one who routinely builds a 1.5+ million line C++ application (most of that
in header files), I don't see compile time as a problem (full builds take
a few minutes, typical incremental builds during development take a few seconds);
nor do I believe that preventing ODR violations is valuable enough to
justify adding Modules TS or P0947R0(Atom) to C++.

YMMV.


http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2018/p0986r0.html

Melzzzzz

unread,
Jan 30, 2019, 5:18:19 PM1/30/19
to
On 2019-01-30, Bart <b...@freeuk.com> wrote:
> On 30/01/2019 19:43, Melzzzzz wrote:
>> On 2019-01-30, Bart <b...@freeuk.com> wrote:
>
>>> However, circular dependencies CAN be a problem if A.cpp imports B.cpp,
>>> and B.cpp imports A.cpp, neither of which is yet compiled, or the
>>> compiled version has become out of date.
>>
>> I don't know details about module proposal but
>> void f() { g(); }
>> void g(){}
>>
>> should compile and link then.
>
> That's a different problem, which is out-of-order declarations. C
> doesn't like those (don't know about C++). Although it doesn't stop C
> compilers from accepting code like this (albeit with warnings):
>
> void f(){g("two"); g(&f);}
> void g(float x){};

No. You don't have type check. I meant no need for prototypes.

>
> The problem I mean is illustrated here, with a fantasy version of C that
> has modules:
This problem is solved in other languages. You either parse all library
files as single file, or ....

Melzzzzz

unread,
Jan 30, 2019, 5:19:48 PM1/30/19
to
No problems with make. Compilers must accomodate.

David Brown

unread,
Jan 30, 2019, 6:05:07 PM1/30/19
to
Ah, when you said "Build tools have to change for sure", I thought you
meant tools like "make". Obviously compilers have to change to support
the new feature!


Bart

unread,
Jan 30, 2019, 6:37:53 PM1/30/19
to
On 30/01/2019 22:18, Melzzzzz wrote:
> On 2019-01-30, Bart <b...@freeuk.com> wrote:
>> On 30/01/2019 19:43, Melzzzzz wrote:
>>> On 2019-01-30, Bart <b...@freeuk.com> wrote:
>>
>>>> However, circular dependencies CAN be a problem if A.cpp imports B.cpp,
>>>> and B.cpp imports A.cpp, neither of which is yet compiled, or the
>>>> compiled version has become out of date.
>>>
>>> I don't know details about module proposal but
>>> void f() { g(); }
>>> void g(){}
>>>
>>> should compile and link then.
>>
>> That's a different problem, which is out-of-order declarations. C
>> doesn't like those (don't know about C++). Although it doesn't stop C
>> compilers from accepting code like this (albeit with warnings):
>>
>> void f(){g("two"); g(&f);}
>> void g(float x){};
>
> No. You don't have type check. I meant no need for prototypes.

Which you get with out of order declarations. I solved this long ago in
my own languages, and wouldn't be able to do without the feature now.

However, while it was easy to solve within one module (it just needs an
extra pass compared with C or C++), dealing with mutually imported
modules is another matter.

>>
>> The problem I mean is illustrated here, with a fantasy version of C that
>> has modules:
> This problem is solved in other languages. You either parse all library
> files as single file, or ....

My approach [in my language] works when all source files comprising the
program unit (single executable or library file) are compiled at the
same time, sharing a global symbol table (the output is the executable).

Parsing is performed across all modules before proceeding to the next
stage, which is resolving names. And that process can now cross between
modules because everything is in memory.

(For external libraries it still relies on manually created files of
declarations, necessary anyway as most will be in a different language.)

There are still a number of problems, one of which is this: with a
purely hierarchical import structure, it is easy to construct a
load-order for the modules. That means that when modules contain
initialisation routines, all those can automatically be called in the
right order.

But with circular imports, that load-order is not determinable. If A
imports B, and B imports A, whose initialisation routine do you call
first? Each may require the other to have been set up already. You have
to sort it out manually.

--
bart

Paavo Helde

unread,
Jan 31, 2019, 1:14:41 AM1/31/19
to
On 31.01.2019 1:37, Bart wrote:
> On 30/01/2019 22:18, Melzzzzz wrote:
>> On 2019-01-30, Bart <b...@freeuk.com> wrote:
>>> On 30/01/2019 19:43, Melzzzzz wrote:
>>>> On 2019-01-30, Bart <b...@freeuk.com> wrote:
>>>
>>>>> However, circular dependencies CAN be a problem if A.cpp imports
>>>>> B.cpp,
>>>>> and B.cpp imports A.cpp, neither of which is yet compiled, or the
>>>>> compiled version has become out of date.
>>>>
>>>> I don't know details about module proposal but
>>>> void f() { g(); }
>>>> void g(){}
>>>>
>>>> should compile and link then.
>>>
>>> That's a different problem, which is out-of-order declarations. C
>>> doesn't like those (don't know about C++). Although it doesn't stop C
>>> compilers from accepting code like this (albeit with warnings):
>>>
>>> void f(){g("two"); g(&f);}
>>> void g(float x){};
>>
>> No. You don't have type check. I meant no need for prototypes.
>
> Which you get with out of order declarations. I solved this long ago in
> my own languages, and wouldn't be able to do without the feature now.
>
> However, while it was easy to solve within one module (it just needs an
> extra pass compared with C or C++)

C++ is perfectly capable of doing the needed extra pass by itself, it
just needs a little syntax sugar:

struct mynamespace {

static void f(double x) { g(x-1); }

static void g(float x) { if (x>0) { f(x); }}

};

int main() {
mynamespace::f(100);
}




David Brown

unread,
Jan 31, 2019, 2:23:33 AM1/31/19
to
On 31/01/2019 00:37, Bart wrote:
> On 30/01/2019 22:18, Melzzzzz wrote:
>> On 2019-01-30, Bart <b...@freeuk.com> wrote:
>>> On 30/01/2019 19:43, Melzzzzz wrote:
>>>> On 2019-01-30, Bart <b...@freeuk.com> wrote:
>>>
>>>>> However, circular dependencies CAN be a problem if A.cpp imports
>>>>> B.cpp,
>>>>> and B.cpp imports A.cpp, neither of which is yet compiled, or the
>>>>> compiled version has become out of date.
>>>>
>>>> I don't know details about module proposal but
>>>> void f() { g(); }
>>>> void g(){}
>>>>
>>>> should compile and link then.
>>>
>>> That's a different problem, which is out-of-order declarations. C
>>> doesn't like those (don't know about C++). Although it doesn't stop C
>>> compilers from accepting code like this (albeit with warnings):
>>>
>>>      void f(){g("two"); g(&f);}
>>>      void g(float x){};
>>
>> No. You don't have type check. I meant no need for prototypes.
>
> Which you get with out of order declarations. I solved this long ago in
> my own languages, and wouldn't be able to do without the feature now.
>

C, C++ and many other languages support declarations (or "prototypes",
or "forward declarations" - the terminology varies by language) before
definitions. That solves any circular dependency issues within a module
quite happily. Co-recursive functions are a rarity in code.

Some people like to organise their files "backwards" - they like to
define a function first, then further down in the file they define the
functions that it calls. That is fine, but will mean you need more
separate prototype declarations in C. For people who like that code
arrangement, C's methods are a little inconvenient. (As Paavo points
out, C++ no longer needs that if you feel it is an issue.)


> However, while it was easy to solve within one module (it just needs an
> extra pass compared with C or C++), dealing with mutually imported
> modules is another matter.
>

Ordering is not a problem in the slightest for modules. Mutually
dependent imports (circular imports) are an issue, but these can almost
always be avoided in your code structuring.

James Kuyper

unread,
Jan 31, 2019, 6:47:41 AM1/31/19
to
On 1/31/19 02:23, David Brown wrote:
...
> C, C++ and many other languages support declarations (or "prototypes",
> or "forward declarations" - the terminology varies by language) before
> definitions.

While the terminology does vary by language, neither C nor C++ use the
term "prototype" to make such a distinction. Do you know of some other
language where it is used for that purpose? In C and C++, a prototype
can occur in either a forward declaration or in the declaration that
appears at the start of a function definition. In C, a forward
declaration need not be a prototype, and the same is true of the
declaration which appears a the start of a function definition. "forward
declaration" and "defining declaration" is a distinction that's
completely independent of the distinction between "prototyped
declaration" and "non-prototyped declaration" (with the latter appearing
only in C).

Bart

unread,
Jan 31, 2019, 7:06:28 AM1/31/19
to
On 31/01/2019 07:23, David Brown wrote:
> On 31/01/2019 00:37, Bart wrote:

>> Which you get with out of order declarations. I solved this long ago
>> in my own languages, and wouldn't be able to do without the feature now.
>>
>
> C, C++ and many other languages support declarations (or "prototypes",
> or "forward declarations" - the terminology varies by language) before
> definitions.  That solves any circular dependency issues within a module
> quite happily.

That doesn't solve it at all. Actually it is /part/ of the problem we're
trying to solve! And sometimes you can't neatly get around it:

enum {a,b,c=y,d};
enum {w=b,x,t,z};

You can't reorder these. And you can't split them up if a,b,c,d and
w,x,y,z belong together, and you still want to rely on auto-increment.
But it's easy to see that a,b,c,d should be 0,1,3,4 and w,x,y,z is
1,2,3,4 (see sig).

Any 'solutions' will spoil the code.

> Co-recursive functions are a rarity in code.

Co-recursion has some technical meaning which I'm not sure is the one
that is relevant here. If you mean that A() calls B() which calls A(),
then I write such code all the time.

>
> Some people like to organise their files "backwards" - they like to
> define a function first, then further down in the file they define the
> functions that it calls.  That is fine, but will mean you need more
> separate prototype declarations in C.  For people who like that code
> arrangement, C's methods are a little inconvenient.  (As Paavo points
> out, C++ no longer needs that if you feel it is an issue.)

With an extra construct? Having this natively possible anywhere in a
language, without having to worry about such things at all, is more
desirable:

E readexpr(void) { ... return readterm();}
E readterm(void) { ... return readexpr();}


> Mutually
> dependent imports (circular imports) are an issue, but these can almost
> always be avoided in your code structuring.

I've had experience of this and often found it difficult to impossible.
99% of functions would fit into the hierarchy, but there were always odd
ones that didn't.

Trying to extract things out usually turned into a can of worms, and you
ended up with obviously contrived code, ruining the tidy structure of
your project.

(My solutions tended to use ad hoc manual declarations, circumventing
the module system, but the compiler could not check that my manual
declaration matched the actual definition of a function.)

Again, this itself turns into the problem that needs to be fixed. You
should be able to just write things in the most natural manner. If it
makes sense to the person reading or writing the code, it should make
sense to a compiler.

--
bart

enum (a=0,b,c=y,d) # usually 1-based
enum (w=b,x,y,z)

println a,b,c,d, w,x,y,z


Output:

0 1 3 4 1 2 3 4

This however doesn't work:

enum (a=b, b=a)

Öö Tiib

unread,
Jan 31, 2019, 9:42:42 AM1/31/19
to
The "prototypes" are typically denoting alternative to "classes"
in OOP languages with dynamic types. There instead of inheritance
we just extend objects directly and instead of instantiations
of classes we just clone prototype objects. That has not much
to do with C or C++, closest such language is JavaScript.

David Brown

unread,
Jan 31, 2019, 10:38:30 AM1/31/19
to
Fair enough - that is a lot more precise than I was (and, I think more
precise than necessary). I referred to "prototypes" merely because some
people like to give a function prototype as a forward declaration, and
then omit the function parameters (if any) later in the definition.

David Brown

unread,
Jan 31, 2019, 10:51:09 AM1/31/19
to
On 31/01/2019 13:06, Bart wrote:
> On 31/01/2019 07:23, David Brown wrote:
>> On 31/01/2019 00:37, Bart wrote:
>
>>> Which you get with out of order declarations. I solved this long ago
>>> in my own languages, and wouldn't be able to do without the feature now.
>>>
>>
>> C, C++ and many other languages support declarations (or "prototypes",
>> or "forward declarations" - the terminology varies by language) before
>> definitions.  That solves any circular dependency issues within a
>> module quite happily.
>
> That doesn't solve it at all. Actually it is /part/ of the problem we're
> trying to solve! And sometimes you can't neatly get around it:
>
>   enum {a,b,c=y,d};
>   enum {w=b,x,t,z};

It solves it for functions and types. It has never occurred to me that
anyone would have need of re-ordering enums like that. I think it could
be hard to get any solution here that does not involve multiple rounds
or general equation solving, which is hardly appropriate for a language
like C or C++. (You can do it in metafont or metapost, but those are
very different kinds of language.)

>
> You can't reorder these. And you can't split them up if a,b,c,d and
> w,x,y,z belong together, and you still want to rely on auto-increment.
> But it's easy to see that a,b,c,d should be 0,1,3,4 and w,x,y,z is
> 1,2,3,4 (see sig).
>
> Any 'solutions' will spoil the code.
>
>> Co-recursive functions are a rarity in code.
>
> Co-recursion has some technical meaning which I'm not sure is the one
> that is relevant here. If you mean that A() calls B() which calls A(),
> then I write such code all the time.

Mutual recursion is the term I wanted. There can be cases where this is
useful, in handling recursive data structures, but I think if you are
writing it a lot you have questionable coding structures. (Not
necessarily wrong, merely questionable.) However, the point is that is
only with such mutual recursion that you need to have forward
declarations for your functions - and it is not a hardship to use this
on occasion. It would be annoying to have to use forward declarations
for a large proportion of functions, but not for just a few.

>
>>
>> Some people like to organise their files "backwards" - they like to
>> define a function first, then further down in the file they define the
>> functions that it calls.  That is fine, but will mean you need more
>> separate prototype declarations in C.  For people who like that code
>> arrangement, C's methods are a little inconvenient.  (As Paavo points
>> out, C++ no longer needs that if you feel it is an issue.)
>
> With an extra construct? Having this natively possible anywhere in a
> language, without having to worry about such things at all, is more
> desirable:
>
>  E readexpr(void) { ... return readterm();}
>  E readterm(void) { ... return readexpr();}
>

I quite agree that it would be convenient to be able to do this without
forward declarations, and I can well understand allowing it in a new
language. I just don't think it is a big issue - like many people, I
have programmed in C (and other languages that need forward
declarations) for many years without feeling this to be a concern.

>
>> Mutually dependent imports (circular imports) are an issue, but these
>> can almost always be avoided in your code structuring.
>
> I've had experience of this and often found it difficult to impossible.

Maybe you have a fundamentally different way of organising code than I
do. (I know we have quite different types of code). It simply doesn't
occur in my coding - either embedded C, C++ and assembly programming, or
PC programming in Python, Pascal, etc.

james...@alumni.caltech.edu

unread,
Jan 31, 2019, 11:02:27 AM1/31/19
to
Could you demonstrate the technique you're talking about? I suspect that you've not describing it correctly. If function parameters are present in a forward declaration of a function, but omitted from the corresponding function definition, then:

1. In C++ you've defined an overload of the function with a different signature from the one used in the forward declaration - calling the function with arguments that match the forward declaration would result in a search (which would presumably fail) for a different overload.

2. In C, you've defined a function that's incompatible with the forward declaration. That's a constraint violation if they have the same scope (6.7p3), and the behavior is undefined (6.2.7p2), regardless of scope.

Bart

unread,
Jan 31, 2019, 3:42:39 PM1/31/19
to
On 31/01/2019 15:50, David Brown wrote:
> On 31/01/2019 13:06, Bart wrote:

>> Co-recursion has some technical meaning which I'm not sure is the one
>> that is relevant here. If you mean that A() calls B() which calls A(),
>> then I write such code all the time.
>
> Mutual recursion is the term I wanted. There can be cases where this is
> useful, in handling recursive data structures, but I think if you are
> writing it a lot you have questionable coding structures.

No it's not questionable. Most of the big programs I've written have
involved recursive data. (CAD systems, windows-based GUIs, compilers and
interpreters. Even file systems are recursive.) Obviously yours don't.

(Not
> necessarily wrong, merely questionable.) However, the point is that is
> only with such mutual recursion that you need to have forward
> declarations for your functions - and it is not a hardship to use this
> on occasion. It would be annoying to have to use forward declarations
> for a large proportion of functions, but not for just a few.

I had to do that for years. I can tell you that things are much sweeter
if you don't have to bother. (It's quite a problem too if you have one
language which or may not need forward declarations that has to be
expressed in one which has its own rules for them.)

> I quite agree that it would be convenient to be able to do this without
> forward declarations, and I can well understand allowing it in a new
> language. I just don't think it is a big issue - like many people, I
> have programmed in C (and other languages that need forward
> declarations) for many years without feeling this to be a concern.

I like to add functions in any order. I shouldn't have to consider that
the functions one may call are always defined earlier, or that the
functions that might call this one must be defined later. How do you
even find that spot in a busy module?

And you might want to move things around, or copy code between files.


>
>>
>>> Mutually dependent imports (circular imports) are an issue, but these
>>> can almost always be avoided in your code structuring.
>>
>> I've had experience of this and often found it difficult to impossible.
>
> Maybe you have a fundamentally different way of organising code than I
> do.

Let's take one project of mine (not C code obviously as it uses
modules), and look at two modules mc_name and mc_type (two successive
passes of a compiler). mc_name has this at the top:

import mc_type

And mc_type has this:

import mc_name.

Mutual imports. According to you, I should be able to trivially fix
that. Those modules ought to be independent, but sometimes things aren't
perfect.

mc_name calls one function in mc_type, but I can't just extract that
into a third module, as it has numerous connections to the rest of the
module. And it's the same story the other way. And unless I have /two/
extra new modules, I would be mixing up the gubbins from what are
supposed to be two unrelated modules, and exposing even more stuff that
is supposed to be kept private to each.

One more project where the two modules are cc_lex and cc_lib (a C
compiler). And it's the same thing where rearranging things so that the
modules are a pure hierarchy would mean tearing the project apart and
having a weird module structure that now needs an explanation.

(As I said, I solved this in the past by just adding a few manual
function declarations to cut across module demarcations. Now it is
easier for them just to import each other. It works fine.)

Melzzzzz

unread,
Jan 31, 2019, 4:07:24 PM1/31/19
to
On 2019-01-31, Bart <b...@freeuk.com> wrote:
> On 31/01/2019 15:50, David Brown wrote:
>> On 31/01/2019 13:06, Bart wrote:
>
>>> Co-recursion has some technical meaning which I'm not sure is the one
>>> that is relevant here. If you mean that A() calls B() which calls A(),
>>> then I write such code all the time.
>>
>> Mutual recursion is the term I wanted. There can be cases where this is
>> useful, in handling recursive data structures, but I think if you are
>> writing it a lot you have questionable coding structures.
>
> No it's not questionable. Most of the big programs I've written have
> involved recursive data. (CAD systems, windows-based GUIs, compilers and
> interpreters. Even file systems are recursive.) Obviously yours don't.

List is recursive data structure, so as tree and any graph for that
matter... are you sure you are arguing right thing?

Thomas Koenig

unread,
Jan 31, 2019, 4:17:35 PM1/31/19
to
Alf P. Steinbach <alf.p.stein...@gmail.com> schrieb:
> On 29.01.2019 19:31, Lynn McGuire wrote:
>> "C++ Modules Might Be Dead-on-Arrival"
>>    https://vector-of-bool.github.io/2019/01/27/modules-doa.html
>>
>> Cool, the author compared C++ to Fortran !
>
> Not in a way that said something good about C++ modules. :(

Not that there are a lot of good things to be said about the C++
module proposal. The question of which module is defined
in which file (well, you could put it into a Makefile when you
write it) is only one aspect. Another aspect is the question
of how to handle #defines which are in force when a module is
used...

Bart

unread,
Jan 31, 2019, 4:42:19 PM1/31/19
to
In the sorts of languages we're talking about, you would probably use
iteration for lists and recursion for anything that looks like a tree
because those would be the most practical choices.

But if you are going to add lists to the set of recursive data
structures, then that would just increase the number of programs that
use mutual recursion.

Melzzzzz

unread,
Jan 31, 2019, 5:33:55 PM1/31/19
to
Yeah list is first class citizen in recursive languages.

Öö Tiib

unread,
Feb 1, 2019, 4:32:54 AM2/1/19
to
On Thursday, 31 January 2019 22:42:39 UTC+2, Bart wrote:
> On 31/01/2019 15:50, David Brown wrote:
> > On 31/01/2019 13:06, Bart wrote:
>
> >> Co-recursion has some technical meaning which I'm not sure is the one
> >> that is relevant here. If you mean that A() calls B() which calls A(),
> >> then I write such code all the time.
> >
> > Mutual recursion is the term I wanted. There can be cases where this is
> > useful, in handling recursive data structures, but I think if you are
> > writing it a lot you have questionable coding structures.
>
> No it's not questionable. Most of the big programs I've written have
> involved recursive data. (CAD systems, windows-based GUIs, compilers and
> interpreters. Even file systems are recursive.) Obviously yours don't.

"Mutually recursive" about modules means that the modules have
circular dependency. The modules depend on existence of each other.
That is not strongly tied to recursive data of our programs.

Data where object of some type may have elements (or elements of
elements) of same type is recursive. That does not mean that
modules declaring these types are mutually recursive. Module A
of GUI widgets does not need to know anything about module B
of GUI widgets despite a program can use widgets from A and B as
subwidgets of each other. Instead in typical architecture both A
and B depend on module W that defines common loose-coupling
interfaces between super- and sub-widgets.

Circular dependency between modules indicates that the modules
were either separated pointlessly, incorrectly, not enough or
that the interfaces are too intrusive.
IOW it can be these should be joined, split even more, the
responsibilities clarified and/or the interfaces made more
generic.

The circular dependencies in GUIs is typically result of having
the program logic and often also parts of data leaked into GUIs.
That should not be blamed upon recursive nature of GUI. Damage
done by spaghetti-programmers is not easy to clean up and
can take years. C++ modules can help there as abstract
framework of architecture.

David Brown

unread,
Feb 1, 2019, 5:34:08 AM2/1/19
to
Recursive data structures do not always require mutually recursive
functions. You often want a simple recursive function (for lists, you
are likely to use iteration - but you might prefer recursion), applying
a visitor function as you move through the structure.

Again, I am not saying that mutual recursive functions are not useful,
or denying that they are a good choice for some programming constructs.
All I am saying is that they aren't needed much - writing an occasional
forward function declaration to support them really is not a hardship.




Wolfgang Kilian

unread,
Feb 1, 2019, 5:50:33 AM2/1/19
to
It looks like the C++ module proposal as such is reasonable and rather
similar to Fortran's most recent module/submodule system. (Apart from
the C++ habit of creating incomprehensible syntax.) The problem seems
to be the interaction with the preprocessor.

One of the best decisions of the Fortran committee in the past was to
*not* include a preprocessor in the standard. (Sorry, couldn't resist.)

-- Wolfgang

--
E-mail: firstnameini...@domain.de
Domain: yahoo

Bart

unread,
Feb 1, 2019, 6:48:40 AM2/1/19
to
The preprocessor (here I mainly mean macro processing and conditional
code) should have no effect on a /proper/ module system. Someone writes:

import A

then the interface imported from module A (from A.c, A.cpp, or some file
that has been generated) should be entirely unaffected by anything that
has gone before in this module.

If the proposed C++ module scheme is just a development of C's
text-based #include mechanism, then that's not going to cut it.

Further, you should be able to write:

import A
import A
import A

and the last two lines should be ignored. This doesn't need intervention
here, nor inside A (eg. "pragma once"). This stuff is the job of the
module system.

You should also be able to write either:

import A
import B

or:

import B
import A

with no difference. (If B itself imports A, then that's its business.)

If a module imports A, and A imports C, then in this module:

import A

nothing from C should be visible, or affect anything in this file.

If A exports something which has elements of C and that is needed being
able to use A, then then it may be necessary to import C too.

(It's not clear what my own implementation [not for C++] does. If A
exports a struct containing members of a type exported from C, then this
struct can be used normally from the main program, those members can be
accessed by name etc.

But the name of the type is not visible unless C is imported directly.
However that is not needed for the normal use of that exported type.)

--
bart

David Brown

unread,
Feb 1, 2019, 7:47:33 AM2/1/19
to
That is the intention of C++ modules.

It is also possible with well-designed C headers - but you do need to
design them appropriately.


> If the proposed C++ module scheme is just a development of C's
> text-based #include mechanism, then that's not going to cut it.

Everyone knows that. Text-based #include was simple to implement in the
early days of C, and very flexible - but you pay the price of not
knowing the preprocessor environment when a header is processed. C++
modules will not see macros defined by other files when they are
compiled, and they will not export the macros defined within the
modules. (Compiler "builtin" macros will, of course, be available.)

>
> Further, you should be able to write:
>
>   import A
>   import A
>   import A
>
> and the last two lines should be ignored. This doesn't need intervention
> here, nor inside A (eg. "pragma once"). This stuff is the job of the
> module system.

This should be fine. (It is also fine with well-designed C headers.)

>
> You should also be able to write either:
>
>   import A
>   import B
>
> or:
>
>   import B
>   import A

This should be fine. (It is also fine with well-designed C headers.)

>
> with no difference. (If B itself imports A, then that's its business.)
>
> If a module imports A, and A imports C, then in this module:
>
>   import A
>
> nothing from C should be visible, or affect anything in this file.
>

I am not sure on that. Certainly it cannot be as simple as you suggest.

Suppose module C provides a type "foo", and module A provides a type
that has a field of type "foo". Then clearly users of module A need
access to C's "foo" type.

It is reasonable that if A imports C for its implementation only, then
those parts are not visible in something that imports A. (I mean
visible to the user code - the compiler can see it, and use it in
optimisation, inlining, etc.)

It is a while since I have read the proposals for C++ modules, and they
are somewhat in flux - so I don't know how they handle this.

> If A exports something which has elements of C and that is needed being
> able to use A, then then it may be necessary to import C too.
>
> (It's not clear what my own implementation [not for C++] does. If A
> exports a struct containing members of a type exported from C, then this
> struct can be used normally from the main program, those members can be
> accessed by name etc.
>
> But the name of the type is not visible unless C is imported directly.
> However that is not needed for the normal use of that exported type.)
>

I think it is strange that /you/ don't know what /your/ implementation
of /your/ language does. What do the specification documents for your
language say?

Paavo Helde

unread,
Feb 1, 2019, 8:28:20 AM2/1/19
to
I'm not surprised at all, the amount of details one can hold in one's
head is not infinite. And specification documents for not so formal
projects have the unfortunate habit to go out of date in 15 minutes.




Bart

unread,
Feb 1, 2019, 8:56:05 AM2/1/19
to
On 01/02/2019 12:47, David Brown wrote:
> On 01/02/2019 12:48, Bart wrote:

>> If a module imports A, and A imports C, then in this module:
>>
>>   import A
>>
>> nothing from C should be visible, or affect anything in this file.
>>
>
> I am not sure on that. Certainly it cannot be as simple as you suggest.
>
> Suppose module C provides a type "foo", and module A provides a type
> that has a field of type "foo". Then clearly users of module A need
> access to C's "foo" type.

Yes, this my example from below. But why should A need access to "foo"?
That is, named access to that type.

Accessing only a field of that type, whatever A needs to do that is
taken care of. The implementation will need to know those details and
/it/ has access to all the modules.


> It is reasonable that if A imports C for its implementation only, then
> those parts are not visible in something that imports A. (I mean
> visible to the user code - the compiler can see it, and use it in
> optimisation, inlining, etc.)
>
> It is a while since I have read the proposals for C++ modules, and they
> are somewhat in flux - so I don't know how they handle this.
>
>> If A exports something which has elements of C and that is needed being
>> able to use A, then then it may be necessary to import C too.
>>
>> (It's not clear what my own implementation [not for C++] does. If A
>> exports a struct containing members of a type exported from C, then this
>> struct can be used normally from the main program, those members can be
>> accessed by name etc.
>>
>> But the name of the type is not visible unless C is imported directly.
>> However that is not needed for the normal use of that exported type.)
>>
>
> I think it is strange that /you/ don't know what /your/ implementation
> of /your/ language does. What do the specification documents for your
> language say?

This area is defined by the implementation, which means I have to try it
out to see what happens. Generally I see very few problems (but then I
also don't bother with 'public' and 'private' members).

I think what it does in this example is that top-level names exported by
C, which are visible to A, are not visible to the main program.

Slightly more elaborate example:

======================
c.m
======================
global record point = (int16 x,y) # 'global' is needed to export

======================
a.m
======================
import c
global record line = (point p,q)

======================
prog.m
======================
import a
line v = ((10,20),(30,40))

proc start=
println "V=", v.p.x, v.p.y, v.q.x, v.q.y
println =v.p.bytes
println =v.p.typestr
println =v.p.x.bytes
println =v.p.x.typestr
end
======================

The output is:
V= 10 20 30 40
BYTESIZE(V.P)= 4
TYPESTR(V.P)= record(i16 x,i16 y)
BYTESIZE(V.P.X)= 2
TYPESTR(V.P.X)= i16

So everything actually needed to make use of A's 'line' type is
available. But if I try and write:

point a,b

in prog.m, it doesn't work unless I import C.

Simpler example:

c.m contains: global const xyz = 77
a.m contains: import c; global const abc = xyz+100
prog.m contains: import a; ... print abc

Output is '177' which incorporates the value of xyz. But I can't
directly use 'xyz' unless I import C.

--
bart

David Brown

unread,
Feb 1, 2019, 9:12:25 AM2/1/19
to
On 01/02/2019 14:55, Bart wrote:
> On 01/02/2019 12:47, David Brown wrote:
>> On 01/02/2019 12:48, Bart wrote:
>
>>> If a module imports A, and A imports C, then in this module:
>>>
>>>    import A
>>>
>>> nothing from C should be visible, or affect anything in this file.
>>>
>>
>> I am not sure on that.  Certainly it cannot be as simple as you suggest.
>>
>> Suppose module C provides a type "foo", and module A provides a type
>> that has a field of type "foo".  Then clearly users of module A need
>> access to C's "foo" type.
>
> Yes, this my example from below. But why should A need access to "foo"?
> That is, named access to that type.
>

Maybe you want to make a new object of that same type? (Though "auto"
and "decltype" might handle it for you). If the type is an enumeration,
you'll want access to the enumeration constants too.

> Accessing only a field of that type, whatever A needs to do that is
> taken care of. The implementation will need to know those details and
> /it/ has access to all the modules.

That will often be the case, yes.

>
>
>> It is reasonable that if A imports C for its implementation only, then
>> those parts are not visible in something that imports A.  (I mean
>> visible to the user code - the compiler can see it, and use it in
>> optimisation, inlining, etc.)
>>
>> It is a while since I have read the proposals for C++ modules, and they
>> are somewhat in flux - so I don't know how they handle this.
>>
>>> If A exports something which has elements of C and that is needed being
>>> able to use A, then then it may be necessary to import C too.
>>>
>>> (It's not clear what my own implementation [not for C++] does. If A
>>> exports a struct containing members of a type exported from C, then this
>>> struct can be used normally from the main program, those members can be
>>> accessed by name etc.
>>>
>>> But the name of the type is not visible unless C is imported directly.
>>> However that is not needed for the normal use of that exported type.)
>>>
>>
>> I think it is strange that /you/ don't know what /your/ implementation
>> of /your/ language does.  What do the specification documents for your
>> language say?
>
> This area is defined by the implementation, which means I have to try it
> out to see what happens. Generally I see very few problems (but then I
> also don't bother with 'public' and 'private' members).
>
> I think what it does in this example is that top-level names exported by
> C, which are visible to A, are not visible to the main program.
>

I didn't need details of how it is implemented - I am not a user of your
language. I merely thought it was odd that you didn't know.

David Brown

unread,
Feb 1, 2019, 9:19:57 AM2/1/19
to
As far as I understand it, Bart has done professional work using this
language. To me, that means that the delivery of the code to the
customer has to include everything necessary for the customer to
maintain the code, even if the original developer is no longer
available. That normally means the code has to be in an established
language - the customer has to be able to hire a developer who knows the
language, and they need to be able to acquire the development tools. If
the language is obscure (and a single person home-made language is
obscure), the customer delivery would include the compiler/translator,
and at least basic specifications, documentation, examples, etc., so
that a new developer can learn what they need to know.

Perhaps Bart has a different sort of relationship or agreement with his
customers, or perhaps the generated C code is considered good enough as
"source code".

If this particular language is just for fun and hobby use, then I
understand how the details can be forgotten - not many people see
writing detailed language specifications or implementation manuals as
fun, and I fully appreciate it he has not written them.



Bart

unread,
Feb 1, 2019, 9:50:27 AM2/1/19
to
On 01/02/2019 14:19, David Brown wrote:
> On 01/02/2019 14:28, Paavo Helde wrote:
>> On 1.02.2019 14:47, David Brown wrote:
>>> On 01/02/2019 12:48, Bart wrote:
>>>> (It's not clear what my own implementation [not for C++] does. If A
>>>> exports a struct containing members of a type exported from C, then this
>>>> struct can be used normally from the main program, those members can be
>>>> accessed by name etc.
>>>>
>>>> But the name of the type is not visible unless C is imported directly.
>>>> However that is not needed for the normal use of that exported type.)
>>>>
>>>
>>> I think it is strange that /you/ don't know what /your/ implementation
>>> of /your/ language does.  What do the specification documents for your
>>> language say?
>>
>> I'm not surprised at all, the amount of details one can hold in one's
>> head is not infinite. And specification documents for not so formal
>> projects have the unfortunate habit to go out of date in 15 minutes.
>>
>
> As far as I understand it, Bart has done professional work using this
> language.

(No, only older versions of it from 80s to early 2000s. They didn't have
this module system but something much cruder (although still more
sophisticated that C's headers!).)

> If this particular language is just for fun and hobby use, then I
> understand how the details can be forgotten - not many people see
> writing detailed language specifications or implementation manuals as
> fun, and I fully appreciate it he has not written them.

(I did actually put something together recently, but you're right, it
was a bit of a slog, and not properly finished needing lots of editing:

https://github.com/sal55/mx/blob/master/mdocs.md

And it won't be finished because I'm already working on a new
replacement language. That will include many elements that are found in
C++ (eg. built-in flex arrays) but it will be dramatically simpler to
use and should still compile instantly. However, I have yet to actually
do it ...)

David Brown

unread,
Feb 1, 2019, 10:29:50 AM2/1/19
to
On 01/02/2019 15:50, Bart wrote:
> On 01/02/2019 14:19, David Brown wrote:
>> On 01/02/2019 14:28, Paavo Helde wrote:
>>> On 1.02.2019 14:47, David Brown wrote:
>>>> On 01/02/2019 12:48, Bart wrote:
>>>>> (It's not clear what my own implementation [not for C++] does. If A
>>>>> exports a struct containing members of a type exported from C, then
>>>>> this
>>>>> struct can be used normally from the main program, those members
>>>>> can be
>>>>> accessed by name etc.
>>>>>
>>>>> But the name of the type is not visible unless C is imported directly.
>>>>> However that is not needed for the normal use of that exported type.)
>>>>>
>>>>
>>>> I think it is strange that /you/ don't know what /your/ implementation
>>>> of /your/ language does.  What do the specification documents for your
>>>> language say?
>>>
>>> I'm not surprised at all, the amount of details one can hold in one's
>>> head is not infinite. And specification documents for not so formal
>>> projects have the unfortunate habit to go out of date in 15 minutes.
>>>
>>
>> As far as I understand it, Bart has done professional work using this
>> language.
>
> (No, only older versions of it from 80s to early 2000s. They didn't have
> this module system but something much cruder (although still more
> sophisticated that C's headers!).)

Fair enough.

Paavo Helde

unread,
Feb 1, 2019, 11:37:54 AM2/1/19
to
I fully agree that in an ideal world each professionally used program
and especially each compiler language should have a complete detailed
specification. But that's in an ideal world.

In the real world I guess the most prominent example of a language not
having a formal specification and relying on a reference implementation
only is Python, hyped to heaven and used professionally by millions.

PHP did not have a formal specification until 2014 either.



David Brown

unread,
Feb 1, 2019, 12:02:37 PM2/1/19
to
On 01/02/2019 17:37, Paavo Helde wrote:
>
> I fully agree that in an ideal world each professionally used program
> and especially each compiler language should have a complete detailed
> specification. But that's in an ideal world.
>
> In the real world I guess the most prominent example of a language not
> having a formal specification and relying on a reference implementation
> only is Python, hyped to heaven and used professionally by millions.
>
> PHP did not have a formal specification until 2014 either.
>
>

There are different levels of specification and documentation - often
you don't need very detailed or formal specifications. You just need
information about how the language works and what the features and
libraries do.



Thomas Koenig

unread,
Feb 1, 2019, 6:17:12 PM2/1/19
to
["Followup-To:" nach comp.lang.fortran gesetzt.]
Wolfgang Kilian <kil...@invalid.com> schrieb:
> On 31.01.2019 22:17, Thomas Koenig wrote:
>> Alf P. Steinbach <alf.p.stein...@gmail.com> schrieb:
>>> On 29.01.2019 19:31, Lynn McGuire wrote:
>>>> "C++ Modules Might Be Dead-on-Arrival"
>>>>    https://vector-of-bool.github.io/2019/01/27/modules-doa.html
>>>>
>>>> Cool, the author compared C++ to Fortran !
>>>
>>> Not in a way that said something good about C++ modules. :(
>>
>> Not that there are a lot of good things to be said about the C++
>> module proposal. The question of which module is defined
>> in which file (well, you could put it into a Makefile when you
>> write it) is only one aspect. Another aspect is the question
>> of how to handle #defines which are in force when a module is
>> used...
>>
>
> It looks like the C++ module proposal as such is reasonable and rather
> similar to Fortran's most recent module/submodule system. (Apart from
> the C++ habit of creating incomprehensible syntax.) The problem seems
> to be the interaction with the preprocessor.

The build system (which was proposed to be solved by referring to
some of Oracle via some sort of web server by a committee member,
but where the Oracle was supposed to have its info from was left
unspecified) was one point.

Interaction with the preprocessor was another.

Renaming when importing from a module was not supposed to be
possible, and modules were proposed to be independent of namespaces
- you could happily have identifiers from several namespaces in
a single module, and identifiers from one namespace distributed
across several modules.

I think the last two points show that the proposed C++ modules are indeed
fundamentally different from Fortran modules and submodules.

> One of the best decisions of the Fortran committee in the past was to
> *not* include a preprocessor in the standard. (Sorry, couldn't resist.)

And so people use the ill-suited C preprocessor anyway :-)

Kenny McCormack

unread,
Feb 2, 2019, 8:40:07 AM2/2/19
to
In article <q31f4r$6f1$1...@dont-email.me>,
David Brown <david...@hesbynett.no> wrote:
...
>I think it is strange that /you/ don't know what /your/ implementation
>of /your/ language does. What do the specification documents for your
>language say?

You two really, really need to get a room.

--
Just for a change of pace, this sig is *not* an obscure reference to
comp.lang.c...

0 new messages