September 25, 2012
On Tue, 25 Sep 2012 15:23:50 -0400, deadalnix <deadalnix@gmail.com> wrote:

> Le 25/09/2012 20:57, Maxim Fomin a écrit :
>> On Tuesday, 25 September 2012 at 17:48:46 UTC, deadalnix wrote:
>>> This is code duplication and is generally considered as a bad
>>> practice. I'm not convinced that the language should be modified to
>>> allow something that is known as bad practice.
>>>
>>> What you need here is a more robust di generator IMO.
>>
>> This is neither a code duplication (there is certain distinction between
>> prototype and body) nor a bad practice - this is a common pattern in C
>> and C++. It is surprising that D cannot do such a simple thing which in
>> addition is not harmless, so there is no sense in depreciating it.
>
> This is code duplication. And this has been considered a problem in C/C++ for a while now.

No, it's a prototype.

Note that it's *required* if you want to hide implementation using .di files.

There is no code involved, it's just generating a symbol reference in the object file.

-Steve
September 25, 2012
On Tuesday, September 25, 2012 15:48:11 Steven Schveighoffer wrote:
> On Tue, 25 Sep 2012 15:23:50 -0400, deadalnix <deadalnix@gmail.com> wrote:
> > Le 25/09/2012 20:57, Maxim Fomin a écrit :
> >> On Tuesday, 25 September 2012 at 17:48:46 UTC, deadalnix wrote:
> >>> This is code duplication and is generally considered as a bad practice. I'm not convinced that the language should be modified to allow something that is known as bad practice.
> >>> 
> >>> What you need here is a more robust di generator IMO.
> >> 
> >> This is neither a code duplication (there is certain distinction between prototype and body) nor a bad practice - this is a common pattern in C and C++. It is surprising that D cannot do such a simple thing which in addition is not harmless, so there is no sense in depreciating it.
> > 
> > This is code duplication. And this has been considered a problem in C/C++ for a while now.
> 
> No, it's a prototype.
> 
> Note that it's *required* if you want to hide implementation using .di files.
> 
> There is no code involved, it's just generating a symbol reference in the object file.

It's still code duplication, because you've now listed the function signature twice. Yes, it's minimal code duplication, but it's still duplicating code. It's necessary for stuff like .di files (which are code duplication by definition, because they're duplicating a module - or at least part of it), but most everyone I know has thought (where it's come anyway) that prototypes were a _bad_ thing about C/C++. So, eliminating them as much as possible would generally be good, and even when it comes to .di files, given their limitations (e.g. disabling inlining and CTFE), we arguably should have a better solution for interface files anyway (e.g. having a binary file with the partially compiled code and generated documentation alongside it giving the API), in which case we wouldn't even need prototypes for interface files anymore. If anything, I'd argue that the fact that prototypes are part of the language is a sign of a deficiency in the language (especially if they're necessary).

- Jonathan M Davis
September 25, 2012
On Tue, 25 Sep 2012 16:07:51 -0400, Jonathan M Davis <jmdavisProg@gmx.com> wrote:

> On Tuesday, September 25, 2012 15:48:11 Steven Schveighoffer wrote:
>> On Tue, 25 Sep 2012 15:23:50 -0400, deadalnix <deadalnix@gmail.com> wrote:
>> > Le 25/09/2012 20:57, Maxim Fomin a écrit :
>> >> On Tuesday, 25 September 2012 at 17:48:46 UTC, deadalnix wrote:
>> >>> This is code duplication and is generally considered as a bad
>> >>> practice. I'm not convinced that the language should be modified to
>> >>> allow something that is known as bad practice.
>> >>>
>> >>> What you need here is a more robust di generator IMO.
>> >>
>> >> This is neither a code duplication (there is certain distinction  
>> between
>> >> prototype and body) nor a bad practice - this is a common pattern in  
>> C
>> >> and C++. It is surprising that D cannot do such a simple thing which  
>> in
>> >> addition is not harmless, so there is no sense in depreciating it.
>> >
>> > This is code duplication. And this has been considered a problem in
>> > C/C++ for a while now.
>>
>> No, it's a prototype.
>>
>> Note that it's *required* if you want to hide implementation using .di
>> files.
>>
>> There is no code involved, it's just generating a symbol reference in the
>> object file.
>
> It's still code duplication, because you've now listed the function signature
> twice. Yes, it's minimal code duplication, but it's still duplicating code.

