Thread overview
Constants?
Feb 11, 2009
Mike L.
Feb 11, 2009
Zarathustra
Feb 13, 2009
Mike L.
February 11, 2009
Could someone lay out for me the different ways of doing constants in D (d1, particularly)? I've heard things about const, final, invariant, and "anonymous enums"?
February 11, 2009
On Wed, Feb 11, 2009 at 4:09 PM, Mike L. <mike.linford@gmail.com> wrote:
> Could someone lay out for me the different ways of doing constants in D (d1, particularly)? I've heard things about const, final, invariant, and "anonymous enums"?
>

OK, D1 doesn't have constness in the way that C/C++ and D2 do.  D1 only has constants and enums.

A constant is created with 'const':

const int x = 5;
const message = "hello"; // uses type inference to infer char[5]

'const' actually has different behavior depending on where it's used. It's always used to declare variables (you can't put it on params, for instance), but if you use 'const' as a class member:

class A
{
    const int x;

    this(int x)
    {
        this.x = x; // OK
        // this.x++; // NOT ok
    }
}

it works like the Java "final", in which case there is a copy of it in each instance of A, but it can only be assigned once and it must be assigned in the constructor.

If you want to dynamically initialize a module-level const, you can do
so in a static this():

const int x;

static this()
{
    x = something();
}

Again, x can only be assigned to once, and it must be assigned in the
static this().

'final' does not work the way it does in Java.  'final' was used to mean more or less the same thing as in Java when D2 was new, but that usage has been dropped.

'const' (and the other qualifier 'invariant') mean different things in D2; I won't get into that here unless you really want to know.

The other kind of constant that D1 has is enumerations.  Enumerations can be named:

enum Foo { Bar = 3 }

So Foo.Bar is a constant with the value 3.  Or they can be anonymous:

enum { Baz = 5 }

Baz is a constant with the value 5.

Enumerations differ from consts in that they do not consume any space in the final outputted object/library/executable, whereas consts do. This has actually been significant in some cases: the Windows header ports, for instance, used the "const int Blah = ..." form for many many constants, bloating the outputted object files by several dozens of kilobytes.  The "enum: int { Blah = ... }" form consumes no extra space in the executable.

Also: in D2, "enum" can be used as a storage class, like "const" or "invariant", in which case the idea of "not taking any space in the output" is preserved:

invariant int x = 5; // constant, but in the object files enum int y = 5; // not in the object files
February 11, 2009
For more documentation:
d1:
  const:
    <http://www.digitalmars.com/d/1.0/attribute.html#const>

  final:
    <http://www.digitalmars.com/d/1.0/class.html#Final>

  invariant:
    <http://www.digitalmars.com/d/1.0/class.html#Invariant>

  enums:
    <http://www.digitalmars.com/d/1.0/enum.html>

d2:
  const and invariant
    <http://www.digitalmars.com/d/2.0/const3.html>

  final:
    <http://www.digitalmars.com/d/2.0/class.html>

  enums:
    <http://www.digitalmars.com/d/2.0/enum.html>

Jarrett Billingsley Wrote:

> On Wed, Feb 11, 2009 at 4:09 PM, Mike L. <mike.linford@gmail.com> wrote:
> > Could someone lay out for me the different ways of doing constants in D (d1, particularly)? I've heard things about const, final, invariant, and "anonymous enums"?
> >
> 
> OK, D1 doesn't have constness in the way that C/C++ and D2 do.  D1 only has constants and enums.
> 
> A constant is created with 'const':
> 
> const int x = 5;
> const message = "hello"; // uses type inference to infer char[5]
> 
> 'const' actually has different behavior depending on where it's used. It's always used to declare variables (you can't put it on params, for instance), but if you use 'const' as a class member:
> 
> class A
> {
>     const int x;
> 
>     this(int x)
>     {
>         this.x = x; // OK
>         // this.x++; // NOT ok
>     }
> }
> 
> it works like the Java "final", in which case there is a copy of it in each instance of A, but it can only be assigned once and it must be assigned in the constructor.
> 
> If you want to dynamically initialize a module-level const, you can do
> so in a static this():
> 
> const int x;
> 
> static this()
> {
>     x = something();
> }
> 
> Again, x can only be assigned to once, and it must be assigned in the
> static this().
> 
> 'final' does not work the way it does in Java.  'final' was used to mean more or less the same thing as in Java when D2 was new, but that usage has been dropped.
> 
> 'const' (and the other qualifier 'invariant') mean different things in D2; I won't get into that here unless you really want to know.
> 
> The other kind of constant that D1 has is enumerations.  Enumerations can be named:
> 
> enum Foo { Bar = 3 }
> 
> So Foo.Bar is a constant with the value 3.  Or they can be anonymous:
> 
> enum { Baz = 5 }
> 
> Baz is a constant with the value 5.
> 
> Enumerations differ from consts in that they do not consume any space in the final outputted object/library/executable, whereas consts do. This has actually been significant in some cases: the Windows header ports, for instance, used the "const int Blah = ..." form for many many constants, bloating the outputted object files by several dozens of kilobytes.  The "enum: int { Blah = ... }" form consumes no extra space in the executable.
> 
> Also: in D2, "enum" can be used as a storage class, like "const" or "invariant", in which case the idea of "not taking any space in the output" is preserved:
> 
> invariant int x = 5; // constant, but in the object files enum int y = 5; // not in the object files

February 13, 2009
Thanks, glad to have it all in one place.