Re: Run-time setting of immutable variable?

2021-09-03 Thread DLearner via Digitalmars-d-learn
On Thursday, 2 September 2021 at 23:12:28 UTC, Steven 
Schveighoffer wrote:



[...]
immutable means "I can never change and *everything I point at* 
can never change".

[...]

If that is how the language defines the keyword 'immutable' when 
used in the definition of a pointer variable, then so be it.


I would, however, suggest that the additional 
'action-at-a-distance' implication (freezing not just the 
variable itself, but also it's target) is inconsistent with the 
definition of 'immutable' with other variable types.


Surely it would be better to reserve 'immutable' on a pointer to 
mean simply set-once on the pointer itself (with no implications 
for whatever the pointer is pointing to), and another keyword 
('blocked'?) for the current definition?





Re: Run-time setting of immutable variable?

2021-09-02 Thread Ali Çehreli via Digitalmars-d-learn

On 9/2/21 9:01 AM, DLearner wrote:
Suppose there is a variable that is set once per run, and is (supposed) 
never to be altered again.


An accessor function can be a solution, which supports your other 
comment about data potentially mutating by other means:


// Assume these are in a module
// 

// This is private; you can even name it arr_.
private
ubyte[10] arr;

// This is the accessor:
public
const(ubyte)* arrPtr() {
  return arr.ptr;
}
// 

void main() {
  *arrPtr = 42;  // Compilation ERROR; good.
}

Ali


Re: Run-time setting of immutable variable?

2021-09-02 Thread Steven Schveighoffer via Digitalmars-d-learn

On 9/2/21 1:17 PM, DLearner wrote:


I am looking for a mutable Arr but would like an immutable ArrPtr.


Then you want const not immutable.

Here is the reason:

```d
void main()
{
int x = 5;
immutable int *ptr = cast(immutable int *)
assert(*ptr == 5); // ok
x = 6;
assert(*ptr == 5); // what happens here?
}
```

Depending on optimizations and compiler constant folding, that second 
assert may pass.


immutable means "I can never change and *everything I point at* can 
never change". The compiler is free to use this knowledge to avoid 
redoing calculations it has already done. I tknows that `*ptr == 5` 
already, and that can never change, so it just doesn't even bother with 
the second assert.


However, make ptr *const*, and now not only do you not need the cast, 
but the second assert will fail as expected.



```
`Arr` is not immutable, so `ArrPtr` shouldn't point at it if it's 
immutable.

```
Surely there is no inconsistency - at run time the array is in a fixed 
place,  so ArrPtr is (or at least should be) a constant, but the 
contents of the array

can vary as the program runs.


In D, const and immutable are transitive, which means that you can't 
have a pointer that is const, but allows changing what it points at. So 
while a const pointer *may* work for your purposes, you may want a 
specialized type, or a property function. It depends on how you intend 
to use `ArrPtr`. Others have given good answers to this problem.


-Steve


Re: Run-time setting of immutable variable?

2021-09-02 Thread H. S. Teoh via Digitalmars-d-learn
On Thu, Sep 02, 2021 at 05:17:15PM +, DLearner via Digitalmars-d-learn 
wrote:
[...]
> The following clean-compiled and produced the expected result:
> ```
> ubyte[10] Arr;
> 
> immutable void* ArrPtr;
>   shared static this() {
>   ArrPtr = cast(immutable void*)([0]);
>   }

Casting this to immutable is unsafe, because Arr is actually mutable. In
D, const and immutable are transitive, so when you cast a pointer into
immutable, you're basically promising that *both* the pointer *and* the
data pointed to will never change. The compiler is free to assume that
the data pointed to will never change, which may cause consistency
problems if the data *does* change later.

In cases like this, const is a better choice: const ensures that the
pointer will not mutate and the pointed-to data cannot be mutated
through this pointer, but the data *may* be mutated through another
reference (e.g., by modifying Arr directly).


[...]
> I am looking for a mutable Arr but would like an immutable ArrPtr.

In D, const and immutable are transitive, so you cannot do this (but see
below).


> ```
> `Arr` is not immutable, so `ArrPtr` shouldn't point at it if it's
> immutable.
> ```
> Surely there is no inconsistency - at run time the array is in a fixed
> place,  so ArrPtr is (or at least should be) a constant, but the
> contents of the array can vary as the program runs.

In this case, what you want is const, not immutable.  Const means you
cannot modify the pointer, and you cannot mutate the data through this
pointer, but you *can* modify the array from a mutable reference.


T

-- 
You are only young once, but you can stay immature indefinitely. -- azephrahel


Re: Run-time setting of immutable variable?

2021-09-02 Thread jfondren via Digitalmars-d-learn

On Thursday, 2 September 2021 at 17:17:15 UTC, DLearner wrote:
Surely there is no inconsistency - at run time the array is in 
a fixed place,  so ArrPtr is (or at least should be) a 
constant, but the contents of the array

can vary as the program runs.


In the case of `immutable(T)* ArrPtr`, the contents of the 
pointed-to array cannot vary as the program runs. If it's 
immutable, nothing in the program ever mutates it. In the case of 
`const(T)* ArrPtr`, the contents of the pointed-to array can vary 
as the program runs, and the only restriction is that the array 
can't be mutated through ArrPtr.


If what you mean is that you want the *pointer* to never change, 
`T * const ArrPtr` in C syntax, but that you don't care if the 
pointed-to array changes via ArrPtr or any other reference, then 
I don't think D can express this. You could make ArrPtr a 
function:


```d
void main() {
int[] xs = [1, 2, 3, 4];
int* p() { return [2]; }
p[0] = 0;
assert(xs == [1, 2, 0, 4]);
p++; // Error: ... not an lvalue and cannot be modified
}
```


Re: Run-time setting of immutable variable?

2021-09-02 Thread Kagamin via Digitalmars-d-learn

If you want only address, you can keep it as size_t:

ubyte[10] Arr;
immutable size_t Address;
static this() {
Address = cast(size_t)([0]);
}


Re: Run-time setting of immutable variable?

2021-09-02 Thread DLearner via Digitalmars-d-learn
On Thursday, 2 September 2021 at 16:46:46 UTC, Steven 
Schveighoffer wrote:

On 9/2/21 12:01 PM, DLearner wrote:
Suppose there is a variable that is set once per run, and is 
(supposed) never to be altered again.  However, the value to 
which it is set is not known at compile time.

Example below, variable is 'ArrPtr';
```
ubyte[10] Arr;

// immutable void* ArrPtr;
void* ArrPtr;

void main() {

    ArrPtr = cast(void*)Arr[0];

// modify ArrPtr>


}
```
Is there a way of getting D to guarantee that ArrPtr is never 
modified after

```
    ArrPtr = cast(void*)Arr[0];
```]


You shouldn't be doing this. `Arr` is not immutable, so 
`ArrPtr` shouldn't point at it if it's immutable.


If you want to guarantee that `ArrPtr` never changes once set, 
yet still want it to point at mutable data, you need to use a 
type that does that (like a head mutable or "write once" type), 
which I believe doesn't exist in phobos.


If you don't actually need to mutate the data via `ArrPtr`, you 
can make it const, and use H.S. Teoh's solution. But you should 
not use immutable, as the compiler implies that data pointed at 
is also immutable (and of course, you won't need casting). Make 
sure you use regular `static this`, not `shared static this`, 
as your fields are thread-local, not shared.


-Steve


The following clean-compiled and produced the expected result:
```
ubyte[10] Arr;

immutable void* ArrPtr;
shared static this() {
ArrPtr = cast(immutable void*)([0]);
}

void main() {

  import std.stdio;
  void* ArrPtr2;

  ArrPtr2 = cast(void*)([0]);

  writeln("ArrPtr = ", ArrPtr);
  writeln("ArrPtr2 = ", ArrPtr2);  // consistency test

//  ArrPtr = ArrPtr + 1;  // mutability test - compile 
(correctly) failed when uncommented.

  ArrPtr2 = ArrPtr2 + 1;

  Arr[1] = 4;
  Arr[1] = 7;  // mutability test   
}
```

The following produced deprecated warnings, but still seemed to 
work:

```
ubyte[10] Arr;

immutable void* ArrPtr;
static this() {
ArrPtr = cast(immutable void*)([0]);
}

void main() {

  import std.stdio;
  void* ArrPtr2;

  ArrPtr2 = cast(void*)([0]);

  writeln("ArrPtr = ", ArrPtr);
  writeln("ArrPtr2 = ", ArrPtr2);  // consistency test

//  ArrPtr = ArrPtr + 1;  // mutability test on ArrPtr - 
compile (correctly) failed when uncommented.

  ArrPtr2 = ArrPtr2 + 1;

  Arr[1] = 4;
  Arr[1] = 7;  // mutability test on Arr
}
```
I am looking for a mutable Arr but would like an immutable ArrPtr.

```
`Arr` is not immutable, so `ArrPtr` shouldn't point at it if it's 
immutable.

```
Surely there is no inconsistency - at run time the array is in a 
fixed place,  so ArrPtr is (or at least should be) a constant, 
but the contents of the array

can vary as the program runs.


Re: Run-time setting of immutable variable?

2021-09-02 Thread Steven Schveighoffer via Digitalmars-d-learn

On 9/2/21 12:01 PM, DLearner wrote:
Suppose there is a variable that is set once per run, and is (supposed) 
never to be altered again.  However, the value to which it is set is not 
known at compile time.

Example below, variable is 'ArrPtr';
```
ubyte[10] Arr;

// immutable void* ArrPtr;
void* ArrPtr;

void main() {

    ArrPtr = cast(void*)Arr[0];

// 

}
```
Is there a way of getting D to guarantee that ArrPtr is never modified 
after

```
    ArrPtr = cast(void*)Arr[0];
```]


You shouldn't be doing this. `Arr` is not immutable, so `ArrPtr` 
shouldn't point at it if it's immutable.


If you want to guarantee that `ArrPtr` never changes once set, yet still 
want it to point at mutable data, you need to use a type that does that 
(like a head mutable or "write once" type), which I believe doesn't 
exist in phobos.


If you don't actually need to mutate the data via `ArrPtr`, you can make 
it const, and use H.S. Teoh's solution. But you should not use 
immutable, as the compiler implies that data pointed at is also 
immutable (and of course, you won't need casting). Make sure you use 
regular `static this`, not `shared static this`, as your fields are 
thread-local, not shared.


-Steve


Re: Run-time setting of immutable variable?

2021-09-02 Thread H. S. Teoh via Digitalmars-d-learn
On Thu, Sep 02, 2021 at 04:01:19PM +, DLearner via Digitalmars-d-learn 
wrote:
> Suppose there is a variable that is set once per run, and is
> (supposed) never to be altered again.  However, the value to which it
> is set is not known at compile time.

This is the classic use case of `immutable`.  Using the example you
gave, you'd move the initialization of ArrPtr into a static module
constructor:

immutable void* ArrPtr;
shared static this() {
ArrPtr = ...; // initialize it here
}

void main() {
... // ArrPtr is immutable from here on.
}


T

-- 
Дерево держится корнями, а человек - друзьями.


Run-time setting of immutable variable?

2021-09-02 Thread DLearner via Digitalmars-d-learn
Suppose there is a variable that is set once per run, and is 
(supposed) never to be altered again.  However, the value to 
which it is set is not known at compile time.

Example below, variable is 'ArrPtr';
```
ubyte[10] Arr;

// immutable void* ArrPtr;
void* ArrPtr;

void main() {

   ArrPtr = cast(void*)Arr[0];

// ArrPtr>


}
```
Is there a way of getting D to guarantee that ArrPtr is never 
modified after

```
   ArrPtr = cast(void*)Arr[0];
```

Best regards