September 09, 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

---------------------------------------



unit Unit1;

{$mode objfpc}{$H+}

interface

uses
  Classes, SysUtils, FileUtil, Forms, Controls, Graphics, Dialogs, StdCtrls;

type

  { TForm1 }

  TForm1 = class(TForm)
    Button1: TButton;
    Memo1: TMemo;
    procedure Button1Click(Sender: TObject);
  private
    { private declarations }
  public
    { public declarations }
    procedure ChangeTitle(x:string);
    procedure ChangeOtherTitle(x: string);
  end;

var
  Form1: TForm1;

implementation

{$R *.lfm}

{ TForm1 }

procedure TForm1.Button1Click(Sender: TObject);
begin
  ChangeTitle('test');
end;

procedure TForm1.ChangeTitle(x: string);
begin
   Memo1.Lines.Add(x);
end;

procedure TForm1.ChangeOtherTitle(x: string);
begin
   Memo1.Lines.Add(x);
end;

end.




Here is how it looks like in Lazarus.
In the class definition you type the declaration.

  public
    { public declarations }
    procedure ChangeTitle(x:string);

Then you press "control shift c" this will create the empty implementation.
Use "control shift up" to cycle between the interface section and the implementation section.


There are two keywords "interface" and "implementation" to separate the two sections.

Honestly. There is not much typing going on.

If you go want to go the the next procedure in the implementation section it is faster to go "control shift up" back to the interface section. And then go to the next method and go back "control shift up" to the implentation section than to press the arrow down button until you are at the next method.


Lazarus does not accept changes in the name of the parameter.

September 09, 2013
On Sunday, 8 September 2013 at 04:47:04 UTC, Jonathan M Davis wrote:
> On Saturday, September 07, 2013 10:00:05 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
>
> I confess that I really don't like this idea. I think that the separation of
> declarations and definitions is a serious downside of C++ and that it
> negatively impacts code maintenence. And from the recent discussion on this,
> it's clear that quite a few people agree with me.
>
> However, at the same time, there are some folks (like Manu) who really prefer
> to separate the declaration and definitions so that they can just see the
> signatures for an entire class' functions at once without seeing any
> definitions. Personally, I don't think that that's a big deal and that it's far
> better to just use generated documentation for that, but clearly there's not a
> consensus on that.
>
> </ snip>
>
> - Jonathan M Davis

I completely agree with Jonathan!
This will only produce more code which will lead to more bugs and more maintenance.
September 09, 2013
On Monday, 9 September 2013 at 00:43:39 UTC, H. S. Teoh wrote:
> Therefore, the *real* solution to this problem is to fix the compiler's
> .di output to give a proper overview of the class *automatically*, and
> nicely pretty-printed.

Yes, that should be superior approach in general though exact usability is very detail-specific - currently relation between .di and .d and not really well-defined and pulling this off will requires its own DIP at the very least.

For example, it is not entirely clear to me, what should happen if there are both .di and .d files in the file system at the same time and they have minor difference (remember, it is perfectly legal to tweak .di manually). It is likely, that improving .di tool chain will require similar signature matching verification anyway. Also I am wondering how to differ purely auto-generated .di files (should be updated completely upon build) and ones with manual changes (should be only verified).

It is all about small details.
September 09, 2013
On 9 September 2013 18:08, deadalnix <deadalnix@gmail.com> wrote:

> On Monday, 9 September 2013 at 07:00:23 UTC, Jacob Carlborg wrote:
>
>> On 2013-09-09 05:46, Manu wrote:
>>
>>> Missed the action...
>>>
>>> Well it's clear this is not a popular proposal.
>>> And even to me personally, it's certainly not of critical importance. If
>>> there was a single thing I'd like to see *DONE* in D, it would be
>>> temporary/r-value->ref args, without question (really, really annoying
>>> to work around).
>>>
>>
>> So what's wrong with this approach, that's already working today:
>>
>> class Foo
>> {
>>     void foo ();
>>
>>     void foo ()
>>     {
>>
>>     }
>> }
>>
>> void main ()
>> {
>>     auto foo = new Foo;
>>     foo.foo();
>> }
>>
>> BTW, this feature was implemented because you asked for it.
>>
>
> This is super useful to generate boilerplate from compile time reflection !
>

Which is what I requested it for, and use it very extensively.


September 09, 2013
On Monday, 9 September 2013 at 04:18:29 UTC, deadalnix wrote:
> For that second, it has been discussed in the thread to improve the di behavior to fit that role. Do think this is a viable approach, and that your team of happy devs would have benefited from that ?

Correct me if I'm wrong, but isn't the problem of using manually-written .di files to separate out class declaration and definition, that you consequently also have to manually include all the declarations of all the other module content?
September 09, 2013
"Jacob Carlborg" <doob@me.com> wrote in message news:l0jrm7$3199$1@digitalmars.com...
> On 2013-09-09 05:46, Manu wrote:
>> Missed the action...
>>
>> Well it's clear this is not a popular proposal.
>> And even to me personally, it's certainly not of critical importance. If
>> there was a single thing I'd like to see *DONE* in D, it would be
>> temporary/r-value->ref args, without question (really, really annoying
>> to work around).
>
> So what's wrong with this approach, that's already working today:
>
> class Foo
> {
>     void foo ();
>
>     void foo ()
>     {
>
>     }
> }
>
> void main ()
> {
>     auto foo = new Foo;
>     foo.foo();
> }
>
> BTW, this feature was implemented because you asked for it.
>
> -- 
> /Jacob Carlborg

