January 15, 2020
On 15.01.20 06:31, Arine wrote:
> 
> It just needs @gc, and impure and i'd say it'd be good to go.

concrete, explicit, mutable, endorsed, runtime, internal, virtual, hide, unshared, dynamic, unsynchronized, dependable, __ungshared, ...
January 14, 2020
On 1/14/2020 3:04 PM, Adam D. Ruppe wrote:
> to make `nothrow:` (etc) go into the child scopes except templates means we have a less disruptive way to make this work without formally changing the defaults.

As I remarked before, this will have the unintended consequence of causing the "best practice" to be listing all the attributes at the opening brace of all struct declarations just in case someone 5000 lines previously added an:

    attribute:

Best practice:

    struct S
    {
        throw @safe pure @nogc etc. etc. etc. etc. ...
        ...
    }

and then have to remember to add to that list for every new attribute. It's ugly, and people are going to hate it.

January 15, 2020
On Wednesday, 15 January 2020 at 07:33:14 UTC, Walter Bright wrote:
> Best practice:
>
>     struct S
>     {
>         throw @safe pure @nogc etc. etc. etc. etc. ...
>         ...
>     }
>
> and then have to remember to add to that list for every new attribute. It's ugly, and people are going to hate it.

Honestly, based on experience of maintaining larger D codebases, I'm not sure it isn't anyway best practice to apply attributes (including protection attributes) only ever to individual symbols and functions.

It can look a bit verbose, and obviously it can be annoying in the way you describe, but it really helps avoid any doubt what attributes apply in any given case.
January 15, 2020
On Wednesday, 15 January 2020 at 07:33:14 UTC, Walter Bright wrote:
> [snip]
>
> Best practice:
>
>     struct S
>     {
>         throw @safe pure @nogc etc. etc. etc. etc. ...
>         ...
>     }
>
> and then have to remember to add to that list for every new attribute. It's ugly, and people are going to hate it.

Is that only an issue for child scopes? If you have a 5000 line file full of functions at the module level, then you run the risk of having to annotate all of them if someone puts attribute: at the top.

It's also interesting that @safe flows through, both with @safe: and @safe { code }.



January 15, 2020
On Tuesday, 14 January 2020 at 22:30:40 UTC, Walter Bright wrote:
> On 1/14/2020 8:44 AM, Dukc wrote:
>> This would be a step forward, of course. But would not it be better to kill the one-way attribute problem in one go -meaning, making an antiattribute for `pure` and `@nogc` too?
>
> Because for the anti-nothrow we already have a trivial solution staring us in the face, we just have to pick it up. I have no explanation for not seeing the obvious before.

Good.

>
>
>> In addition, I suggest that there should be a way to use [`pure:`/`nothrow:`/`@nogc:`/`@safe:`/their antiattributes] so that they only apply when attributes are not inferred - not for templated functions. This would also remove a big obstacle from front of DIP1028, as one could just mark the whole module `@system` with one statement without killing template `@safe` or `@live` inference.
>
> It turns out that there's another "attribute" under the covers - the default. Only when an attribute is the default does inference come into play. Hence, when "nothrow" becomes the default, there will be actually three states - throw, nothrow, and default.

Yes, correct. But what is worth mentioning ew are actually discussing about FOUR attributes: `throw`, `nothrow`, present default and the `nothrow` default. If the latest someday becomes the default, we suddently lose our ability to use the current default.

What I was saying that it would be worthwhile to make all those "default" attributes accessible so that is the scope already is, say `throw`, you can change it to the (current or likely-future) default behaviour. This will make the transition to nothrow-default much easier, as people can set their whole modules to the old default to keep legacy code running, or set the whole module to the new default so that the checks are done even before the transition.

>
> It works out rather nicely. It's in play for safe/trusted/system already, and has been since the beginning.

Setting the default this way should also be possible for `@system/`@safe/`@live` too (in theory, for `@trusted` too, but why in the world would anyone want to default to it?). And for other inferred attributes, if they get their antiattributes.


January 15, 2020
On Wednesday, 15 January 2020 at 07:33:14 UTC, Walter Bright wrote:
> As I remarked before, this will have the unintended consequence of causing the "best practice" to be listing all the attributes at the opening brace

