September 07, 2013
On 9/7/13, Walter Bright <newshound2@digitalmars.com> wrote:
> http://wiki.dlang.org/DIP47

Am I correct to say that such member definitions will have the same overload rules as before? Currently using UFCS has issues where function hijacking prevention will cause errors at compile time, for example:

-----
module a;
import b;

struct A { }
void test(A a) { }  // hides B.test!

void main()
{
    B b;

    // error: function a.test (A a) is not
    // callable using argument types (B)
    b.test();
}
-----

-----
module b;
struct B { }
void test(B b) { }
-----

I just want to ensure that the following does not issue a compiler error:

-----
module a;
import b;
struct A { void test() { } }
void A.test() { }  // outlined

void main()
{
    B b;
    b.test();  // should be ok, A.test should not hide B.test!
}
-----

-----
module b;
struct B { void test() { } }
void B.test() { }  // outlined
-----
September 07, 2013
On Sat, Sep 07, 2013 at 07:28:39PM +0200, Jos van Uden wrote:
> On 7-9-2013 19:00, 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
> 
> 
> The problem is that it is optional, so when you're reading other people's code you'll still have to deal with inline definitions, and you'll need a decent editor (doesn't have to be an IDE, even basic editors like notepad++ and editpad pro support code folding and function lists) to easily read it.

This in itself is a pretty strong argument against this DIP. It introduces additional cognitive overload (now we have to learn a second syntax for defining class members), and *still* doesn't help the people who want this feature in the first place when they have to read others' code.

Not to mention, this will add additional complexity to the parser, and probably introduce more bugs related to function attributes -- for example:

- Should function attributes be repeated verbatim across the in-class
  declaration and the out-of-class definition?  If not, where can they
  be omitted?

- What about attribute inference? What if the definition has attributes
  that conflict with the in-class declaration?

- How will this interact with the current DI generation code?

- How will it affect forward references (which are currently already
  rather wonky in certain areas)?

- What about nested classes? Will they be allowed to have outlining
  member functions too? Where should their member definitions be, and
  what should their syntax be? How will attribute inference work for
  them?

I vote against this DIP. I feel like it's adding a lot of complexity to the language (and probably many more bugs to the compiler) for only a small gain. We already have enough wrinkles yet to be ironed out (scope, shared, auto ref, AA's, inout ambiguities, postblit, tail-const, emplace, the combinatorial explosion of all the different interactions between the foregoing, just to name a few), why are we introducing yet another level of complexity into the mix?


T

-- 
Tech-savvy: euphemism for nerdy.
September 07, 2013
On 7 September 2013 20:04, Jonas Drewsen <nospam4321@hotmail.com> wrote:
>> 3. Parameter names need not match.
>
>
> I think we should be conservative and require that parameter names match. This will ensure that code will not break in the future if named parameter functionality is added to the language at some point.
>

What about the absence of parameter names in the declaration?

struct Foo
{
   int bar (string, int, int);
}


int
Foo.bar (string str, int start, int end)
{
  /* ... */
}


-- 
Iain Buclaw

*(p < e ? p++ : p) = (c & 0x0f) + '0';
September 07, 2013
On 9/7/2013 12:05 PM, Andrej Mitrovic wrote:
> Am I correct to say that such member definitions will have the same
> overload rules as before?

Yes. This proposal does not add the outlined function name to any other scope than where it is declared, hence it cannot hide anything.
September 07, 2013
On 9/7/2013 11:39 AM, Paolo Invernizzi wrote:
> No pun intended, but having it as  _mandatory_ would be a little to much for
> people like me that don't like this proposal at all.

There's no way it would be mandatory.

September 07, 2013
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).

> 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.

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.

> @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.
September 07, 2013
On 9/7/13, Andrej Mitrovic <andrej.mitrovich@gmail.com> wrote:
> If 'val' will always refer to a.val in the declaration module

I meant if 'val' in the parameter list in the outlined function always refers to 'a.val'.
September 07, 2013
On 9/7/13, Walter Bright <newshound2@digitalmars.com> wrote:
> http://wiki.dlang.org/DIP47

> 1. Only member functions of aggregates at module scope can be outlined.

This is an unnecessary restriction. You haven't provided any reason in the DIP why #1 is necessary.
September 07, 2013
On 7-9-2013 20:39, Paolo Invernizzi wrote:
> On Saturday, 7 September 2013 at 17:28:42 UTC, Jos van Uden wrote:
>> On 7-9-2013 19:00, 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
>>
>>
>> The problem is that it is optional, so when you're reading other people's
>> code you'll still have to deal with inline definitions, and you'll need
>> a decent editor (doesn't have to be an IDE, even basic editors like
>> notepad++ and editpad pro support code folding and function lists) to
>> easily read it.
>
> No pun intended, but having it as  _mandatory_ would be a little to much for people like me that don't like this proposal at all.
>
> - Paolo Invernizzi


Exactly, so we're adding a lot of code noise, while you still have to use
an editor for codes that don't outline, so you might as well just use an
smart editor in the first place.
September 07, 2013
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)?

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
}

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.