September 07, 2013
On Saturday, 7 September 2013 at 17:00:08 UTC, Walter Bright wrote:
> Outlining of member functions is the practice of placing the declaration of a member function in the struct/class/union, and placing the definition of it at global scope in the module or even in another module.
>
> http://wiki.dlang.org/DIP47

Many details were ommited. Just some of them, others were raised.

1) If you allow to have definition in external module (by the way, this point is not clear), how can you control name mangling?

2) Does outlining limited only to static functions?

3) With UFSC if you have a.foo you cannot know where to found foo(a) - it can be hidden in dozens of imports, and if there are public imports, the situation becomes even more complex.
September 07, 2013
On 9/7/2013 12:56 PM, Maxim Fomin wrote:
> On Saturday, 7 September 2013 at 17:00:08 UTC, Walter Bright wrote:
>> Outlining of member functions is the practice of placing the declaration of a
>> member function in the struct/class/union, and placing the definition of it at
>> global scope in the module or even in another module.
>>
>> http://wiki.dlang.org/DIP47
>
> Many details were ommited. Just some of them, others were raised.
>
> 1) If you allow to have definition in external module (by the way, this point is
> not clear), how can you control name mangling?

You import the module containing the declaration. Like in C++.


> 2) Does outlining limited only to static functions?

No.

> 3) With UFSC if you have a.foo you cannot know where to found foo(a) - it can be
> hidden in dozens of imports, and if there are public imports, the situation
> becomes even more complex.

??? You find the declaration in the module that declares it. Same as for C++.
September 07, 2013
On 9/7/2013 12:30 PM, Andrej Mitrovic wrote:
> On 9/7/13, Walter Bright <newshound2@digitalmars.com> wrote:
>> 3. Parameter names need not match.
>
> I disagree with this, because it will practically guarantee that
> declarations and definitions go out of sync, which will be *harmful*
> for readability (which is partly what this DIP is all about).

Good point.

>
>> 4. If there is a default parameter value, it may only appear in the member function declaration.
>
> Also disagreed, because again you can't tell how a function can be
> called just by looking at its definition, now you have to go back and
> forth between the declaration and the definition to fully understand
> how the function works and how it can be used.

How a function is to be *used* should be all there in the *declaration*. Not the definition.

I didn't mention it in the DIP, and should, that the reason for the default value to be in the declaration is 1. it should only depend on the declaration's scope and 2. because all uses of it should rely only on the declaration and 3. because making an exact duplicate of it in the definition is pointless.

> On the other hand, allowing both the declaration and the definition to
> have the default values (which must match of course) might have issues
> with readability as well:
>
> module a;
>
> enum val = 1;
> struct S { void test(int x = val); }
>
> module a_impl;
>
> enum val = 2;
> void S.test(int x = val);  // a.val or a_impl.val?
>
> If 'val' will always refer to a.val in the declaration module, then
> there's no conflict, however it does create a bit of a readability
> issue.
>
> Still, I think default values should appear at both sides. It's very
> easy to forget you've defaulted a parameter when you start
> implementing the function, you could even implement it wrongly.

No, see above.


>> @safe/@trusted/@system, private/package/public/export access, linkage and storage classes are as set in the declaration, overriding any in effect for the definition.
>
> They should both match or there should be an error. Don't allow sloppy
> code to be written like that, people *will* read both the declarations
> and the definitions (the team or contributors in an open-source
> project), and any mismatch will only cause confusion.

I have mixed feelings about this. I think there needs to be just enough in the definition to match it to the declaration, and nothing else.

September 07, 2013
On Saturday, 7 September 2013 at 17:00:08 UTC, Walter Bright wrote:
> Outlining of member functions is the practice of placing the declaration of a member function in the struct/class/union, and placing the definition of it at global scope in the module or even in another module.
>
> http://wiki.dlang.org/DIP47

