August 27, 2012
On Monday, 27 August 2012 at 21:08:48 UTC, Maxim Fomin wrote:
> On Monday, 27 August 2012 at 20:29:15 UTC, deadalnix wrote:
>>
>> That guy just have to rework 5 projects. This is quite a lot of work.
>>
>> Obviously, that change have to be done. But you can't just impose such a change on users. Their agenda isn't synchronized with D's.
>>
>> D NEED a better versioning scheme, as explained MANY times here already.
>
> I may be considered rude, but as I have understood from the first post Manu
> 1) decided to use a not fully designed language feature
> 2) used this feature in public API when working with DLLs (which is by itself a problematic area)
> 3) integrated this with other language in a a way that require substantial rewrite and possibly redesign
> 4) updated compiler
> which I consider a process of looking for problems and no excuse for making code-break change. Anyway, older version of compiler is available.

All true, except one crucial fact: DMD gets critical bug fixes incorporated with new features in the same release. This leaves a poor choice to the programmer, either he sticks with older compiler version and can't get any critical bug fixes, or he updates the compiler to latest version with all the bug fixes but risks breakage of code due to new features (which is _exactly_ what happened to manu).

It's high time for D to split its dev version from the stable one. All major software have this, Debian, Linux, browsers (chrome, Firefox, etc), Windows, etc, etc. This is an ancient concept practiced for decades now in the software world.

August 27, 2012
On 28 August 2012 00:03, Walter Bright <newshound2@digitalmars.com> wrote:

> On 8/27/2012 3:32 AM, Manu wrote:
>
>> Here's an advanced trick I use a lot since D doesn't extern to static C++ methods (heavily simplified, this is way out of context):
>>
>> struct CPPClass
>> {
>>      this()
>>      {
>>          // not my actual code, but effectively, write 'this' and the C++
>> method
>> pointer into a delegate on initialisation [I wrap this process up using
>> magic]
>>          void** pDelegate = cast(void**)&**cppNonVirtualMethod;
>>          pDelegate[0] = this;
>>          pDelegate[1] = pCPPMethodPointer;
>>      }
>>
>>      void delegate(int x = 0) cppNonVirtualMethod; // C++ methods often
>> have
>> default args
>>
>
>        void delegate(int x) cppNonVirtualMethod;
>        void callCppNonVirtualMethod(int x) { (*cppNonVirtualMethod)(x); }
>        void callCppNonVirtualMethod() { callCppNonVirtualMethod(0); }
>
> With inlining on, the calls to the second overload should disappear, and you have the same code generated as you would for the default arg method. You could probably reduce the typing with some sort of mixin template, but this is the basic idea.


I've actually considered this approach, and the overload isn't required in
this case, since the true method can have a default arg. The same pattern
can apply at the global scope.
There are 2 reasons I didn't go for it:

Every api call is a double-call with inlining turned off (debug builds).
Debug builds are already slow enough, I didn't want to base a design
decision on that when it was perfectly syntactically reasonable to call
through the function pointers directly.
__forceinline would address this concern. (I really need this anyway for
the simd api. simd intrinsics are all wrapped in templates; if these are
not inlined, making a function call for every math opcode, it's gonna be
waaaaay slower than using the fpu)

And the second is forward declarations and function definitiona appearing
within the same file (I have a feature request on this).
The API is easily defined by the function pointer, but since the definition
needs to define the default args, what now needs to be defined is a forward
declaration/prototype.
The trouble is, my module magic mixin can't produce the bodies for the
stubs it finds because a prototype and definition can't appear in the same
file.

void functionDecl(int x = 10); // declaration by user (ideally with an
custom attribute: @engine_import, which would inform the magic generating
mixin to produce a stub and linkage code for this)

// **** magically generated by a mixin: ****
void function(int) __functionDecl_ptr;
__forceinline void functionDecl(int x)
{
   __functionDecl_ptr(x);
}
// **************
static this()
{
  __functionDecl_ptr = importExtern("functionDecl");
}
// **************

Sadly, there's a lot missing from the language to be able to do that, but I hope we can reach that place one day.