I misunderstood, I was thinking in terms of generated code.

But in any case, it's still not duplicated code.  What you are doing is defining an interface, then attaching the implementation of the interface to the declaration by repeating its name.

Would you say repeating the function signature of an interface in an implementing class is code duplication?  Would you say that typing the name of a variable that you already declared so you could access it is code duplication?

Duplicated or not, it's still valid under the spec as far as I can tell.

> It's necessary for stuff like .di files (which are code duplication by
> definition, because they're duplicating a module - or at least part of it), but
> most everyone I know has thought (where it's come anyway) that prototypes were
> a _bad_ thing about C/C++.

The main reason for having prototypes in C/C++ was so you could declare a symbol that you weren't defining yet.

In some cases, this was necessary, because C/C++ does not have forward references.  So there is indeed very little reason in D to declare a function, then implement it in the same file.

But I think what Manu is trying to do is not exactly just "repeat the signature", he is using the signature of the original to generate the signature of the auto-generated function.  Essentially, it's not duplicated code on either the source or the compiled level, so disabling the ability to declare a function and then implement it later would prevent this possibility.  I don't think it makes sense to do that.

-Steve
September 25, 2012
On Tuesday, 25 September 2012 at 11:52:38 UTC, Manu wrote:
> So I have this recurring pattern, it's really starting to annoy me.
> It stems from the fact that a function prototype and the definition can not
> appear in the same file in D (as it can in C/C++)
> [...]
> Go on, tear me apart... :)

I'm not sure I understand what benefit you are giving, I'll explain a situation I went through.

tldr: I like having a clean "header" file for static linking. It would be nice to build off that to dynamically link.

I wanted to load up a DLL (C++ with C interface). Found this nifty file on stackoverflow

http://stackoverflow.com/questions/3818229/loading-plugins-dlls-on-the-fly

Didn't want to write all those mixins myself. I already had the "header" file for my DLL and didn't want to write all those mixins.

I created an array with all the function names, then created a function which took iterated this array and asked for the function type as I'd imported the "header."

I ran into a bunch of runtime errors with this setup, probably didn't like the duplication of function names. Or something completely different.

Finally I went to static linking. Since I had a nice clean header I didn't need to do anything fancy, pragma(lib) my .lib file and disable the defFunctions mixin.
September 25, 2012
On 09/25/2012 01:53 PM, Manu wrote:
> So I have this recurring pattern, it's really starting to annoy me.
> It stems from the fact that a function prototype and the definition can
> not appear in the same file in D (as it can in C/C++)
> Eg,
>
> void func(int x); // <-- declaration of function, informs type and
> associated names, args, ...
>
> //later
> void func(int x) // <-- may be generated with magic (and may use the
> prototype declaration for type information as declared by the prototype
> above)
> {
>    ... do stuff
> }
>
> I really need this. Why is it illegal? Is there chance of having this
> supported? What are the problems?
> ...

It is illegal because nobody has written code to support it. It
should be possible to support it. I don't think there are any problems
with the concept.
September 25, 2012
On 09/26/2012 01:29 AM, Timon Gehr wrote:
> On 09/25/2012 01:53 PM, Manu wrote:
>> So I have this recurring pattern, it's really starting to annoy me.
>> It stems from the fact that a function prototype and the definition can
>> not appear in the same file in D (as it can in C/C++)
>> Eg,
>>
>> void func(int x); // <-- declaration of function, informs type and
>> associated names, args, ...
>>
>> //later
>> void func(int x) // <-- may be generated with magic (and may use the
>> prototype declaration for type information as declared by the prototype
>> above)
>> {
>>    ... do stuff
>> }
>>
>> I really need this. Why is it illegal? Is there chance of having this
>> supported? What are the problems?
>> ...
>
> It is illegal because nobody has written code to support it. It
> should be possible to support it. I don't think there are any problems
> with the concept.

(The implementation faces some challenges, the following is easy to get wrong:

module module_;

void foo();

alias foo alias1;
static if(is(typeof(alias1))){
    void foo(){}
    alias foo alias2;
}

static assert(__traits(isSame, alias1, alias2));
static assert(__traits(allMembers, module_).length == 3); // 2 alias, 1 function definition
)
September 26, 2012
On 2012-09-25 22:07, Jonathan M Davis wrote:

