Thread overview
Compiler fails to identify conflict when using array parameters
Dec 23, 2005
Kris
Dec 24, 2005
Manfred Nowak
Dec 24, 2005
Stewart Gordon
Allow double declarations (was: Compiler fails to identify conflict when using array parameters)
Dec 25, 2005
Manfred Nowak
Re: Allow double declarations
Dec 26, 2005
Stewart Gordon
Dec 26, 2005
Manfred Nowak
Dec 26, 2005
Stewart Gordon
Dec 27, 2005
Manfred Nowak
Dec 27, 2005
Stewart Gordon
Dec 28, 2005
Thomas Kuehne
December 23, 2005
Conflict reported:

class Foo
{
        void foo (int i) {}
        void foo (int i) {}
}

No conflict reported:

class Foo
{
        void foo (char[] i) {}
        void foo (char[] i) {}
}




December 24, 2005
Kris wrote:

> Conflict reported:
[...]
> No conflict reported:
[...]

For a practical programmer the second case is not a problem because the conflict is reported as soon as the function is called, which is most likeley done in the `unittest'.

This is also consistent with the behaviour of not reporting conflicting definitions from imports until they are used.

Therefore only an irregularity can be found in the first case. But it is surely not a bug to report conflicts earlier than usual.

-manfred
December 24, 2005
Manfred Nowak wrote:
<snip>
> This is also consistent with the behaviour of not reporting conflicting definitions from imports until they are used.
<snip>

That's different.  Conflicting function names in different libraries are not a fault of either library.  It is the responsibility of the app programmer to disambiguate between them.

OTOH there is no possible way to disambiguate between the two functions in the OP's case.  As such, it is an error in the module in which the functions are defined.

Stewart.

-- 
My e-mail is valid but not my primary mailbox.  Please keep replies on on the 'group where everyone may benefit.
December 25, 2005
Stewart Gordon wrote:

[...]
> OTOH there is no possible way to disambiguate between the two functions in the OP's case.  As such, it is an error in the module in which the functions are defined.


Thanks for your input. It changed my view on the subject drastically.

Your argument is true and well founded under the assumption, that declarations should enable usage.

But if you drop this assumption it is becoming wrong. i.e. if you want a way to prohibit the usage of an identifier you are loosing a simple way, when double declarations are errored out by the compiler if in the same module.

For example look at the topic "Can I stop people deriving from my class?" in Stroustrups FAQ http://public.research.att.com/~bs/bs_faq2.html

Wouldn't it be neat to simply declare the constructor of class `Usable' twice?

-manfred
[X-posted and F'up to Digitalmars.D]
December 26, 2005
Manfred Nowak wrote:

> Stewart Gordon wrote:
> 
> [...]
> 
>>OTOH there is no possible way to disambiguate between the two
>>functions in the OP's case.  As such, it is an error in the
>>module in which the functions are defined.
> 
> Thanks for your input. It changed my view on the subject drastically.
> 
> Your argument is true and well founded under the assumption, that declarations should enable usage.
> 
> But if you drop this assumption it is becoming wrong. i.e. if you want a way to prohibit the usage of an identifier you are loosing a simple way, when double declarations are errored out by the compiler if in the same module.
> 
> For example look at the topic "Can I stop people deriving from my class?" in Stroustrups FAQ
> http://public.research.att.com/~bs/bs_faq2.html
> 
> Wouldn't it be neat to simply declare the constructor of class `Usable' twice?

That's because C++ doesn't (on the whole) support forward references.

And anyway, the OP on .bugs was trying to _define_ a function twice.

> -manfred
> [X-posted and F'up to Digitalmars.D]


-- 
My e-mail is valid but not my primary mailbox.  Please keep replies on on the 'group where everyone may benefit.
December 26, 2005
Stewart Gordon wrote:

[...]
> And anyway, the OP on .bugs was trying to _define_ a function twice.

I understand that. But what is the problem with two definitions without using them?

And why should I use a D-two-module-gimmick to undefine a previously defined symbol?

1) Imagine  the case, that at depth 1 of a derive hierachy I have declared a symbol `s' twice. At depth 2 this symbol is imported.

Your argument is, that at depth 2 one cannot disambiguate between those symbols `s' doubly declared  at depth 1. But thats a drop in the ocean. Throw away both definitions at depth 1 and replace them by  two definitions in two separate modules at depth 0, that are both imported at depth 1.

Now again at depth 2 you have two definitions imported from that module at depth 1. You can even disambiguate between both definitions. But to no avail because you do not know to which you have to disambiguate.

2) The argument for not having protective attributes on the module level is that in a module code can and therefore has to trust each other.

