March 14, 2014
On 3/13/2014 8:56 PM, Manu wrote:
> It does nothing to prevent the library case,

I addressed that in another post here, i.e. I'm very skeptical of the notion that a large code base built with no attempt at writing fast code is going to get fast with merely this change. I don't buy that high performance code comes by accident. If you wish to debate this, though, please reply to my other post on the topic, which expounds with more detail.


> or the don't-early-optimise case of implying breaking changes in the future.

Optimizing code often involves breaking the interface. For example, the existence or absence of a destructor can have dramatic differences in the code generated. (Even very experienced C++ coders are often unaware of this.)

March 14, 2014
On 14 March 2014 16:20, Walter Bright <newshound2@digitalmars.com> wrote:

> On 3/13/2014 8:40 PM, Daniel Murphy wrote:
>
>> "Walter Bright"  wrote in message news:lft8ok$2epl$1@digitalmars.com...
>>
>>  Also,
>>>
>>>      class C { final: ... }
>>>
>>> achieves final-by-default and it breaks nothing.
>>>
>>
>> No, it doesn't, because it is not usable if C introduces any virtual methods.
>>
>
> That's what the !final storage class is for.
>

Please don't consider !final, that's like pouring lemon juice on the would. Use virtual, it's a keyword that everybody knows and expects, and already exists in peoples code that they might be migrating to D.


March 14, 2014
On 3/12/2014 11:44 PM, Manu wrote:
> But you understand the danger in creating a situation where experts can't
> optimise their code even if they want to; if at some later time it becomes an
> issue, or some new customer comes along with more stringent requirements.
> These are not unrealistic hypothetical scenarios. Libraries exist, and they have
> customers by definition. Requirements change over time. Defaulting to an
> inflexible position is dangerous.

As I pointed out in another post, virtuality is hardly the only thing that can change in an interface that strongly affects performance. The existence of destructors is another. About everything about an interface affects performance.

March 14, 2014
On 3/13/14, 11:30 PM, Manu wrote:
> On 14 March 2014 16:20, Walter Bright <newshound2@digitalmars.com
> <mailto:newshound2@digitalmars.com>> wrote:
>
>     On 3/13/2014 8:40 PM, Daniel Murphy wrote:
>
>         "Walter Bright"  wrote in message
>         news:lft8ok$2epl$1@__digitalmars.com...
>
>             Also,
>
>                   class C { final: ... }
>
>             achieves final-by-default and it breaks nothing.
>
>
>         No, it doesn't, because it is not usable if C introduces any
>         virtual methods.
>
>
>     That's what the !final storage class is for.
>
>
> Please don't consider !final, that's like pouring lemon juice on the
> would.

The "wound" should have nothing to do with the decision. It would be a mistake to add a keyword here because "well, we had to give them something".

The converse of final doesn't deserve its own keyword. Also we do need a means to negate others, too.

> Use virtual, it's a keyword that everybody knows and expects, and
> already exists in peoples code that they might be migrating to D.

That does apply to C++ and maybe C# but not to other languages.


Andrei

March 14, 2014
On Friday, 14 March 2014 at 07:06:53 UTC, Andrei Alexandrescu wrote:
>> Use virtual, it's a keyword that everybody knows and expects, and
>> already exists in peoples code that they might be migrating to D.
>
> That does apply to C++ and maybe C# but not to other languages.
>

Yes, virtual by default is pretty what come by default nowadays.
March 14, 2014
On 3/13/14, 17:43, Walter Bright wrote:
> On 3/13/2014 3:21 PM, Timon Gehr wrote:
>> On 03/13/2014 02:32 PM, Steven Schveighoffer wrote:
>>>
>>> The one I would really like to see is logical OR. There is no easy way
>>> around this, one must come up with convoluted mechanisms that are much
>>> harder to design, write, and understand than just version(x || y)
>>
>> version(A) version=AorB;
>> version(B) version=AorB;
>> version(AorB){ }
>>
>
> If you're writing things like that, it's still missing the point. The
> point is not to find workarounds, but to rethink just what feature is
> being version'd on.
>
> For example, suppose it's wrapping a call to SomeWackyFunction:
>
> version (Linux)
>      SomeWackyFunction();
> else version (OSX)
>      SomeWackyFunction();
> else
>      ... workaround ...
>
> Execrable answer:
>
>      version (Linux) version=LinuxOrOSX;
>      version (OSX) version=LinuxOrOSX;
>      ...
>      version (LinuxOrOSX)
>      SomeWackyFunction();
>      else
>          ... workaround ...
>
> This is execrable because LinuxOrOSX:
>
> 1. has no particular relationship to SomeWackyFunction()
> 2. makes for confusion if LinuxOrOSX is used also to version in other
> things
> 3. makes for what do I do if I add in FreeBSD? Rename to
> LinuxOrOSXOrFreeBSD ? yeech
>
>
> Better answer:
>
>      version (Linux) version=hasSomeWackyFunction;
>      version (OSX) version=hasSomeWackyFunction;
>      ...
>      version (hasSomeWackyFunction)
>      SomeWackyFunction();
>      else
>          ... workaround ...
>
> At least this is maintainable, though it's clumsy if that code sequence
> appears more than once or, worse, must be replicated in multiple modules.
>
> Even better:
>
>      --------
>      import wackyfunctionality;
>      ...
>      WackyFunction();
>      --------
>      module wackyfunctionality;
>
>      void WackyFunction() {
>          version (Linux)
>            SomeWackyFunction();
>          else version (OSX)
>              SomeWackyFunction();
>          else
>              ... workaround ...
>      }
>      --------
>
> Simple, maintainable, easy on the eye.
>
>