Whoa, I didn't think of applying that to member functions.  This seems like the answer.  Put your variables and function prototypes at the top of your class.  Done.


September 09, 2013
On Monday, 9 September 2013 at 12:28:54 UTC, Dicebot wrote:
> On Monday, 9 September 2013 at 00:43:39 UTC, H. S. Teoh wrote:
>> Therefore, the *real* solution to this problem is to fix the compiler's
>> .di output to give a proper overview of the class *automatically*, and
>> nicely pretty-printed.
>
> Yes, that should be superior approach in general though exact usability is very detail-specific - currently relation between .di and .d and not really well-defined and pulling this off will requires its own DIP at the very least.
>
> For example, it is not entirely clear to me, what should happen if there are both .di and .d files in the file system at the same time and they have minor difference (remember, it is perfectly legal to tweak .di manually). It is likely, that improving .di tool chain will require similar signature matching verification anyway. Also I am wondering how to differ purely auto-generated .di files (should be updated completely upon build) and ones with manual changes (should be only verified).
>
> It is all about small details.

In languages like Modula-2, it is a compile error if there are differences.

So I would say D compilers should follow the same behavior, unless it is requested to generate .di files automatically, which will then overwrite the corresponding .di files.
September 09, 2013
On 09/09/13 15:12, Daniel Murphy wrote:
> "Jacob Carlborg" <doob@me.com> wrote in message
> news:l0jrm7$3199$1@digitalmars.com...
>>
>> So what's wrong with this approach, that's already working today:
>>
>> class Foo
>> {
>>      void foo ();
>>
>>      void foo ()
>>      {
>>
>>      }
>> }
>>
>> void main ()
>> {
>>      auto foo = new Foo;
>>      foo.foo();
>> }
>>
>> BTW, this feature was implemented because you asked for it.
>>
>> --
>> /Jacob Carlborg
>
> Whoa, I didn't think of applying that to member functions.  This seems like
> the answer.  Put your variables and function prototypes at the top of your
> class.  Done.

Problem -- what about:

    class Foo
    {
        // Declarations
        void foo();
        int bar(double n);

        // Definitions
        void foo() { .... }
        int bar(double n) { ....}

        // Whoops!  Forgot to include this one in the
        // declarations list, but it's still accepted
        // as part of the class
        void goo() { ... }
    }

A well-defined rule for separating out declarations and definitions would check for that and throw a compile error.
September 09, 2013
On 09/09/13 05:46, Manu wrote:
> For the record, I tend to agree with the arguments of many in the 'against' camp
> *from a purist point of view*, but the problem remains, and the reason I raised
> it; this has demonstrated to me and my colleagues on a number of occasions that
> it is a consistent productivity hindrance.

For what it's worth, I think this kind of baptism-by-fire practical experience is very valuable, and that it's worth considering carefully even if the final decision is not to implement the requested feature.

Question: do you have any access to information about similar short-deadline programming activity using other languages (Java, C# ...) that also forbid the separation of declaration and definition, and how devs using those languages cope with that?  It might offer an alternative solution that no one here has thought of.

> I support this DIP, obviously, but I'd suggest perhaps a conservative
> restriction that definitions should only be allowed to appear within the same
> module as the declaration. This would seem to simplify things like mangling
> issues and access rights. In my own use case, I have no reason to spread
> definitions across files. I just want to see class outlines clearly summarised
> at the top of the file. This saves time, and time is money.

I think the conservative approach is probably correct -- the class outline and the function definitions should have to be in the same module, and the outline and definitions should match precisely.  Any mismatch (including in variable names)?  Compile error.  A function in the outline that isn't implemented? Compile error.  A function implemented that isn't in the outline?  Compile error.  That should greatly reduce the possibility of error caused by code duplication.

Then it simply becomes a question of deciding if the manual labour of writing separate outlines and definitions is worth it.  I guess this is probably somewhere where a tool really _can_ be useful, to ensure that the definitions and the outline stay in sync.

Writing D code in this way should probably be disapproved of in the D style guidelines, but with the proviso that it's there for the circumstances where it really is useful.
September 09, 2013
On Monday, 9 September 2013 at 14:22:15 UTC, Joseph Rushton Wakeling wrote:
> Then it simply becomes a question of deciding if the manual labour of writing separate outlines and definitions is worth it.  I guess this is probably somewhere where a tool really _can_ be useful, to ensure that the definitions and the outline stay in sync.
>
> Writing D code in this way should probably be disapproved of in the D style guidelines, but with the proviso that it's there for the circumstances where it really is useful.

Very well spoken, this is exactly how I see it.