The same argument holds in this case, because both definitions are in the same module.

3) One can see double declarations as dead code, that has to be eliminated, but one can also see it as a comment, that one wants to be checked by the compiler.

In total: because D does not check conflicting definitions in imports to a module until one of them is to be used, it is an unnecessary restriction to disallow conflicting definitions in one module until they are used.

-manfred
December 26, 2005
Manfred Nowak wrote:
> Stewart Gordon wrote:
> 
> [...]
> 
>> And anyway, the OP on .bugs was trying to _define_ a function
>> twice. 
> 
> I understand that. But what is the problem with two definitions without using them?

That if they are in precisely the same scope, they cannot possibly be what the programmer meant.

> And why should I use a D-two-module-gimmick to undefine a previously defined symbol?

Why would you want to undefine a symbol?

> 1) Imagine the case, that at depth 1 of a derive hierachy I have declared a symbol `s' twice. At depth 2 this symbol is imported.
> 
> Your argument is, that at depth 2 one cannot disambiguate between those symbols `s' doubly declared at depth 1. But thats a drop in the ocean. Throw away both definitions at depth 1 and replace them by  two definitions in two separate modules at depth 0, that are both imported at depth 1.
> 
> Now again at depth 2 you have two definitions imported from that module at depth 1. You can even disambiguate between both definitions. But to no avail because you do not know to which you have to disambiguate.

Why would I put a function call in my code if I have no idea which function I want to call?

<snip>
> In total: because D does not check conflicting definitions in imports to a module until one of them is to be used, it is an unnecessary restriction to disallow conflicting definitions in one module until they are used.

Unnecessary to give a library programmer this level of error-checking before a user of the library tries to use the inadvertently doubly-defined function?  Strikes me as nonsense.

Stewart.

-- 
My e-mail is valid but not my primary mailbox.  Please keep replies on on the 'group where everyone may benefit.
December 27, 2005
Stewart Gordon wrote:

[...]
> Why would you want to undefine a symbol?

For example in the maintenance phase, to be sure that a previously defined symbol cannot be used anymore. But I am not sure about that. I have just posted in the learn group a question on how protective attributes work or should work ... to no avail.

Therefore: if there is no sure way to become previously defined symbols undefined are at least unreachable its plausible to not forbid a simple solution.


> Why would I put a function call in my code if I have no idea which function I want to call?

For example because you want to call the symbol `s' as declared above, but the interface changed while you were on your holidays.


> <snip>

Yeah. Snip away those arguments some hold up for not checking protective attributes within a module, but then you snip them away also for that subject.


> Unnecessary to give a library programmer this level of error-checking before a user of the library tries to use the inadvertently doubly-defined function?  Strikes me as nonsense.

Maybe its nonsense for a library programmer. But is D a library programming language?

And how do you know that it is unadvertently? Every once in a while someone asks about the functions which were imported with same names from different modules, although only one of them is used. In the case that none of this doubly imported symbols is used they would be offered undetected to other modules. Is that an error, because you assume, that the symbols offered from one single module must be unique? Then why is this not checked on import?

Coming to an end, I recognize that I have tried to answer all your questions, whilst you seems not to have answered any of mine. Please defend the position not to have unused doubly declared symbols in a module with arguments or declare that you want them this way out of the cathedral of your wisdom. But D is currently heterogene according to the uniqueness of identifiers, therefore no position is equipped with a status quo.

-manfred
December 27, 2005
Manfred Nowak wrote:
> Stewart Gordon wrote:
> 
> [...]
> 
>> Why would you want to undefine a symbol?
> 
> For example in the maintenance phase, to be sure that a previously defined symbol cannot be used anymore. But I am not sure about that. I have just posted in the learn group a question on how protective attributes work or should work ... to no avail.
> 
> Therefore: if there is no sure way to become previously defined symbols undefined are at least unreachable its plausible to not forbid a simple solution.

But because D supports forward references, it wouldn't work between the two definitions either.

Anyway, can you think of a real-world situation when you'd want to restrict access to an internal function and putting the stuff that uses it in a separate module isn't an option?

>> Why would I put a function call in my code if I have no idea which function I want to call?
> 
> For example because you want to call the symbol `s' as declared above, but the interface changed while you were on your holidays.