> I'd argue that the fact that prototypes are part of the language is
> a sign of a deficiency in the language (especially if they're necessary).

They're necessary for linking with C functions. But except from that I agree with you.

-- 
/Jacob Carlborg
September 26, 2012
On 26 September 2012 02:35, Timon Gehr <timon.gehr@gmx.ch> wrote:

> On 09/26/2012 01:29 AM, Timon Gehr wrote:
>
>> On 09/25/2012 01:53 PM, Manu wrote:
>>
>>> So I have this recurring pattern, it's really starting to annoy me.
>>> It stems from the fact that a function prototype and the definition can
>>> not appear in the same file in D (as it can in C/C++)
>>> Eg,
>>>
>>> void func(int x); // <-- declaration of function, informs type and
>>> associated names, args, ...
>>>
>>> //later
>>> void func(int x) // <-- may be generated with magic (and may use the
>>> prototype declaration for type information as declared by the prototype
>>> above)
>>> {
>>>    ... do stuff
>>> }
>>>
>>> I really need this. Why is it illegal? Is there chance of having this
>>> supported? What are the problems?
>>> ...
>>>
>>
>> It is illegal because nobody has written code to support it. It should be possible to support it. I don't think there are any problems with the concept.
>>
>
> (The implementation faces some challenges, the following is easy to get wrong:
>
> module module_;
>
> void foo();
>
> alias foo alias1;
> static if(is(typeof(alias1))){
>     void foo(){}
>     alias foo alias2;
> }
>
> static assert(__traits(isSame, alias1, alias2));
> static assert(__traits(allMembers, module_).length == 3); // 2 alias, 1
> function definition
> )
>

I'm not sure I understand the point being illustrated here. I don't see how
the aliases are relevant?
Is an alias to a prototype somehow different than an alias to a definition?

Shouldn't the discovery of a function definition within the same file as a pre-declared prototype just promote the prototype to a full definition? They are the same symbol, just that one instance adds the definition.


September 26, 2012
Le 25/09/2012 22:43, Steven Schveighoffer a écrit :
>
> But I think what Manu is trying to do is not exactly just "repeat the
> signature", he is using the signature of the original to generate the
> signature of the auto-generated function. Essentially, it's not
> duplicated code on either the source or the compiled level, so disabling
> the ability to declare a function and then implement it later would
> prevent this possibility. I don't think it makes sense to do that.
>

This is why I suggested to improve the di generator instead of allowing that in the language in a first place.
September 26, 2012
Le 26/09/2012 10:14, Manu a écrit :
> On 26 September 2012 02:35, Timon Gehr <timon.gehr@gmx.ch
> <mailto:timon.gehr@gmx.ch>> wrote:
>
>     On 09/26/2012 01:29 AM, Timon Gehr wrote:
>
>         On 09/25/2012 01:53 PM, Manu wrote:
>
>             So I have this recurring pattern, it's really starting to
>             annoy me.
>             It stems from the fact that a function prototype and the
>             definition can
>             not appear in the same file in D (as it can in C/C++)
>             Eg,
>
>             void func(int x); // <-- declaration of function, informs
>             type and
>             associated names, args, ...
>
>             //later
>             void func(int x) // <-- may be generated with magic (and may
>             use the
>             prototype declaration for type information as declared by
>             the prototype
>             above)
>             {
>                 ... do stuff
>             }
>
>             I really need this. Why is it illegal? Is there chance of
>             having this
>             supported? What are the problems?
>             ...
>
>
>         It is illegal because nobody has written code to support it. It
>         should be possible to support it. I don't think there are any
>         problems
>         with the concept.
>
>
>     (The implementation faces some challenges, the following is easy to
>     get wrong:
>
>     module module_;
>
>     void foo();
>
>     alias foo alias1;
>     static if(is(typeof(alias1))){
>          void foo(){}
>          alias foo alias2;
>     }
>
>     static assert(__traits(isSame, alias1, alias2));
>     static assert(__traits(allMembers, module_).length == 3); // 2
>     alias, 1 function definition
>     )
>
>
> I'm not sure I understand the point being illustrated here. I don't see
> how the aliases are relevant?

From a compiler perspective, the example above is hell. That was his point.

In other terms, supporting such a feature add complexity to the compiler, and it should come with a sufficient benefice to make sense to implement.