Thread overview
Re: how to declare an immutable class?
Aug 11, 2016
Jonathan M Davis
Aug 12, 2016
Charles Hixson
Aug 12, 2016
Mike Parker
Aug 12, 2016
Charles Hixson
Aug 12, 2016
Mike Parker
Aug 12, 2016
Jonathan M Davis
Aug 12, 2016
Mike Parker
Aug 13, 2016
Charles Hixson
Aug 12, 2016
Jonathan M Davis
August 11, 2016
On Thursday, August 11, 2016 10:56:59 Charles Hixson via Digitalmars-d-learn wrote:
> I want to declare a class all instances of which will be immutable, and all references to which will be inherently immutable (so that I don't need to slip a huge number of "immutable" statements in my code).
>
> This is surely possible, because string acts just that way, but I can't figure out how to do this.
>
> immutable class    Msg  {    this(...) immutable{...} ... }
>
> doesn't work that way, as when I do
>
> Msg m = new Msg (...);
>
> I get:
>
> Error: incompatible types for ((this.m) - (m)): 'immutable(Msg)' and
> 'cellram.Msg'
>
> and
>
> Error: immutable method cellram.Msg.this is not callable using a mutable object
>
>
> Does anyone know the correct approach?

There is no such thing as an immutable class. You can have an instance of a class that's immutable, and you can make it so that all of the members of a class are immutable, but you're still going to need to use the keyword immutable with the type to indicate that it's immutable. If you do

immutable class C
{
    ...
}

that's the same as

immutable
{
    class C
    {
        ...
    }
}

It makes it so that all of the members of the class are immutable, but
if you use C in the code, it won't be immutable - only immutable C will be
immutable. Now, you could use an alias to reduce your typing. e.g.

alias IC = immutable C;

and then whenever you use IC, it will be replaced with immutable C by the compiler, but anywhere you use C rather than the alias, you're going to need to put immutable on it if you want it to be immutable. So, your code could become something like

immutable class _Msg
{
    // the immutable on the class made this immutable. There's no need
    // to mark it with immutable.
    this(...)
    {
    }

    ...
}

alias Msg = immutable _Msg;

and then when you do

auto msg = new Msg;

you'll get an immutable(_Msg).

- Jonathan M Davis

August 11, 2016
A way around this, which may be the same as the approach used by string was:

alias immutable(Msg_)    Msg;
class    Msg_
{  ...

This so far appears to do what I want.  The only problem is that it introduces an extraneous symbol, which I would prefer to avoid.

OTOH, I did fix a few problems before this solution
On 08/11/2016 10:56 AM, Charles Hixson via Digitalmars-d-learn wrote:
> I want to declare a class all instances of which will be immutable, and all references to which will be inherently immutable (so that I don't need to slip a huge number of "immutable" statements in my code).
>
> This is surely possible, because string acts just that way, but I can't figure out how to do this.
>
> immutable class    Msg  {    this(...) immutable{...} ... }
>
> doesn't work that way, as when I do
>
> Msg m = new Msg (...);
>
> I get:
>
> Error: incompatible types for ((this.m) - (m)): 'immutable(Msg)' and 'cellram.Msg'
>
> and
>
> Error: immutable method cellram.Msg.this is not callable using a mutable object
>
>
> Does anyone know the correct approach?
>
>

August 12, 2016
On Friday, 12 August 2016 at 00:44:31 UTC, Charles Hixson wrote:
> A way around this, which may be the same as the approach used by string was:
>
> alias immutable(Msg_)    Msg;
> class    Msg_
> {  ...


This is exactly what Jonathan suggested in the post above. And yes, it's how string is handled:

alias string = immutable(char)[];

>
> This so far appears to do what I want.  The only problem is that it introduces an extraneous symbol, which I would prefer to avoid.

What problem do you want to avoid? This is a common D idiom. Alias names are very short-lived. Yes, it's another symbol in the namespace, but it will never make it to the object file. It won't even make it to error messages -- you'll see Msg_ there instead.



August 11, 2016
On 08/11/2016 06:33 PM, Mike Parker via Digitalmars-d-learn wrote:
> On Friday, 12 August 2016 at 00:44:31 UTC, Charles Hixson wrote:
>> A way around this, which may be the same as the approach used by string was:
>>
>> alias immutable(Msg_)    Msg;
>> class    Msg_
>> {  ...
>
>
> This is exactly what Jonathan suggested in the post above. And yes, it's how string is handled:
>
> alias string = immutable(char)[];
>
>>
>> This so far appears to do what I want.  The only problem is that it introduces an extraneous symbol, which I would prefer to avoid.
>
> What problem do you want to avoid? This is a common D idiom. Alias names are very short-lived. Yes, it's another symbol in the namespace, but it will never make it to the object file. It won't even make it to error messages -- you'll see Msg_ there instead.
Yes, I saw his answer after I'd posted my resolution.
It works, it's just not the syntax that I'd prefer.  And it leaves me wondering exactly what
immutable class Msg {...}
was declaring.

August 12, 2016
On Friday, 12 August 2016 at 04:49:46 UTC, Charles Hixson wrote:

> It works, it's just not the syntax that I'd prefer.  And it leaves me wondering exactly what
> immutable class Msg {...}
> was declaring.

This should demonstrate:

```
immutable class iMsg {
    int getX() { return 10; }
}

class Msg {
    int getX() { return 20; }
}

void main() {
    auto msg1 = new immutable iMsg;
    assert(msg1.getX() == 10);

    auto msg2 = new immutable Msg;
    assert(msg2.getX() == 20);
}
```

The line with msg2.getX() will fail to compile, because it's calling a non-immutable method on an immutable object. Change the declaration of Msg to the following and it compiles:

```
class Msg {
    int getX() immutable { return 20; }
}
```

immutable class Foo { ... } is the same as declaring every member of Foo as immutable, just as final class Foo { ... } makes every method final.


August 12, 2016
On Friday, August 12, 2016 05:25:45 Mike Parker via Digitalmars-d-learn wrote:
> immutable class Foo { ... } is the same as declaring every member of Foo as immutable, just as final class Foo { ... } makes every method final.

I'm not sure that that's quite the same thing, because there is such a thing as a final class, because making the class final makes it illegal to derive another class from it rather than just affecting the class' functions. So, final does affect the class itself, whereas immutable does not. It's the same with most of attributes though - @safe, pure, nothrow, etc. They affect the members but not the class itself. Putting them on the class is the same as doing

attribute
{
    class C
    {
        ...
    }
}

or the same as

attribute:

class C
{
    ...
}

if there's nothing after the class in the file (since the label syntax affects everything after it in the file, whereas the braces only affect what's in the braces).

- Jonathan M Davis

August 12, 2016
On Thursday, August 11, 2016 21:49:46 Charles Hixson via Digitalmars-d-learn wrote:
> It works, it's just not the syntax that I'd prefer.  And it leaves me
> wondering exactly what
> immutable class Msg {...}
> was declaring.

All it does is make the members of the class immutable. It doesn't affect the class itself - just like you could do

@safe class Msg {...}

and that has no effect on the class itself - just its members. I guess that it's somewhat confusing given that some attributes affect the class itself (e.g. public or abstract), but most don't, and if they don't, they just affect the members of the class. But the type qualifiers - const, immutable, and shared - do not affect the class itself, just its members. Off the top of my head, I think that the only attributes that affect the actual class are public, protected, package, private, static, abstract, and final - and static doesn't even affect the class in all cases (e.g. it would have no affect at the top-level of a module).

- Jonathan M Davis

August 12, 2016
On Friday, 12 August 2016 at 08:35:54 UTC, Jonathan M Davis wrote:
> On Friday, August 12, 2016 05:25:45 Mike Parker via Digitalmars-d-learn wrote:
>> immutable class Foo { ... } is the same as declaring every member of Foo as immutable, just as final class Foo { ... } makes every method final.
>
> I'm not sure that that's quite the same thing, because there is such a thing as a final class, because making the class final makes it illegal to derive another class from it rather than just affecting the class' functions. So, final does affect the class itself, whereas immutable does not.

Yes, bad comparison, but the rest of your post makes the point I intended.
August 12, 2016
Thank you both.


On 08/12/2016 01:35 AM, Jonathan M Davis via Digitalmars-d-learn wrote:
> On Friday, August 12, 2016 05:25:45 Mike Parker via Digitalmars-d-learn wrote:
>> immutable class Foo { ... } is the same as declaring every member
>> of Foo as immutable, just as final class Foo { ... } makes every
>> method final.
> I'm not sure that that's quite the same thing, because there is such a thing
> as a final class, because making the class final makes it illegal to derive
> another class from it rather than just affecting the class' functions. So,
> final does affect the class itself, whereas immutable does not. It's the
> same with most of attributes though - @safe, pure, nothrow, etc. They affect
> the members but not the class itself. Putting them on the class is the same
> as doing
>
> attribute
> {
>      class C
>      {
>          ...
>      }
> }
>
> or the same as
>
> attribute:
>
> class C
> {
>      ...
> }
>
> if there's nothing after the class in the file (since the label syntax
> affects everything after it in the file, whereas the braces only affect
> what's in the braces).
>
> - Jonathan M Davis
>
>