August 27, 2012
On Monday, August 27, 2012 23:22:39 foobar wrote:
> All true, except one crucial fact: DMD gets critical bug fixes incorporated with new features in the same release. This leaves a poor choice to the programmer, either he sticks with older compiler version and can't get any critical bug fixes, or he updates the compiler to latest version with all the bug fixes but risks breakage of code due to new features (which is _exactly_ what happened to manu).

Except that the change which is causing Manu problems _isn't_ a new feature. It's a bug fix. So, better versioning wouldn't necessarily have helped him any at all. At best, if we had a more complex versioning scheme, it could be decided that the bug fix was potentially disruptive enough that it should only be fixed in a more major release, but _every_ bug fix risks breaking code, especially when code could be relying on the buggy behavior.

- Jonathan M Davis
August 27, 2012
On 28 August 2012 00:08, Maxim Fomin <maxim@maxim-fomin.ru> wrote:

> On Monday, 27 August 2012 at 20:29:15 UTC, deadalnix wrote:
>
>>
>> That guy just have to rework 5 projects. This is quite a lot of work.
>>
>> Obviously, that change have to be done. But you can't just impose such a change on users. Their agenda isn't synchronized with D's.
>>
>> D NEED a better versioning scheme, as explained MANY times here already.
>>
>
> I may be considered rude, but as I have understood from the first post Manu 1) decided to use a not fully designed language feature
>

Where is that stated? It appeared to be a perfectly good, working, and
awesome(!) language feature.

2) used this feature in public API when working with DLLs (which is by
> itself a problematic area)
>

Are you suggesting using DLL's is asking for trouble? Dynamic linkage is a fundamental part of software.

3) integrated this with other language in a a way that require substantial
> rewrite and possibly redesign
>

D will interact with other languages in the real world, if anything, my doing so and talking about my approach and experience is a service.

4) updated compiler
>

No shit, D has loads of bugs which are rapidly fixed all the time.

which I consider a process of looking for problems and no excuse for making
> code-break change. Anyway, older version of compiler is available.
>

Whatever.


August 27, 2012
On 28 August 2012 00:11, Walter Bright <newshound2@digitalmars.com> wrote:

> On 8/27/2012 3:32 AM, Manu wrote:
>
>> Almost all my API's are dynamically bound to foreign code, eg:
>>
>> extern(C) void function( ref const(Vector2) v0, ref const(Vector2) v1, ref
>> const(Vector2) v2, ref const(Color) color = Color.white, BlendMode
>> blendMode =
>> BlendMode.Disabled ) fillTriangle2D;
>>
>
> These can all be handled in a straightforward (but admittedly wordy) method of wrapping the call to the function pointer in an overloaded function.
>

They can, see my prev post.

It's less readable, less maintainable, more obscure to those reading the code... the language had an awesome feature that addressed it directly. When mixins get involved, readability, syntax highlighting, and other basic IDE services all go out the window.

Perhaps the most important one that I forgot; debugging becomes VERY annoying. Try stepping into an engine API when it's wrapped up with magic... F10 (jumps to a rubbish API file, cursor disappears, stub code doesn't actually exist). Continue pressing F10 for a while until it eventually finds it's way into the function pointer. Repeat when leaving the function >_< .. Again, __forceinline would address this.

I understand that you've probably got so many of these, it's drudgery to
> make the edits.
>

It would be annoying.

Question: are the default values all of the form T.init? I.e. is
> Color.white == Color.init?
>

No, I don't think so. Color inits to black. Many enums also have an Unknown state. and float init's to NaN for some crazy reason ;)


August 27, 2012
On 08/27/2012 05:48 AM, Robert Clipsham wrote:

> I seem to recall I looked at this issue myself at one point. It goes
> something like:
> ----
> auto foo = (int a = 1) { return a; };
> auto bar = (int a) { return a; };
> ----
> int function(int) is mangled exactly the same as int function(int = 1)
> as default args aren't used for mangling. dmd does semantic analysis on
> the type of foo, which returns int function(int = 1), which is mangled
> as int function(int) and stored in dmd's hashmap of types (default args
> aren't mangled). When the semantic analysis of bar is done it checks the
> hashmap, sees that the type is already there (has the same name
> mangling) and does not repeat semantic analysis. If you switch the order
> of declarations then the opposite happens - the default arg is ignored.

