What about namespaces ?

B

BartC

The best part about this way of implementing namespaces in C is that it
would open the door to polymorphism, similar to the one implemented
through
the _Generic() keyword in C11. Consider the following example:
namespace foo
namespace int_version
void do_stuff(int param)
namespace float_version
void do_stuff(float param)
using namespace foo::int_version, foo_float_version;
foo::float_version?

do_stuff(1); // this would call foo_int_version_do_stuff(1);

do_stuff(1.0f); // this would call foo_float_version_do_stuff(1);

Looks deceptively simple, but I think would very quickly become a nightmare
to implement, or understand. You're trying match a set of N parameter (and
return?) types, against a set of M identically-named functions. There might
be more than one match. Or there might be no perfect matches, while some can
match if you perform a cast on one or more arguments.

And then there is the search order to consider, even when parameter types
are not significant.

Also, don't you still have to duplicate essentially the same code in each
function? Unless this covers template programming too..
 
M

Malcolm McLean

בת×ריך ×™×•× ×©×œ×™×©×™, 3 ב×פריל 2012 21:27:46 UTC+1, מ×ת Rui Maciel:
This would imply that using short identifier names somehow represents the
right way of doing things, but I don't see how anyone can claim that a piece
of code can improve if someone decides to employ a form of dictionary
compression on the identifier names, or if a function is somehow made worse
if an extra letter is added to its identifier.
That's important.

You want "mean" for an average, not meanf, meand and so on, which soon creates a situation where the user is left scratching round in the documentation for the right name, and maybe what it does (is stdev_s sample standard devation, or deviation of a list of shorts?)
 
S

Stefan Ram

Malcolm McLean said:
You want "mean" for an average, not meanf, meand and so on,
which soon creates a situation where the user is left
scratching round in the documentation for the right name, and
maybe what it does (is stdev_s sample standard devation, or
deviation of a list of shorts?)

One can devise such a language:

....
import standard_math_mean_double_2 as mean;
....
mean( 2.0, 3.0 )
....

But what we can do today:

....
inline static double mean
( int const alpha, int const beta )
{ return standard_mean_double_2( alpha, beta ); }
....
mean( 2.0, 3.0 )
....

(called »forwarding«).
 
R

Rui Maciel

Stefan said:
In this regard, one can also read the paragraph starting with

»The sad conclusion that namespaces were a mistake.«

http://www.informit.com/guides/content.aspx?g=cplusplus&seqNum=286

The thesis presented in that article is that "namespaces were a mistake" due
to the following two reasons:
- programmers may use namespaces in a way that the author doesn't like
- operator overloading may have led the implementation of argument dependent
lookup in some compilers way back in 2006 to be a bit dodgy


The first reason is a bit silly while the second one doesn't apply to the C
programming language.


Rui Maciel
 
I

Ian Collins

One can collect all names of a library in a struct. The struct is then
published by a pointer. So there only is a single external identifier
necessary per lib, which can be edited in the case of a clash.

What about functions?
 
B

Ben Bacarisse

One can collect all names of a library in a struct. The struct is then
published by a pointer. So there only is a single external identifier
necessary per lib, which can be edited in the case of a clash.

That does not work for types and constants.
 
I

Ian Collins

You want to know how to store a function pointer in a struct?

I didn't say function pointer, I said function.

struct A
{
void (*fn)(int);
};

int main()
{
// How do I define or call A::fn without an A?
}
 
S

Stefan Ram

Ian Collins said:
struct A
{
void (*fn)(int);
};

int main()
{
// How do I define or call A::fn without an A?
}

Some external identifiers are needed. But this is the same
for functions as it is for objects.

#include <A.h>

int main()
{ struct A const * const a = open_A();
if( a )
{ a->fn();
a->close(); }}

One needs to export »open_A« and »struct A«, and types and
constants as Ben wrote, but at least, function names like
»fn« and some other names are »in a namespace«.
 
I

Ian Collins

Some external identifiers are needed. But this is the same
for functions as it is for objects.

#include<A.h>

int main()
{ struct A const * const a = open_A();
if( a )
{ a->fn();
a->close(); }}

One needs to export »open_A« and »struct A«, and types and
constants as Ben wrote, but at least, function names like
»fn« and some other names are »in a namespace«.

So while "One can collect all names of a library in a struct" that
doesn't really emulate a namespace, does it? What you get is an
approximation to a C++ struct or class.

Now the irony is C++ structs *can* emulate many of the features of a
namespace!
 
G

Guest

I think you understate this. What he showed wasn't what "programmers" did,
but how actual standards writers and implementors abused and diminished
namespaces.

Namespaces don't prevent name clashing. As regards naming conflicts,
namespaces are hardly any different than prefixing and undercores. That's
because everybody prefers to use (and reuse) short, easy to remember
prefixes--like xml or dns or socket or, in the C++ case, "std". The
alternative is to go the Java route, incorporating global namespaces a la
DNS or X.500. One leaves you, effectively, with the status quo; the other
leads somewhere many people don't want to go.