Then I would RTFD, or if not, RTFS.

>> <snip>
> 
> Yeah. Snip away those arguments some hold up for not checking protective attributes within a module, but then you snip them away also for that subject. 

Maybe we should have a "veryprivate" protection attribute: only stuff within the scope can access it.

>> Unnecessary to give a library programmer this level of error-checking before a user of the library tries to use the inadvertently doubly-defined function?  Strikes me as nonsense.
> 
> Maybe its nonsense for a library programmer. But is D a library programming language?

Almost any language is a library programming language to an extent. Sometimes the language to which a library is targeted is a good choice of the language in which to write it.

We have a group of people for which this checking is of value: library programmers.  We have a group of people for which it doesn't matter as much one way or another: application programmers.  One argument for fixing it, no arguments against.  Is this not sufficient support?

> And how do you know that it is unadvertently?

By the absence of any way in which the D spec makes it make sense.

> Every once in a while someone asks about the functions which were imported with same names from different modules, although only one of them is used. In the case that none of this doubly imported symbols is used they would be offered undetected to other modules. Is that an error, because you assume, that the symbols offered from one single module must be unique?

Only if the definitions are both in that very module.

> Then why is this not checked on import?

Because it would be stupid to stop somebody from using two libraries in the same application (or make it a nightmare to do so) just because they happen to have a symbol in common.

When the same identifier is used in multiple imported modules, they retain their distinct identities.

Take this:
----------
module module1;

void func() {}
----------
module module2;

void func() {}
----------
module module3;

import module1;
import module2;
----------
module module4;

import module3;
----------

module3 imports two functions called func.  But this doesn't matter, because they still have distinct identities, module1.func() and module2.func().  Now look at module4.  It imports both funcs from module3, because it imports module1 and module2.  Again, they are still module1.func() and module2.func().

OTOH, if you instead had

----------
module module3;

void func() {}
void func() {}
----------
module module4;

import module3;
----------

then they are module3.func() and module3.func().  Hence there is a name conflict.  Think not only the inability of the programmer to choose one, but also: how would the compiler mangle the names?

> Coming to an end, I recognize that I have tried to answer all your questions, whilst you seems not to have answered any of mine. Please defend the position not to have unused doubly declared symbols in a module with arguments or declare that you want them this way out of the cathedral of your wisdom. But D is currently heterogene according to the uniqueness of identifiers, therefore no position is equipped with a status quo.

I've had another look at your questions, and I'm not sure which you consider to be still unanswered.

Basically, there are two things wrong with the idea of doubly defining something in order to restrict access to it to a certain part of the module.  Firstly, it's incompatible with a design principle of D, namely that the order in which entities are declared within their scope is irrelevant.  Secondly, if you want to undefine a symbol, it seems silly to have to supply a new definition for the compiler to ignore.  If this were an intended language feature, it would be done in a neater way. Perhaps a means of grouping members into sections, each considered a scope at least from the POV of allowing access to the aforementioned veryprivate members.

Stewart.

-- 
My e-mail is valid but not my primary mailbox.  Please keep replies on on the 'group where everyone may benefit.
December 28, 2005
Kris schrieb am 2005-12-23:
> Conflict reported:
>
> class Foo
> {
>         void foo (int i) {}
>         void foo (int i) {}
> }
>
> No conflict reported:
>
> class Foo
> {
>         void foo (char[] i) {}
>         void foo (char[] i) {}
> }

At first it seemed like a no-brainer, but D certanly has some interresting properties.

is legal:
# module some_module;
# class A{}
# struct A{}
# enum A{ DUMMY }

is discurraged:
(statement.html: Local names should all be unique within a function.)
# void someFunction(){
#     class A{}
#     struct A{}
#     enum A{ DUMMY }
# }

Either my understanding of D's name spaces is severly lacking or the docs seem to be inconsistend.

By the way why "*should* be unique" and not "have to be unique"?

Thomas