I had opened a related bug recently:

  http://d.puremagic.com/issues/show_bug.cgi?id=8579

Ali
August 27, 2012
On 8/27/12 2:28 PM, Jonathan M Davis wrote:
> On Monday, August 27, 2012 23:22:39 foobar wrote:
>> All true, except one crucial fact: DMD gets critical bug fixes
>> incorporated with new features in the same release. This leaves a
>> poor choice to the programmer, either he sticks with older
>> compiler version and can't get any critical bug fixes, or he
>> updates the compiler to latest version with all the bug fixes but
>> risks breakage of code due to new features (which is _exactly_
>> what happened to manu).
>
> Except that the change which is causing Manu problems _isn't_ a new feature.
> It's a bug fix. So, better versioning wouldn't necessarily have helped him any
> at all.

Yah, this particular example is more of an example of the limitation of the stable/dev approach. Nevertheless, I do think we should switch to it.

But more importantly we must first move to an integrally automated, scripted method of releasing software. The amount of manual drudgery that goes into today's release process makes my blood curd. To paraphrase a famous quote, we can't improve what we don't have.


Andrei
August 27, 2012
On 8/27/2012 2:37 PM, Manu wrote:
> They can, see my prev post.
>
> It's less readable, less maintainable, more obscure to those reading the code...
> the language had an awesome feature that addressed it directly.
> When mixins get involved, readability, syntax highlighting, and other basic IDE
> services all go out the window.

Ok, thanks, it helps immensely to see just what you're trying to do. Let me think about it some more.
August 27, 2012
On Monday, August 27, 2012 14:54:52 Andrei Alexandrescu wrote:
> On 8/27/12 2:28 PM, Jonathan M Davis wrote:
> > Except that the change which is causing Manu problems _isn't_ a new feature. It's a bug fix. So, better versioning wouldn't necessarily have helped him any at all.
> 
> Yah, this particular example is more of an example of the limitation of the stable/dev approach. Nevertheless, I do think we should switch to it.

Oh, I agree. I'm just saying that this is not a problem that a major.minor versioning system would solve. Such a versioning scheme could definitely be beneficial, but I think that many of those asking for it seriously overestimate how much it will reduce breaking changes. Aside from whatever deprecations occur (the number of which has been diminishing), they're almost exclusively caused by bug fixes.

> But more importantly we must first move to an integrally automated, scripted method of releasing software. The amount of manual drudgery that goes into today's release process makes my blood curd. To paraphrase a famous quote, we can't improve what we don't have.

Agreed.

- Jonathan M Davis
August 27, 2012
On 08/27/12 13:46, Timon Gehr wrote:
> On 08/27/2012 01:16 PM, Artur Skawina wrote:
>> On 08/27/12 12:54, Timon Gehr wrote:
>>> On 08/27/2012 10:48 AM, Piotr Duda wrote:
>>>> 2012/8/27 Walter Bright <newshound2@digitalmars.com>:
>>>>> On 8/26/2012 11:14 PM, Piotr Duda wrote:
>>>>>>
>>>>>> Default args should be part of types (for passing them as template args etc, implicity convertable if they differs only on defaults) but not mangled in (since mangling is revelant only for linking, where defaults doesn't matter).
>>>>>
>>>>>
>>>>> And then there's a list of other bugs that show up. Now you have two different types showing up as the same type (i.e. name) to the linker, and you've got weird collisions.
>>>>
>>>> For linker these types should be identical, so there shouldn't be any collisions, unless D handles default args fundamentally different than C++.
>>>>
>>>
>>> You said they should be part of the type for passing as template args:
>>>
>>> auto foo(T)(T dg){
>>>      return dg();
>>> }
>>>
>>> // therefore
>>> assert(foo((int x=2)=>x)==2); // this instantiation
>>> assert(foo((int x=3)=>x)==3); // must differ from this one
>>> // ergo, they cannot have the same mangled symbol name!
>>
>> Anonymous functions must be unique anyway.
> 
> What is the point?

I misunderstood, my fault, sorry.

A template instantiation with a parameter containing a default argument must of course reflect that argument in the mangled name. Are there other cases where def-args can't be ignored? (not where they are just "lost", that is not a problem)

artur