March 19, 2012
deadalnix wrote:
> As all functionnality of a Ship are final, you basically ends up with a mother ship that is a ship and then have some other function that are de facto separated and unreachable from ship.

Yes, because Ship is designed to be the common denominator among Ship types. This is not a problem, it's simply the far right side of access-limitation. There's no need to abstract the type (as you suggest below) simply because the base class went one function "to tight".


> Separation of concerns tells us that this should be 2 different objects.

MotherShip is still concerned with being a Ship. It's intended as a Ship, and should be classified as such. Removing the ability to express this only forces coders into needlessly wrapping functions:

  class Ship { final void fire() {} }
  class Bomber : Ship { void bomb() {} }

  void main() {
    auto b = new Bomber();
    b.fire(); // can fire() like other Ships automatically
  }

vs:

  class Bomber {
    Ship ship;
    void fire() { ship.fire(); } // have to wrap this
  }

This would be very annoying if you had many functions in the base class and would probably lead the authors writing a single unused virtual function into the base, just so they could derive types from it.


> As teha ddition of MotherShip to Ship are orthogonal, I would argue that mothership functionality is better suited for its own class/struct/whatever, and agregated with a ship.

A Ship wrapper is not conceptually a Ship. Nor could you cast a Ship pointer to it. All you're doing by aggregating types is complicating the structure for no-gain and loosing expression in the process.
March 23, 2012
Am Sun, 18 Mar 2012 04:49:12 +0100
schrieb "F i L" <witte2008@gmail.com>:

> On Sunday, 18 March 2012 at 03:27:40 UTC, bearophile wrote:
> > F i L:
> >
> >> I'm a bit confused. Reading through the virtual function's docs (http://dlang.org/function.html#virtual-functions) it says:
> >> 
> >> "All non-static non-private non-template member functions are virtual. This may sound inefficient, but since the D compiler knows all of the class hierarchy when generating code, all functions that are not overridden can be optimized to be non-virtual."
> >
> > This is so much theoretical that I think this should be removed from the D docs. And to be put back when one DMD compiler is able to do this. Otherwise it's just false advertising :-)
> >
> > Bye,
> > bearophile
> 
> Dammit, I was afraid someone would say something like that. Well at least it's a good goal. It is a bit of false advertising though, honestly it should just be marked "implementation in progress" or something like that.
> 

"the D compiler knows all of the class hierarchy when generating code"
This is just wrong, and if that was the base for deciding on virtual as default, I believe it is natural to think about it again.

Otherwise it should read "if you deal with non exported classes and don't use incremental compilation as well as refrain from compiling your code into static libraries, a D compiler can optimize methods to be non-virtual. As of the time of writing [...] no such compiler exists."

Now I feel better :)

-- Marco

March 23, 2012
Marco Leise wrote:
> "the D compiler knows all of the class hierarchy when generating code"
> This is just wrong, and if that was the base for deciding on virtual as default, I believe it is natural to think about it again.

Yes, further reading has led me to believe that Manu is right in his request for a virtual keyword (at least). Final by default is a great concept on paper, but unless it's possible across Lib boundaries (which I'm not sure it is) then to me it does seem a bit backwards given that efficiency is a key feature of D and most programmers are already used to fixed by default anyways.


March 23, 2012
On 03/23/2012 02:47 PM, F i L wrote:
> ...  and most programmers are already used
> to fixed by default anyways.
>

This assertion is unjustified.

March 23, 2012
On Friday, 23 March 2012 at 13:58:00 UTC, Timon Gehr wrote:
> On 03/23/2012 02:47 PM, F i L wrote:
>> ...  and most programmers are already used
>> to fixed by default anyways.
>>
>
> This assertion is unjustified.

