DIP79

From D Wiki
Jump to: navigation, search
Title: Negation of attributes
DIP: 79
Version: 1
Status: Draft (in progress)
Created: 2015-05-28
Last Modified: 2015-06-02
Author: Daniel Kozák
Links: [1]

Abstract

Proposal for a syntax change which will allow negation of attributes like (final, pure, nothrow, @nogc) without the need for new keywords.

Rationale

In D classes all non-final and non-template methods are virtual by default.

class C
    /* virtual */ void someMethod(){}
    /* virtual */ void someOtherMethod(){}
    ...
}

This in theory reduce some kind of bugs, when one forget to mark method as virtual. On the other hand it leads to some speed penalty. To improve speed you could mark your methods as final like this:

class C
{
    final void someMethod(){}
    final void someOtherMethod(){}
    ...
}

This works well, but is somehow annoying and tiresome to mark all methods as final. So some patterns has been introduced:

class C
{
// make all methods final
final:
    /* final */ void someMethod(){}
    /* final */ void someOtherMethod(){}
    ...
}

This is more handy and leads to less typing, but it has some drawbacks. If you need add few methods which are virtual or variables, you are forced to put them before final:.

class C
{
// all virtual methods must be here
    void someVirtualMethod(){}
    void nextVirtualMethod(){}

// even all variables must be here 
    int someVar;

// make all methods final
final:
    /* final */ void someMethod(){}
    /* final */ void someOtherMethod(){}
    ...
}

This is too limiting. Negation of attributes will remove these limits.

The proposed solution

There has been many NG discussions about possible syntax changes which will add negation of attributes possible (see alternative solutions section).

In this DIP I will address solution which use exclamation mark (!) for attribute negation.

Previous code example with this DIP could look like this:

class C
{
final:
    /* final */ void someMethod(){}
    !final void someVirtualBetweenFinalMethod(){}
    /* final */ void someOtherMethod(){}
    ...
!final:
    void someVirtualMethod(){}
    void nextVirtualMethod(){}

    int someVar;
}

Syntax

!final !@nogc !nothrow !pure

Implementation

my initial attempt: https://github.com/Kozzi11/dmd/tree/rever_attr

Future

In future a special syntax for negation of multiple attributes at once, can be added:

!(final @nogc nothrow pure) void someVirtalImpureAndThrowableFunctionUsingGC();

Pros & Cons

Pros

  • easy to implement
  • does not affect compile time speed and memory usage
  • readability

Cons

  • none from my POV

Alternative solutions

~attribute

This is same as proposed solution. But instead of ! char, ~ char will be used.

I like this one almost same as proposed solution. It shares same pros a cons.

@disable(attribute)

This is almost same as two previos solution. But instead of ~, @disable(attribute) expresion is used.

This one is little more verbose and need some extra step in parsing phase, so this is reason why I prefer one of previous solutions.

On the other hand in case of multiple negation, there will be no big difference.

@disable(final @nogc nothrow)

vs.

!(final @nogc nothrow)

or

~(final @nogc nothrow)

attribute(bool expression) or attribute!(bool expression)

This one is quite different. In basic variants attribute(true) and attribute(false) is same as all solutions above with just another syntax. But this syntax will allow us to use conditional expresion to affect result attribute. Eg.:

version(MakeItVirtual)
    enum virtual = true; // someVirtualOrFinalMethod will be virtual
else
    enum virtual = false; // someVirtualOrFinalMethod will be final

class C
{
final:
    final(virtual) someVirtualOrFinalMethod (){}
}

At first glance I like this solution most, because it is more powerful. But than I realize it makes code readability worse. Another disadvantage, implementation would be complicate.

Pros

  • expressiveness

Cons

  • not so easy to implement
  • affect compile time speed and memory usage
  • code readability will suffer
  • no pretty syntax for multiple negation

default

This one use completly different approach. Instead of negation of attributes it is more like unset all actually set attributes. Example:

class A
{
final:
pure:
nothrow:
    void someFinalPureNothrowFunction(){}
default: // unset final, pure and nothrow
    void couldBeVirtualImpureThrowFunction(){}
}

Copyright

This document has been placed in the Public Domain.