...And code duplication everywhere!
March 14, 2014
On Friday, 14 March 2014 at 07:06:53 UTC, Andrei Alexandrescu wrote:
> Also we do need a means to negate others, too.
>
> Andrei

I was going to ask "how many others" are there, but I came up with this list myself. Probably incomplete:

static
const/immtable (no "mutable") keyword
pure
nothrow

To a certain extent, there's also @safe/@system, in the sense that it might make sense to "negate" them, rather than "override" them with another keyword.

Still, when writing something like:
class A
{
@system nothrow:

    !nothrow
    !@system
    void foo();
}

I really reads awful: "not nothrow"/"not system"?
March 14, 2014
monarch_dodra píše v Pá 14. 03. 2014 v 07:41 +0000:
> On Friday, 14 March 2014 at 07:06:53 UTC, Andrei Alexandrescu wrote:
> > Also we do need a means to negate others, too.
> >
> > Andrei
> 
> I was going to ask "how many others" are there, but I came up with this list myself. Probably incomplete:
> 
> static
> const/immtable (no "mutable") keyword
> pure
> nothrow
> 
> To a certain extent, there's also @safe/@system, in the sense that it might make sense to "negate" them, rather than "override" them with another keyword.
> 
> Still, when writing something like:
> class A
> {
> @system nothrow:
> 
>      !nothrow
>      !@system
>      void foo();
> }
> 
> I really reads awful: "not nothrow"/"not system"?
class A
{
@system nothrow:

      disable(nothrow, @system) void foo();
}

or

class A
{
@system nothrow:

      disable(all) void foo();
}

March 14, 2014
On 3/14/2014 12:34 AM, 1100110 wrote:
> ...And code duplication everywhere!

Actually, very little of that.
March 14, 2014
On 3/14/14, 3:02, Walter Bright wrote:
> On 3/14/2014 12:34 AM, 1100110 wrote:
>> ...And code duplication everywhere!
>
> Actually, very little of that.
I don't know what you'd call this then...
Exact same bit of code, repeated multiple times for versions which could be OR'd together.


    version (X86)
    {
        enum RTLD_LAZY = 0x00001;
        enum RTLD_NOW = 0x00002;
        enum RTLD_GLOBAL = 0x00100;
        enum RTLD_LOCAL = 0x00000;
    }
    else version (X86_64)
    {
        enum RTLD_LAZY = 0x00001;
        enum RTLD_NOW = 0x00002;
        enum RTLD_GLOBAL = 0x00100;
        enum RTLD_LOCAL = 0x00000;
    }
    else version (MIPS32)
    {
        enum RTLD_LAZY = 0x0001;
        enum RTLD_NOW = 0x0002;
        enum RTLD_GLOBAL = 0x0004;
        enum RTLD_LOCAL = 0;
    }
    else version (PPC)
    {
        enum RTLD_LAZY = 0x00001;
        enum RTLD_NOW = 0x00002;
        enum RTLD_GLOBAL = 0x00100;
        enum RTLD_LOCAL = 0;
    }
    else version (PPC64)
    {
        enum RTLD_LAZY = 0x00001;
        enum RTLD_NOW = 0x00002;
        enum RTLD_GLOBAL = 0x00100;
        enum RTLD_LOCAL = 0;
    }
    else version (ARM)
    {
        enum RTLD_LAZY = 0x00001;
        enum RTLD_NOW = 0x00002;
        enum RTLD_GLOBAL = 0x00100;
        enum RTLD_LOCAL = 0;
    }
    else version (AArch64)
    {
        enum RTLD_LAZY = 0x00001;
        enum RTLD_NOW = 0x00002;
        enum RTLD_GLOBAL = 0x00100;
        enum RTLD_LOCAL = 0;
    }

Yeah there are a few differences, but it would be trivial to collapse this down...

Just for funsies:

    version (X86 || X86_64)
    {
        enum RTLD_LAZY = 0x00001;
        enum RTLD_NOW = 0x00002;
        enum RTLD_GLOBAL = 0x00100;
        enum RTLD_LOCAL = 0x00000;
    }
    else version (MIPS32)
    {
        enum RTLD_LAZY = 0x0001;
        enum RTLD_NOW = 0x0002;
        enum RTLD_GLOBAL = 0x0004;
        enum RTLD_LOCAL = 0;
    }
    else version (PPC)
    {
        enum RTLD_LAZY = 0x00001;
        enum RTLD_NOW = 0x00002;
        enum RTLD_GLOBAL = 0x00100;
        enum RTLD_LOCAL = 0;
    }
    else version (PPC64 || ARM || AArch64)
    {
        enum RTLD_LAZY = 0x00001;
        enum RTLD_NOW = 0x00002;
        enum RTLD_GLOBAL = 0x00100;
        enum RTLD_LOCAL = 0;
    }


Oh wait, isn't 0x00000 the same as 0? (I honestly don't know if that matters, but assuming it doesn't...)

    version (X86 || X86_64 || PPC || PPC64 || ARM || AArch64)
    {
        enum RTLD_LAZY = 0x00001;
        enum RTLD_NOW = 0x00002;
        enum RTLD_GLOBAL = 0x00100;
        enum RTLD_LOCAL = 0x00000;
    }
    else version (MIPS32)
    {
        enum RTLD_LAZY = 0x0001;
        enum RTLD_NOW = 0x0002;
        enum RTLD_GLOBAL = 0x0004;
        enum RTLD_LOCAL = 0;
    }

Huh, for not having any code duplication it sure is a hell of a lot shorter when combined...