Thread overview
Static array as immutable
Dec 12, 2017
Ivan Trombley
Dec 12, 2017
Radu
Dec 12, 2017
Ivan Trombley
Dec 12, 2017
Jonathan M Davis
Dec 12, 2017
Ivan Trombley
Dec 12, 2017
Jonathan M Davis
Dec 12, 2017
Nathan S.
Dec 12, 2017
Ivan Trombley
Dec 12, 2017
H. S. Teoh
December 12, 2017
Is there some way that I can make this array immutable?

  static float[256] ga = void;
  static foreach (i; 0 .. 256)
      ga[i] = (i / 255.0f) ^^ (1 / 2.2f);

December 12, 2017
On Tuesday, 12 December 2017 at 07:33:47 UTC, Ivan Trombley wrote:
> Is there some way that I can make this array immutable?
>
>   static float[256] ga = void;
>   static foreach (i; 0 .. 256)
>       ga[i] = (i / 255.0f) ^^ (1 / 2.2f);

Check
https://dlang.org/phobos/std_exception.html#assumeUnique
December 12, 2017
On Tuesday, 12 December 2017 at 07:44:55 UTC, Radu wrote:
> On Tuesday, 12 December 2017 at 07:33:47 UTC, Ivan Trombley wrote:
>> Is there some way that I can make this array immutable?
>>
>>   static float[256] ga = void;
>>   static foreach (i; 0 .. 256)
>>       ga[i] = (i / 255.0f) ^^ (1 / 2.2f);
>
> Check
> https://dlang.org/phobos/std_exception.html#assumeUnique

Thanks.
December 12, 2017
On Tuesday, December 12, 2017 07:33:47 Ivan Trombley via Digitalmars-d-learn wrote:
> Is there some way that I can make this array immutable?
>
>    static float[256] ga = void;
>    static foreach (i; 0 .. 256)
>        ga[i] = (i / 255.0f) ^^ (1 / 2.2f);