I'm not sure namespaces quite leave you at status quo. You have the option of using a using directive- and using short names

using my_wonderful_sockets;
socket.open();

or ommitting the using directive and having long names
my_wonderful_sockets::socket.open();

but also (I understand) having some sort of namespace alias
sock::socket.open();


If sock:: turns out to collide you can fiddle with aliases and using directives until you get the right library.

Even using the using directive you've eliminated all those other socket.open() versions that might confuse things.

C++'s problem might be that the standard libary is a pretty poor example ofhow to partition a namespace! ie. not to partition it at all. The reason they tell you not to stick "using std;" in, is because it stuffs thousands of names into your namespace. "using" wouldn't be such bad news with decently sized namespaces.
 
K

Kaz Kylheku

That does not work for types and constants.

It doesn't matter because these things do not have linkage. Clashes
among names that don't have any sort of pervasive scope such as external
linkage can be solved with a local renaming.

E.g. two library header files define "struct foo". No problem.

#define foo abc_foo
#include "abclib.h"
#undef foo

#define foo xyz_foo
#include "xyzlib.h"
#undef foo

Now abclib's struct foo is called struct abc_foo.

C++ is worse in this regard because class names have linkage.

This is why C++ needs namespaces: so you can put classes in them.
If two libraries in a C program make "typedef struct stack" it's not
as bad as two "class stack" in the same C++ program.

As far as external name clashes go, that can be solved by technologies
outside of C, such as symbol export controls on shared libraries.
That is to say, you can have external names in a shared library, referenced
among its modules, which are not exposed outside of the shared library. The
external API is often a lot smaller than the sum total of all API's contained
in the component, internal plus external.

Even a short prefix on names goes a long way. A random three-letter prefix
gives you 26**3 possible namespaces.

Higher level languages with bindings to C libraries can hide that cruft, and
that's pretty much what matters nowadays. Nobody cares about programming at
large in the C language with nice namespaces.

Ultimately, a namespace feature would just translate into some mangling
that the linker level.
What might be nice would be to treat underscores as virtual namespace
delimiters. If I want to have a bunch of symbols in a scope that all begin with
foo_ it would be nice to have:

prefix foo_ {
typedef int x; // this is really foo_x
struct stack { // this is really struct foo_stack
int x; // this is just x
/* ... */
} s; // this is really foo_s
}

// pull foo_bar, foo_xyzzy and foo_x into this scope
// under the short aliases bar, xyzzy and x.
prefix foo_ bar, xyzzy, x;

This is just a dumb text processing hack that doesn't pretend it's anything
more (unlike C++ namespaces which are a text processing hack which pretends to
be more).

In the preprocessor:

#prefix FOO_
#define X Y // actually defines FOO_X Y
#endfix
#addpfx FOO_ A B C // #define-s A B C to be aliases for FOO_A, FOO_B, FOO_C.

