January 31, 2023

On Monday, 30 January 2023 at 20:15:48 UTC, Dukc wrote:

>

I don't see a need for fields to be non-referenceable since immutability protects them if the data in question is already committed.

Yes, again, the idea is that rvalue allows overwriting mutable variables of this type.

rvalue struct S {
  int a;
}

S s;
s = S(5);
s = S(6);

Which immutable does not allow.

And this is important because this idiom is inescapable, it will always crop up (all over std.algorithm causing compile errors for our immutable structs, cough), and in fact I increasingly think it's just good. It's an inherent part of D's C heritage.

January 31, 2023

On Tuesday, 31 January 2023 at 07:31:58 UTC, FeepingCreature wrote:

>

And this is important because this idiom is inescapable, it will always crop up (all over std.algorithm causing compile errors for our immutable structs, cough), and in fact I increasingly think it's just good. It's an inherent part of D's C heritage.

Just to give an example, maxElement is actually straight up impossible to implement for every type without either of:

  • rvalue struct replacing immutable struct`
  • const range API (typeof(this) next() rather than void popFront())
  • rebindable structs in Phobos (librebindable)
  • mandatory tail recursion at every optimization level.

None of which D has.

January 31, 2023

On Tuesday, 31 January 2023 at 07:31:58 UTC, FeepingCreature wrote:

>

On Monday, 30 January 2023 at 20:15:48 UTC, Dukc wrote:

>

I don't see a need for fields to be non-referenceable since immutability protects them if the data in question is already committed.

Yes, again, the idea is that rvalue allows overwriting mutable variables of this type.

In that case I'd probably go with a mutable pointer to an immutable struct. That way you can replace the value in whole, but not single fields of it.

January 31, 2023

On Tuesday, 31 January 2023 at 11:52:33 UTC, Dukc wrote:

>

On Tuesday, 31 January 2023 at 07:31:58 UTC, FeepingCreature wrote:

>

On Monday, 30 January 2023 at 20:15:48 UTC, Dukc wrote:

>

I don't see a need for fields to be non-referenceable since immutability protects them if the data in question is already committed.

Yes, again, the idea is that rvalue allows overwriting mutable variables of this type.

In that case I'd probably go with a mutable pointer to an immutable struct. That way you can replace the value in whole, but not single fields of it.

Okay, now how do you do that without causing GC load? :) Keep in mind that we plan to use this for very inner loops of not-always-cheap algorithms.

January 31, 2023
On Tue, Jan 31, 2023 at 01:02:57PM +0000, FeepingCreature via Digitalmars-d wrote:
> On Tuesday, 31 January 2023 at 11:52:33 UTC, Dukc wrote:
> > On Tuesday, 31 January 2023 at 07:31:58 UTC, FeepingCreature wrote:
> > > On Monday, 30 January 2023 at 20:15:48 UTC, Dukc wrote:
> > > > I don't see a need for fields to be non-referenceable since immutability protects them if the data in question is already committed.
> > > 
> > > Yes, again, the idea is that rvalue allows *overwriting mutable variables* of this type.
> > 
> > In that case I'd probably go with a mutable pointer to an immutable struct. That way you can replace the value in whole, but not single fields of it.
> 
> Okay, now how do you do that without causing GC load? :) Keep in mind that we plan to use this for very inner loops of not-always-cheap algorithms.

Why would a mutable pointer to an immutable struct cause GC load? Isn't it just a matter of taking an address?

	struct S { ... }
	S s, t;
	immutable(S)* ptr = &s;
	...
	ptr = &t;
	... // etc


T

-- 
Truth, Sir, is a cow which will give [skeptics] no more milk, and so they are gone to milk the bull. -- Sam. Johnson
January 31, 2023

On Tuesday, 31 January 2023 at 13:02:57 UTC, FeepingCreature wrote:

>

Okay, now how do you do that without causing GC load? :) Keep in mind that we plan to use this for very inner loops of not-always-cheap algorithms.

Why can't you use regular encapsulation?

I think it would be better for you to see if you can do this is as a rewrite instead as that doesn't affect the type system.

E.g. C# introduced "record" in addition to "struct" and "class" to get slightly different value semantics, but as far as I can tell it is only a rewrite.

January 31, 2023

On Tuesday, 31 January 2023 at 18:13:58 UTC, Ola Fosheim Grøstad wrote:

>

E.g. C# introduced "record" in addition to "struct" and "class" to get slightly different value semantics, but as far as I can tell it is only a rewrite.

Or maybe it isn't (shrug). Anyway, you might want to look at the C# "with" statement:

https://learn.microsoft.com/en-us/dotnet/csharp/whats-new/tutorials/records#non-destructive-mutation

February 01, 2023

On Tuesday, 31 January 2023 at 18:13:58 UTC, Ola Fosheim Grøstad wrote:

>

On Tuesday, 31 January 2023 at 13:02:57 UTC, FeepingCreature wrote:

>

Okay, now how do you do that without causing GC load? :) Keep in mind that we plan to use this for very inner loops of not-always-cheap algorithms.

Why can't you use regular encapsulation?

I think it would be better for you to see if you can do this is as a rewrite instead as that doesn't affect the type system.

E.g. C# introduced "record" in addition to "struct" and "class" to get slightly different value semantics, but as far as I can tell it is only a rewrite.

Maybe it can be done as a rewrite?

For instance, we used to do

struct S
{
    private int a_;

    public int a() { return this.a_; }
}

But this is not quite the semantic we actually want because, for instance, the accessors will still run the invariants, which is pointless because we know the fields won't ever change after the constructor call, and also the function call itself is just useless. But that's the interface we want, at least.

The thing we actually want is, roughly,

struct S
{
    private int a_;

    public rvalue alias a = this.a_;
}

But then we're inventing features again.

That said, even "a function that returns 'a'" isn't quite the right semantics, because this is valid D:

struct S { int a; }
S foo() { ... }
foo.a = 5;

On that topic, what the fuck, D.

February 01, 2023

On Wednesday, 25 January 2023 at 16:23:51 UTC, FeepingCreature wrote:

>

Please, stop adding new features.

February 01, 2023

On Tuesday, 31 January 2023 at 18:30:44 UTC, Ola Fosheim Grøstad wrote:

>

On Tuesday, 31 January 2023 at 18:13:58 UTC, Ola Fosheim Grøstad wrote:

>

E.g. C# introduced "record" in addition to "struct" and "class" to get slightly different value semantics, but as far as I can tell it is only a rewrite.

Or maybe it isn't (shrug). Anyway, you might want to look at the C# "with" statement:

https://learn.microsoft.com/en-us/dotnet/csharp/whats-new/tutorials/records#non-destructive-mutation

Yes, that's exactly what we want!

What we use right now for with is

immutable struct S { int value; mixin(GenerateThis); }
S s = S(5);
S butFour = s.rebuild!(a => a.value = 4);

Which seems to work fine.