If you want anything to be immutable, you either have to initialize it directly or give it a value in a static constructor (and the static constructor solution won't work for local variables). So, you'd need to do something like

static immutable float[256] ga = someFuncThatGeneratesGA();

If the function is pure, and there's no way that the return value was passed to the function, then its return value can be assigned to something of any mutability, since the compiler knows that there are no other references to it, and it can implicitly cast it, or if the type is a value type (as in this case), then you just get a copy, and mutability isn't an issue. Alternatively to using a pure function, you can use std.exception.assumeUnique to cast to immutable, but that relies on you being sure that there are no other references to the data, and it may not work at compile-time, since casting is a lot more restrictive during CTFE. So, in general, using a pure function is preferable to assumeUnique.

- Jonathan M Davis

December 12, 2017
On Tuesday, 12 December 2017 at 09:48:09 UTC, Jonathan M Davis wrote:
> On Tuesday, December 12, 2017 07:33:47 Ivan Trombley via Digitalmars-d-learn wrote:
>> Is there some way that I can make this array immutable?
>>
>>    static float[256] ga = void;
>>    static foreach (i; 0 .. 256)
>>        ga[i] = (i / 255.0f) ^^ (1 / 2.2f);
>
> If you want anything to be immutable, you either have to initialize it directly or give it a value in a static constructor (and the static constructor solution won't work for local variables). So, you'd need to do something like
>
> static immutable float[256] ga = someFuncThatGeneratesGA();
>
> If the function is pure, and there's no way that the return value was passed to the function, then its return value can be assigned to something of any mutability, since the compiler knows that there are no other references to it, and it can implicitly cast it, or if the type is a value type (as in this case), then you just get a copy, and mutability isn't an issue. Alternatively to using a pure function, you can use std.exception.assumeUnique to cast to immutable, but that relies on you being sure that there are no other references to the data, and it may not work at compile-time, since casting is a lot more restrictive during CTFE. So, in general, using a pure function is preferable to assumeUnique.
>
> - Jonathan M Davis

Ah, it doesn't work. I get this error using the ^^ operator:

/usr/include/dmd/phobos/std/math.d(5724,27): Error: cannot convert &real to ubyte* at compile time
/usr/include/dmd/phobos/std/math.d(6629,24):        called from here: signbit(x)
/usr/include/dmd/phobos/std/math.d(6756,16):        called from here: impl(cast(real)x, cast(real)y)

:(
December 12, 2017
On Tuesday, December 12, 2017 10:35:15 Ivan Trombley via Digitalmars-d-learn wrote:
> On Tuesday, 12 December 2017 at 09:48:09 UTC, Jonathan M Davis
>
> wrote:
> > On Tuesday, December 12, 2017 07:33:47 Ivan Trombley via
> >
> > Digitalmars-d-learn wrote:
> >> Is there some way that I can make this array immutable?
> >>
> >>    static float[256] ga = void;
> >>    static foreach (i; 0 .. 256)
> >>
> >>        ga[i] = (i / 255.0f) ^^ (1 / 2.2f);
> >
> > If you want anything to be immutable, you either have to initialize it directly or give it a value in a static constructor (and the static constructor solution won't work for local variables). So, you'd need to do something like
> >
> > static immutable float[256] ga = someFuncThatGeneratesGA();
> >
> > If the function is pure, and there's no way that the return value was passed to the function, then its return value can be assigned to something of any mutability, since the compiler knows that there are no other references to it, and it can implicitly cast it, or if the type is a value type (as in this case), then you just get a copy, and mutability isn't an issue. Alternatively to using a pure function, you can use std.exception.assumeUnique to cast to immutable, but that relies on you being sure that there are no other references to the data, and it may not work at compile-time, since casting is a lot more restrictive during CTFE. So, in general, using a pure function is preferable to assumeUnique.
> >
> > - Jonathan M Davis
>
> Ah, it doesn't work. I get this error using the ^^ operator:
>
> /usr/include/dmd/phobos/std/math.d(5724,27): Error: cannot
> convert &real to ubyte* at compile time
> /usr/include/dmd/phobos/std/math.d(6629,24):        called from
> here: signbit(x)
> /usr/include/dmd/phobos/std/math.d(6756,16):        called from
> here: impl(cast(real)x, cast(real)y)
>
> :(

Well, if the code you need to initialize a variable can't be run at compile time, then that variable can't be a variable that needs to be initialized at compile time and be immutable.

- Jonathan M Davis

December 12, 2017
On Tuesday, 12 December 2017 at 11:37:40 UTC, Jonathan M Davis wrote:
> On Tuesday, December 12, 2017 10:35:15 Ivan Trombley via Digitalmars-d-learn wrote:
>> On Tuesday, 12 December 2017 at 09:48:09 UTC, Jonathan M Davis
>>
>> wrote:
>> > On Tuesday, December 12, 2017 07:33:47 Ivan Trombley via
>> >
>> > Digitalmars-d-learn wrote:
>> >> Is there some way that I can make this array immutable?
>> >>
>> >>    static float[256] ga = void;
>> >>    static foreach (i; 0 .. 256)
>> >>
>> >>        ga[i] = (i / 255.0f) ^^ (1 / 2.2f);
>> >
>> > If you want anything to be immutable, you either have to initialize it directly or give it a value in a static constructor (and the static constructor solution won't work for local variables). So, you'd need to do something like
>> >
>> > static immutable float[256] ga = someFuncThatGeneratesGA();
>> >
>> > If the function is pure, and there's no way that the return value was passed to the function, then its return value can be assigned to something of any mutability, since the compiler knows that there are no other references to it, and it can implicitly cast it, or if the type is a value type (as in this case), then you just get a copy, and mutability isn't an issue. Alternatively to using a pure function, you can use std.exception.assumeUnique to cast to immutable, but that relies on you being sure that there are no other references to the data, and it may not work at compile-time, since casting is a lot more restrictive during CTFE. So, in general, using a pure function is preferable to assumeUnique.
>> >
>> > - Jonathan M Davis
>>
>> Ah, it doesn't work. I get this error using the ^^ operator:
>>
>> /usr/include/dmd/phobos/std/math.d(5724,27): Error: cannot
>> convert &real to ubyte* at compile time
>> /usr/include/dmd/phobos/std/math.d(6629,24):        called from
>> here: signbit(x)
>> /usr/include/dmd/phobos/std/math.d(6756,16):        called from
>> here: impl(cast(real)x, cast(real)y)
>>
>> :(
>
> Well, if the code you need to initialize a variable can't be run at compile time, then that variable can't be a variable that needs to be initialized at compile time and be immutable.
>
> - Jonathan M Davis

While what you're saying is true, exponentiation not being runnable at compile-time is a defect and I would assume a regression. I'll file a bug report. FWIW when trying to run the following with DMD v2.077.1 I get:

```
void main(string[] args)
{
    import std.stdio;
    enum e = (1.0 / 255.0f) ^^ (1 / 2.2f);
    writeln("e = ", e);
}
```

=>

[...]/dmd/std/math.d(440): Error: y.vu[4] is used before initialized
[...]/dmd/std/math.d(413):        originally uninitialized here
[...]/dmd/std/math.d(4107):        called from here: floorImpl(x)
[...]/dmd/std/math.d(2373):        called from here: floor(x + 0.5L)
[...]/dmd/std/math.d(2110):        called from here: exp2Impl(x)
[...]/dmd/std/math.d(6743):        called from here: exp2(yl2x(x, y))
[...]/dmd/std/math.d(6756):        called from here: impl(cast(real)x, cast(real)y)
December 12, 2017
On Tuesday, 12 December 2017 at 15:30:01 UTC, Nathan S. wrote:
> While what you're saying is true, exponentiation not being runnable at compile-time is a defect and I would assume a regression. I'll file a bug report. FWIW when trying to run the following with DMD v2.077.1 I get:
>
> ```
> void main(string[] args)
> {
>     import std.stdio;
>     enum e = (1.0 / 255.0f) ^^ (1 / 2.2f);
>     writeln("e = ", e);
> }
> ```
>
> =>
>
> [...]/dmd/std/math.d(440): Error: y.vu[4] is used before initialized
> [...]/dmd/std/math.d(413):        originally uninitialized here
> [...]/dmd/std/math.d(4107):        called from here: floorImpl(x)
> [...]/dmd/std/math.d(2373):        called from here: floor(x + 0.5L)
> [...]/dmd/std/math.d(2110):        called from here: exp2Impl(x)
> [...]/dmd/std/math.d(6743):        called from here: exp2(yl2x(x, y))
> [...]/dmd/std/math.d(6756):        called from here: impl(cast(real)x, cast(real)y)

FWIW, if the exponent is an integer, I don't get an error.
December 12, 2017
On Tue, Dec 12, 2017 at 06:06:48PM +0000, Ivan Trombley via Digitalmars-d-learn wrote:
> On Tuesday, 12 December 2017 at 15:30:01 UTC, Nathan S. wrote:
> > While what you're saying is true, exponentiation not being runnable at compile-time is a defect and I would assume a regression.
[...]
> FWIW, if the exponent is an integer, I don't get an error.

I don't think exponentiation with non-integer exponents have ever been supported at compile-time. It requires evaluating exp(x) for non-integer x, which, AFAIK, has never been supported at compile-time because the implementation of exp(x) requires constructs that the current CTFE engine doesn't support, namely, inline asm in older versions of std.math, or more recently, the need to access the binary representation of floats/doubles.

Perhaps when Stefan Koch's new CTFE engine is ready for public consumption, we will be able to finally have std.math runnable in CTFE.


T

-- 
Latin's a dead language, as dead as can be; it killed off all the Romans, and now it's killing me! -- Schoolboy