Given that the four most popular languages today (Java, C, C++, and C#) all function this way, I'd say it's fairly accurate. But I also didn't to say Final by default should be default in D (though I wouldn't really disagree with that direction either), I do think D should have a virtual keyword.

March 23, 2012
> Given that the four most popular languages today (Java, C, C++, and C#) all function this way, I'd say it's fairly accurate. But I also didn't to say Final by default should be default in D (though I wouldn't really disagree with that direction either), I do think D should have a virtual keyword.

Whoops, that's wrong. Java is virtual by default. So I guess you're right, my statements aren't really justified.


March 23, 2012
On 3/18/12 9:23 AM, Manu wrote:
> The virtual model broken. I've complained about it lots, and people
> always say "stfu, use 'final:' at the top of your class".
>
> That sounds tolerable in theory, except there's no 'virtual' keyword to
> keep the virtual-ness of those 1-2 virtual functions I have... so it's
> no good (unless I rearrange my class, breaking the logical grouping of
> stuff in it).
> So I try that, and when I do, it complains: "Error: variable
> demu.memmap.MemMap.machine final cannot be applied to variable",
> allegedly a D1 remnant.
> So what do I do? Another workaround? Tag everything as final individually?
>
> My minimum recommendation: D needs an explicit 'virtual' keyword, and to
> fix that D1 bug, so putting final: at the top of your class works, and
> everything from there works as it should.

Is virtual-ness your performance bottleneck?
March 23, 2012
On 23 March 2012 17:24, Ary Manzana <ary@esperanto.org.ar> wrote:

> On 3/18/12 9:23 AM, Manu wrote:
>
>> The virtual model broken. I've complained about it lots, and people always say "stfu, use 'final:' at the top of your class".
>>
>> That sounds tolerable in theory, except there's no 'virtual' keyword to
>> keep the virtual-ness of those 1-2 virtual functions I have... so it's
>> no good (unless I rearrange my class, breaking the logical grouping of
>> stuff in it).
>> So I try that, and when I do, it complains: "Error: variable
>> demu.memmap.MemMap.machine final cannot be applied to variable",
>> allegedly a D1 remnant.
>> So what do I do? Another workaround? Tag everything as final individually?
>>
>> My minimum recommendation: D needs an explicit 'virtual' keyword, and to fix that D1 bug, so putting final: at the top of your class works, and everything from there works as it should.
>>
>
> Is virtual-ness your performance bottleneck?
>

Frequently. It's often the most expensive 'trivial' operation many
processors can be asked to do. Senior programmers (who have much better
things to waste their time on considering their pay bracket) frequently
have to spend late nights mitigating this even in C++ where virtual isn't
default. In D, I'm genuinely concerned by this prospect. Now I can't just
grep for virtual and fight them off, which is time consuming alone, I will
need to take every single method, one by one, prove it is never overloaded
anywhere (hard to do), before I can even begin the normal process of
de-virtualising it like you do in C++.
The problem is elevated by the fact that many programmers are taught in
university that virtual functions are okay. They come to the company, write
code how they were taught in university, and then we're left to fix it up
on build night when we can't hold our frame rate. virtual functions and
scattered/redundant memory access are usually the first thing you go
hunting for. Fixing virtuals is annoying when the system was designed to
exploit them, it often requires some extensive refactoring, much harder to
fix than a bad memory access pattern, which might be as simple as
rearranging a struct.


March 23, 2012
Something that *might* help is to do unit tests. Yeah,
that's kinda ass, but it would catch a stray virtual early.


Do a unit test that does a traits check for virtuals:

http://dlang.org/traits.html#getVirtualFunctions

if the name isn't on a list of approved virtuals,
static assert fail.

You'd then maintain the list of approved virtuals
in the unit test, where it is easier to check over.


idk though, I've never worked on a project like this.
March 24, 2012
On 23 March 2012 21:11, Adam D. Ruppe <destructionator@gmail.com> wrote:

> Something that *might* help is to do unit tests. Yeah, that's kinda ass, but it would catch a stray virtual early.
>

They're not necessarily 'stray' virtuals, they're inappropriate ones
There's a time and place for virtuals, but there's many more times and
places they shouldn't be :)
It's nice to be able to skim a class and see 'virtual' written clearly all
over it to gather some basic performance/usage information about the class.
The visual cue is important, and the ability to grep for them.

Rememer that virtuals are

Do a unit test that does a traits check for virtuals:
>
> http://dlang.org/traits.html#**getVirtualFunctions<http://dlang.org/traits.html#getVirtualFunctions>
>
> if the name isn't on a list of approved virtuals,
> static assert fail.
>

I've said this all before, but I'll repeat my general reasoning on the issue. My objection to virtual-by-default, but, acknowledging that can't be changed, insistence on a virtual keyword is this. (uh oh, manu-rant alert) :P

The top most compelling reason for switching from an extremely mature,
efficient, reliable, commercially accepted language like C/C++ to something
still relatively experimental (D) is to simplify code and maintenance long
term.
The goal is to do the same work we already do with less lines of code. They
should also be cleaner, tidier, less confusing, more informative lines of
code.
Adding a system like you describe to validate virtuals is not a complexity
I'm interested in implementing, it is just one clear reason to sick with
C++. Imagine presenting that to a building full of programmers who
are sceptical about changing from C++ in the first place? What will they
make of such a crude requirement when they already have a perfectly good
virtual keyword in C++?

D offers some amazing steps forwards in terms of powerful meta-programming.
Many typical C/C++ systems that require maintaining (and synchronising)
ugly tables of data, enums, stupid little functions and macros to do
trivial stuff; these can largely be removed in D. It is possible to invent
systems that take code and comprehend it implicitly, generating the desired
functionality, without having to pollute the classes themselves with extra
rubbish used by such a generator (see: user attributes thread).
Removing this sort of crap is something everyone can appreciate. But if we
have to revert to this behaviour to work around a different set of
problems, then we haven't really gained anything.

Code that remains tidy and maintainable for 10+ years (common in gamedev, game engines live ~2 console generations on average, often longer), but is still very fluid and dynamic (how gamedev code differs from other enterprise code, it changes frequently), and doesn't degrade in performance due to added complexity over years, is, fundamentally, SIMPLE code. It is also *LESS* code, the fewer lines, the more maintainable as a rule. And most certainly, code WITHOUT explicit tables of codegen related data; these are always the first things to rot and fall out of sync. There are often weird ancillary systems grown around these things to try and auto-magically maintain them, which themselves are just redundant noise, and contributes to further complexity and eventual bitrot. I've seen it time and time again. This is C++'s biggest shortcoming; the language only goes 90% of the way, and untold complexity is added to achieve the final 10%.

These such sorts of tables are why I fear an enum based serialisation system, or an enum based virtual function verification system. Who maintains these tables? It's only a matter of time before some clever bugger comes along and writes some fancy system to auto-magically manage these tables, and then every other programmer comes along, has no idea what to make of it anymore, and wonders what said clever bugger was smoking. This is just how it works out in practise. Then said clever bugger quits...
>_<

This is one of the key pains I hope to eliminate by using D, but I can't trade performance for it. The bar is high, competition is staunch, games consoles are fixed hardware. All the performance tuning mechanisms available in C/C++ must also be available in D (and generally are, plus more waiting to be taken advantage of). I shouldn't need to add complex workarounds for something so trivial as the missing virtual keyword :)


Side note..

I'm a language nerd, and I get excited by D, but I'm trying to think
critically about transplanting it realistically into the commercial
environment. I know what happens there, and it can only be adopted if a
significant numer of C++'s shortcoings are overcome, AND no new
shortcomings are added in the process. Most people aren't interested in D,
they may be sceptical and apprehensive to abandon something with 40 years
of maturity and a whole industry of support. They will not take the risk to
their business for a small number of improvements, especially if they lose
ANYTHING in the process.
It is in my interest to prove to those people undeniably that D is a step
forward in every regard. I believe that is what it will take to allow it to
be adopted widely in the commercial software world.

D is a competitor to C++. I know there are a lot that might disagree with me, maybe it explores some other avenues too, but in terms of direct competition to C++ (still the only real choice for realtime programming on limited systems), there is NOTHING ELSE. I think D needs to embrace what it is; a native systems language (finally) introducing modern concepts, and by extension, needs to take performance very seriously.

SIMD support is a great start, I really appreciate that one appearing out of nowhere almost overnight! :)