I don't agree this is substantially different than the status quo, the unit of D's encapsulation is the module and it is expected things "spill over" inside a module boundary (see: private's semantics).

But we can have this discussion later if it is too far from this thread's purpose.

> and then have to remember to add to that list for every new attribute. It's ugly, and people are going to hate it.

People just won't do that. If you're happy with defaults, you'd simply not change the default at the top of the module!
January 15, 2020
On Wednesday, 15 January 2020 at 07:33:14 UTC, Walter Bright wrote:
> On 1/14/2020 3:04 PM, Adam D. Ruppe wrote:
>> to make `nothrow:` (etc) go into the child scopes except templates means we have a less disruptive way to make this work without formally changing the defaults.
>
> As I remarked before, this will have the unintended consequence of causing the "best practice" to be listing all the attributes at the opening brace of all struct declarations just in case someone 5000 lines previously added an:
>
>     attribute:
>
> Best practice:
>
>     struct S
>     {
>         throw @safe pure @nogc etc. etc. etc. etc. ...
>         ...
>     }
>
> and then have to remember to add to that list for every new attribute. It's ugly, and people are going to hate it.

I already have `@nogc nothrow pure:` at the top of almost every module. I also have the same at the top of every struct. It's happening right now, and it's not optional because you have to set the attributes based on the default. The only reason you never would have come across this is if you don't care about using those attributes as the default.


*Current Day Best Practice, That's unavoidable if you want these attributes for everything*:

    module blah;
    @nogc nothrow pure:

    struct A {
    @nogc nothrow pure:
    }

    struct B {
    @nogc nothrow pure:
    }


    struct C {
    @nogc nothrow pure:
        void foo() {
            static struct D {
            @nogc nothrow pure:
            }
        }
    }


>     struct S
>     {
>         throw ****@safe**** pure @nogc etc. etc. etc. etc. ...
>         ...
>     }

@safe already passes it's value onto a struct's scope. Yet the problem you are describing doesn't exist for it.


    @safe:

    struct S {
        void foo() {
            int* a = cast(int*)0; // error not allowed in @safe
        }
    }

That problem **does** exist now, because of the very thing you are saying prevents it. Because I can't just do `@nogc nothrow pure:` at the top of the module, I have to specify every single scope to be `@nogc nothrow pure:`. The language literally forces you to do it, unless you want to label each and every function with those attributes. I'm completely blown away, you don't even know that @safe passes through to the next scope? Or did you just add that attribute to exaggerate the problem?

The more I see this problem, and just how little Walter seems to understand of it. Being able to set defaults at the module level seems to make the most sense to me. Leave the garbage `attribute:` behavior the way it is, even if it is garbage. And add it so you can set the default based on the module.

    @safe module blah; // defaults to safe
    @system nothrow module blah2; // default is @system and nothrow

This breaks the least amount of code, and if you want to set @safe to be the default. All someone has to do to get their code to work again is add `@system` in front of the module.

    nothrow module blah;

    throw: // same awful behavior with scope

    void foo(); // "throw"

    struct A {
        void bur(); // nothrow
    }

Whatever I guess, this has just gone from one bad DIP to another to another to another since Andrei left.
January 15, 2020
On Tuesday, 14 January 2020 at 23:04:02 UTC, Adam D. Ruppe wrote:
> On Tuesday, 14 January 2020 at 22:30:40 UTC, Walter Bright wrote:
>> Hence, when "nothrow" becomes the default
>
> IF, not when. I support this DIP as a nice independent move, but I am going to fight you on the step of changing the default.
>

+1 it's a strange misguided idea in the absence of something better than exceptions.


In my best passive-aggressive way, let me quote:

"The basic answer is: Using exceptions for error handling makes your code simpler, cleaner, and less likely to miss errors."

[C++] Why use exceptions? https://isocpp.org/wiki/faq/exceptions#why-exceptions


"What do you do when an error occurs in a program? In many languages, error conditions are signaled by unusual return values like 1. Programmers often don't check for exceptional values because they may assume that errors "can't happen." On the other hand, adding error detection and recovery to what should be a straightforward flow of logic can complicate that logic to the point where the normal flow is completely obscured. An ostensibly simple task such as reading a file into memory might require about seven lines of code. Error checking and reporting expands this to 40 or more lines. Making normal operation the needle in your code haystack is undesirable."

The Java programming language - Arnold, Gosling & Holmes


-------------------->3--------------------


And we all know that, exceptions clean-up the normal path, in a way that no other alternative seeems to do. Isn't readability important?



If one can understand why safe-by-default can be a moneymaker years from now, nothrow-by-default on the contrary would imo be a very costly mistake.

I spent a lot of my life optimizing programs. If there is a way to make a program faster, people will find it eventually. Even if speed is important, safety is usually a lot more important (why get the wrong results fast?). I've come to the conclusion that "you only pay for whay you use" is really wrong, since you WILL pay anyway for the increased bugs, lessened readability etc.

Speed shouldn't be optimized for as some kind of most desirable property.
This is an "appeal-to-speed" logical fallacy, since in reality more bugs often mean less time to optimize; you might well end up slower in the end.

See_also: "fast" C++ projects that don't move fast, and get destroyed by a Java competitor.
January 15, 2020
On Wednesday, 15 January 2020 at 17:16:18 UTC, Guillaume Piolat wrote:
> On Tuesday, 14 January 2020 at 23:04:02 UTC, Adam D. Ruppe wrote:
>>[...]
>
> +1 it's a strange misguided idea in the absence of something better than exceptions.
>
> [...]

Speed is not the reason to have nothrow as default. It’s so that you are forced to be aware of functions that throw and then you either handle it or not. With the current status quo you get surprise exceptions which is less than ideal. Making nothrow as default does not remove your ability to use exceptions as error handling, it makes it more reliable.
January 15, 2020
On Wednesday, 15 January 2020 at 17:34:46 UTC, Aliak wrote:
> It’s so that you are forced to be aware of functions that throw and then you either handle it or not.

Ironically, this was one of the reasons given for exceptions being used in the first place.

And we have 25 years of history showing exceptions do a better job on reliability than the alternatives D currently offers.

It is possible that other techniques could be added to D, and then maybe we can revisit this decision after they prove themselves in practice. But as it is now, exceptions (and I'm critical of certain details of D's exceptions; strings considered harmful lol) are the best we have and discouraging them is a step backwards.