D safety! New Feature?

ag0aep6g via Digitalmars-d digitalmars-d at puremagic.com
Thu Aug 4 11:58:18 PDT 2016


On 08/04/2016 08:22 PM, Mark J Twain wrote:
> The problem is that you have fixated on the *array* and not the general
> principle. The Array was an example.

I'm having trouble understanding what you're getting at, so I'm trying 
to get it from the example you gave. If there's merit in your idea, then 
surely you can give a example where it provides benefit over the 
immutable keyword.

> Get Array out of your mind and
> think of them as general structures. It could be a queue.

Ok.

> D has no built
> in queue, then what?

You can still have an immutable queue, or a queue of immutable elements. 
Just like with arrays.

> What if it is a widget, then what? Immutable Widget
> vs Mutable Widget.
>
> Marking a widget immutable is not the same as having an ImmutableWidget.
> Can you see the difference?

No.

> I assure you there is.

Please show.

> The immutable keyword
> only prevents data manipulation, it does not change the interface.

I'm still not sure what that means. An immutable object does not have 
mutating operations in its interface. A mutable object does. So the 
interfaces are different.

> For
> simple primitives, there is not much difference, but for larger complex
> types, the immutable keyword doesn't cut it.
>
> immutable Queue!int q1;
> ImmutableQueue!int q2;
>
> q1.Enqueue(x);  // Compile time error if no tricks, but the error is
> further up the line inside Enqueue, when it actually modifies the data.

Not true. Since Enqueue isn't marked const or immutable, it can't be 
called on an immutable object. The compiler rejects the call itself. It 
doesn't reject the mutation that happens inside Enqueue, because that's 
perfectly fine in a non-const, non-immutable method.

In code:

----
struct Queue
{
     void Enqeue(int dummy) {}
}

void main()
{
     Queue m;
     m.Enqeue(1);
     immutable Queue i;
     i.Enqeue(2); /* Error: mutable method test.Queue.Enqeue is not 
callable using a immutable object */
}
----

> We can cast away immutability and end up defeating the purpose and end
> up with run-time problems.

You can break everything with casts, yes.

> q2.Enqueue(x);  // Compile time error, Enqueue doesn't exist in
> ImmutableQueue.

It doesn't exist for an immutable Queue, either.

> cannot cast away immutable.

You can still cast from ImmutableQueue to MutableQueue.

> At most we can convert q2 to
> a mutable class, which is a copy, then replace q2 with the copy.
>
> There are difference and the second case is better. The error reporting
> is more accurate and no casting can be done to bypass immutability.
>
> We
> essentially get all this stuff for free if we simply use templates to
> build the hierarchy and separate the template in to different
> parts(immutable, mutable, etc).
>
> Now, an ImmutableQueue might not be hugely useful if we have no way to
> access the data, but it could provide [] access. Again, don't get bogged
> down in the specifics, I'm talking about general application here. The
> more complex the type and hierarchy the more useful such a method is and
> the less useful immutable keyword is.
>
> The immutable keyword is a blind, it only does one thing. Building
> immutability in to the type system itself allows the programmer to make
> immutable smarter and control exactly what it does.

Sorry, but I still don't see what ImmutableWhatever does that `immutable 
Whatever` can't do. As far as I see, your example about having better 
error locations is wrong.


More information about the Digitalmars-d mailing list