By the way, what is the ratio implemented DIPS/total DIPS? I guess it is <5%. Shouldn't it be a sign of DIP process flaws? I seems that many take care of pushing their ideas in form of DIPs but don't bother to take care of implementing them (last sentence obviously doesn't apply personally to Walter).
September 07, 2013
Like I said in Manu's thread, we can actually do this already, via pragma(mangle) hacks. That's brittle, the compiler doesn't tell you if you messed up the signature, but it works and gives answers to a lot of the questions in this thread.

class A {
   void foo();
}

pragma(mangle, A.foo.mangleof)
void foo_impl(A _this) {}


That's compile and run today. Things to note:

* The name is figured out by regular importing rules. A is whatever A is in schope.

* foo_impl might as well not exist as far as the outside world is concerned. It just is A.foo.

* I think the privacy should work this same way too: if it is in the same module, it can see private members, if not, it can't.
September 07, 2013
On 9/7/13, Walter Bright <newshound2@digitalmars.com> wrote:
> How a function is to be *used* should be all there in the *declaration*. Not the definition.

I mean the *header* part of the function's definition (everything up to the closing parens of the parameter list). If someone is currently looking at an implementation file:

void S.foo(int x) { ... }

They will assume 'x' must be specified.

You can argue that people shouldn't be looking at the implementation, but do have in mind two things:

1. This new feature is *optional*, meaning people will still look at the implementation for guidance, and not all new library writers will take advantage of this new feature.

This has the consequence that a user looking at a function called "foo", and looking at one called "S.foo" will have to be careful not to assume that "S.foo" documents the parameter list properly (because it can mismatch the declaration if you allow default arguments to be missing).

2. People are already used to looking at implementation files and method implementations in almost all public D projects. Header files have not proven to be popular among D projects.

> I didn't mention it in the DIP, and should, that the reason for the default value to be in the declaration is 1. it should only depend on the declaration's scope

The code in the function's body already depends on the declaration's scope. It would be a little strange if the body of the function has access to one scope, but the parameter list has either no scope or a different scope.
September 07, 2013
On 9/7/13, Adam D. Ruppe <destructionator@gmail.com> wrote:
> pragma(mangle, A.foo.mangleof)
> void foo_impl(A _this) {}

It's cute, but it it doesn't allow you to e.g. implement constructors outside the class. It also doesn't allow you to call a 'super' method without explicitly naming the class. E.g. with the above you can't do:

_this.super.foo();

You would have to change it to:

_this.ExplicitClassName.foo();
September 07, 2013
On 9/7/2013 1:14 PM, Maxim Fomin wrote:
> By the way, what is the ratio implemented DIPS/total DIPS? I guess it is <5%.
> Shouldn't it be a sign of DIP process flaws? I seems that many take care of
> pushing their ideas in form of DIPs but don't bother to take care of
> implementing them (last sentence obviously doesn't apply personally to Walter).

Even if they are unimplemented, the same ideas crop up repeatedly. The DIPs provide an anchor to avoid everyone repeating the same things.
September 08, 2013
On 9/7/2013 12:43 PM, Andrej Mitrovic wrote:
> On 9/7/13, Walter Bright <newshound2@digitalmars.com> wrote:
>> http://wiki.dlang.org/DIP47
>
> Your example code:
>
> -----
> struct S {
>      static int mfunc(int a, int b = 5) pure;	// member function declaration
> }
>
> int S.mfunc(int a, int b) pure {	// member function definition
>      ...
> }
> -----
>
> Two things:
>
> 1. Why are you demonstrating static functions and not regular member
> functions (or better yet why not both)?

Because I wanted to point out that you didn't need to put the 'static' in front of the definition.


> 2. Why has 'static' been removed at the outlined implementation
> function? It should also be there:
>
> static int S.mfunc(int a, int b) pure {	// member function definition
> }

Why?


> To reiterate, let's not introduce a feature where we can be totally
> lax about what we do at the declaration and implementation site. My
> strong opinion is that the declaration and implementation must
> perfectly match, otherwise you can throw the readability argument out
> the window.

On the other hand, DRY, and I don't recall anyone ever complaining about this in C++ outlined members.

September 08, 2013
"Walter Bright" <newshound2@digitalmars.com> wrote in message news:l0fm2o$2uat$1@digitalmars.com...
> Outlining of member functions is the practice of placing the declaration of a member function in the struct/class/union, and placing the definition of it at global scope in the module or even in another module.
>
> http://wiki.dlang.org/DIP47

I am strongly opposed to this DIP.  I think it brings a little slice of C++ hell to D.

This change will result in manually-synchronized duplication.  The argument that IDEs can deal with this automatically is irrelevant, because they currently can't and are unlikely to do so any time soon.

The main motivation for this seems to be that you can't get a clear overview of a class from looking at the raw source code.  I propose a much simpler solution to this:

** Introduce compiler-checked (via warnings) class summary documentation. **

This solves the problem - an overview of the class is available in the raw source code, and enabling the warning will prevent them from getting out of sync.

Let's solve a documentation issue with documentation improvements.