November 26, 2021

On Friday, 26 November 2021 at 01:48:28 UTC, zjh wrote:

>

On Thursday, 25 November 2021 at 22:36:38 UTC, Walter Bright wrote:

>

I've suggested removing lazy already, with the predicted response.

lazy can be deleted completely. One can replace it with something similar to the concept of C++.

There's one use of lazy that can't be easily replaced, which is template functions like std.exception.ifThrown. Without lazy, we would have to rewrite code like this

auto result = doStuff(x, y, z).ifThrown(w);

...to look like this:

auto result = (() => doStuff(x, y, z)).ifThrown(w);

Personally I don't think this is a huge deal--lazy is not very commonly used in the first place, and having to write a few extra characters in the places where it is used is not a terrible imposition. But it is still a breaking change.

November 26, 2021

On Friday, 26 November 2021 at 02:05:00 UTC, zjh wrote:

>

why we don't use &?

auto ref f3(ref int x) { return x; }
//VS
auto&f3(int&x){return x;}

one inout is enough:

auto inout f3(inout int&x) inout{return x;}
//VS
auto what() return;
auto the() return scope;
auto fuck() return ref scope;
...
November 26, 2021

On Friday, 26 November 2021 at 02:17:18 UTC, zjh wrote:

Return ref replace with @,and return scope replace with %
Why not?

struct S {
    ref int opIndex() return ref scope {
    }
}
//VS
struct S {
    int&opIndex()@%{

    }
}
November 26, 2021

On Friday, 26 November 2021 at 02:08:54 UTC, Paul Backus wrote:

>
auto result = doStuff(x, y, z).ifThrown(w);

...to look like this:

auto result = (() => doStuff(x, y, z)).ifThrown(w);

single λ, It's really hard to change.
But if more than one λ, You can use the concept like. It's very convenient.
We should not encourage the use of lazy, keep it, but not encourage it.

November 26, 2021

On Thursday, 25 November 2021 at 19:35:53 UTC, Paul Backus wrote:

>

On Thursday, 25 November 2021 at 16:11:39 UTC, Dennis wrote:

>

On Thursday, 25 November 2021 at 15:57:13 UTC, WebFreak001 wrote:

>

with return ref and return scope, will there also be a return this for the case like the opIndex functions returning something with the lifetime of the containing struct? I don't quite get how it's otherwise fixing it.

return this in struct member functions is return ref. Walter proposes in the bugzilla issue to allow ref after the parameter list:

struct S {
    ref int opIndex() return ref scope {

    }
}

Seems like we may be reaching the point where it's worth it to make the this parameter explicit, like it is in Python and Rust:

struct S {
    ref int opIndex(return ref scope this) {
        // ...
    }
}

I really like this suggestion! It's a lot cleaner than having all the attributes after the function (which sometimes means the same as before the function)

Would be a lot easier to understand to people who have never seen attributes after the function before. (Like people coming from C#, Java, Python)

However it would be inconsistent to keep the other attributes after the function as well and I doubt anyone would prefer

int width(const @property this) { ... }
                // doesn't really make sense imo, would need to at least keep the @ attributes (and pure, nothrow) after the function

over

int width() const @property { ... }

What is nice that stuff like const/inout would make more sense (writing it before the function meaning the same as after the function unless there are parentheses would be no more)

Would think you could write it like this:

inout int[] getSomething(inout return this, int offset) @property { ... }
November 26, 2021

On Thursday, 25 November 2021 at 16:11:39 UTC, Dennis wrote:

>

return this in struct member functions is return ref. Walter proposes in the bugzilla issue to allow ref after the parameter list:

struct S {
    ref int opIndex() return ref scope {

    }
}

Perhaps it still makes sense to allow free return qualifier with member functions? The invisible this parameter is implicitly ref, so that repeating ref just for the return qualifier wouldn't be needed.

We might still require the return for the invisible ref this to be the last qualifier, so no ref int opIndex() return const scope or anything like that.

November 26, 2021

& vs ref is just one of the many things that C++ does better than D. And I'm not talking about the syntax: What is a "storage class"? And assuming this terms means anything, why would "ref" be one? In what world is a hidden pointer a "storage class"?

November 26, 2021

On Friday, 26 November 2021 at 09:19:45 UTC, Araq wrote:

>

& vs ref is just one of the many things that C++ does better than D. And I'm not talking about the syntax: What is a "storage class"? And assuming this terms means anything, why would "ref" be one? In what world is a hidden pointer a "storage class"?

C++ has storage classes too. auto and static, perhaps others I can't immediately recall. D adds ref, __gshared, enum and lazy on top of those. const, shared and immutable can be syntactically used as storage classes, but in reality they just alias to auto or __ghared and add a type qualifier at the same time.

November 26, 2021

On Friday, 26 November 2021 at 09:19:45 UTC, Araq wrote:

>

What is a "storage class"?

A property of a variable declaration that says something about the memory it is stored in. In C, that could be e.g. register or volatile. In D, that could be __gshared, which says a global variable is stored in the data section instead of thread local storage (default).

>

And assuming this terms means anything, why would "ref" be one?

It's a property of a parameter (which is a variable declaration) that says it's not stored in this function's frame, but somewhere higher up.

>

In what world is a hidden pointer a "storage class"?

You don't explicitly spell out the this parameter in member functions, but ref is not 'hidden'.

You are right though that making ref a storage class is a questionable decision, it adds a lot of complexity to the compiler, which has tons of split code paths (a search for isref gives me 229 hits). Same for scope, which is also questionable as a storage class: it doesn't even say anything about the variable itself, only about the variable that the pointer points to.

November 26, 2021

On Friday, 26 November 2021 at 02:03:41 UTC, Paul Backus wrote:

>

On Friday, 26 November 2021 at 00:31:19 UTC, Dennis wrote:

>

On Friday, 26 November 2021 at 00:26:35 UTC, Paul Backus wrote:

>

More seriously: this is exactly the kind of obscure "gotcha" that makes C++ so beginner-hostile, and IMO it is worth going to considerable lengths (including breaking changes) to avoid it.

Allowing breaking changes, what syntax do you think makes intuitive sense?

  • Allow return ref and return scope.
  • Forbid the return storage class from appearing in any other context.

As an occasional D(hobby) user but long-time lurker on this forum... it has been noticeable t me that D is gradually approaching C++ in complexity!

Something like this, as you hinted,...

>
struct S {
    ref int opIndex(return ref scope this) {
        // ...
    }
}

... are inevitably going to be confusing to newbies.

Personally what I think would help is to somehow 'link' those keywords together that is a single entity i.e. in your example return ref and return scope becomes return-ref and return-scope.

Or anything similar that achieves the same, like return_ref and return_scope, as long as it is clear that they are not separate keywords in this context. Or whatever makes the most sense from a lexing/parsing POV.

It will at least read easier and be easier to explain (like ref int opIndex(return-ref scope this) is allowed, but not ref int opIndex(ref-return scope this), compared to ref int opIndex(return ref scope this) is allowed, but not ref int opIndex(ref return scope this) .

I realize this in effect introduces new keywords and is equally a breaking change, but in my opinion this is preferable to the explosion in parameter attributes we are seeing.