Here, if FOO_B is a function-like macro, then B becomes a function-like
macro also. Design choices: it can have a life of its own (enduring after
#undef FOO_B) or it could be linked to FOO_B such that it follows redefinitions
of FOO_B, and disappears when #undef FOO_B is performed).
 
B

Ben Bacarisse

Kaz Kylheku said:
It doesn't matter because these things do not have linkage. Clashes
among names that don't have any sort of pervasive scope such as external
linkage can be solved with a local renaming.

That's a good point about types, but I was thinking, in part, about
#define constants and I don't think there is a simple way to rename
them. I see you've proposed a new mechanism for handling these, but I
am not sure it's entirely functional yet.
E.g. two library header files define "struct foo". No problem.

#define foo abc_foo
#include "abclib.h"
#undef foo

#define foo xyz_foo
#include "xyzlib.h"
#undef foo

Now abclib's struct foo is called struct abc_foo.

This can produce undefined behaviour because struct foo and struct
abc_foo are not compatible. I don't think that's likely to be a problem
in practice, but I worry that that rule is there for a reason I don't
fully understand.
C++ is worse in this regard because class names have linkage.

This is why C++ needs namespaces: so you can put classes in them.
If two libraries in a C program make "typedef struct stack" it's not
as bad as two "class stack" in the same C++ program.

As far as external name clashes go, that can be solved by technologies
outside of C, such as symbol export controls on shared libraries.
That is to say, you can have external names in a shared library, referenced
among its modules, which are not exposed outside of the shared library. The
external API is often a lot smaller than the sum total of all API's contained
in the component, internal plus external.

Even a short prefix on names goes a long way. A random three-letter prefix
gives you 26**3 possible namespaces.

Higher level languages with bindings to C libraries can hide that cruft, and
that's pretty much what matters nowadays. Nobody cares about programming at
large in the C language with nice namespaces.

Ultimately, a namespace feature would just translate into some mangling
that the linker level.
What might be nice would be to treat underscores as virtual namespace
delimiters. If I want to have a bunch of symbols in a scope that all begin with
foo_ it would be nice to have:

prefix foo_ {
typedef int x; // this is really foo_x
struct stack { // this is really struct foo_stack
int x; // this is just x
/* ... */
} s; // this is really foo_s
}

// pull foo_bar, foo_xyzzy and foo_x into this scope
// under the short aliases bar, xyzzy and x.
prefix foo_ bar, xyzzy, x;

This is just a dumb text processing hack that doesn't pretend it's anything
more (unlike C++ namespaces which are a text processing hack which pretends to
be more).

In the preprocessor:

#prefix FOO_
#define X Y // actually defines FOO_X Y

Sometimes you want this to define FOO_X FOO_Y because Y is also a macro
that will get renamed. I am not sure you can always tell how tokens in
the macro expansion should be treated. Maybe you can...
#endfix
#addpfx FOO_ A B C // #define-s A B C to be aliases for FOO_A, FOO_B, FOO_C.

Here, if FOO_B is a function-like macro, then B becomes a function-like
macro also. Design choices: it can have a life of its own (enduring after
#undef FOO_B) or it could be linked to FOO_B such that it follows redefinitions
of FOO_B, and disappears when #undef FOO_B is performed).

The idea of macro aliases might be the solution to the above problem,
but my brain is not working right now, so I need to think on this after
sleep!
 
T

Tim Rentsch

Rui Maciel said:
[snip]

So, with this in mind, what are your thoughts on the idea of introducing
namespaces to the C programming language? Would it be a bad idea?

To be convincing, any proposal to add a significant language
feature to C needs to make a compelling argument that the
benefits of doing so substantially outweigh the costs.

I think it's hard to make such an argument compelling for
namespaces, since (1) having namespaces doesn't add much
expressive power, and (2) obviously namespaces are not a
prerequisite for building (large) programs, given the
existence of multi-million-line C programs that do okay
without namespaces.
 
R

Rui Maciel

Tim said:
To be convincing, any proposal to add a significant language
feature to C needs to make a compelling argument that the
benefits of doing so substantially outweigh the costs.

I think it's hard to make such an argument compelling for
namespaces, since (1) having namespaces doesn't add much
expressive power, and (2) obviously namespaces are not a
prerequisite for building (large) programs, given the
existence of multi-million-line C programs that do okay
without namespaces.

It's also quite possible to write multi-million-line C programs using
i = i + 1 instead of i++, but yet the increment operator still is a valuable
C feature. In fact, this argument would extend to every single feature
added to C since K&R. Why add anything to the K&R version if these changes
don't add much expressive power and aren't prerequisite for building large
programs? And while we are at it, why should the C programming language be
developed at all? After all, there were already a good number of
programming languages floating around.

Because these changes are convenient and help the end user achieve their
goals with far less effort.


Rui Maciel
 
K

Kaz Kylheku

Rui Maciel said:
[snip]

So, with this in mind, what are your thoughts on the idea of introducing
namespaces to the C programming language? Would it be a bad idea?

To be convincing, any proposal to add a significant language
feature to C needs to make a compelling argument that the
benefits of doing so substantially outweigh the costs.

Evidently, though, a proposal does not need to be convincing (to the
programming public) to actually get into C.
 
J

Joe keane

C89 only had the first six characters being significant in
external identifiers.

And this is -totally- unworkable. I mean really, 'window_draw' and
'window_destroy' are the same?

Realistically, if one were confined to such a linker, it would be
necessary to implement some sort of symbol hashing, to write at-all
non-trivial software, and avoid insane programmers.
 
S

Stefan Ram

Realistically, if one were confined to such a linker, it would be
necessary to implement some sort of symbol hashing, to write at-all
non-trivial software, and avoid insane programmers.

Possibly, one could employ the preprocessor?

#define window_draw kP2RzQ
 
B

Ben Pfaff

Possibly, one could employ the preprocessor?

#define window_draw kP2RzQ

As long as we're talking about lousy linkers, C89 also allowed
the linker to ignore differences in case, so possibly there would
be no point in using both cases in your macro expansions.
 
B

BartC

Joe keane said:
And this is -totally- unworkable. I mean really, 'window_draw' and
'window_destroy' are the same?

Realistically, if one were confined to such a linker, it would be
necessary to implement some sort of symbol hashing, to write at-all
non-trivial software, and avoid insane programmers.

Perhaps writing a proper linker is an option. How difficult can it be?

It must be less effort to do that once, than for a bunch of programmers to
struggle with 6-character limitations for years.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,773
Messages
2,569,594
Members
45,118
Latest member
LatishaWhy
Top