www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.learn - Casting non-aliased mutable arrays to immutable in return values

reply Per =?UTF-8?B?Tm9yZGzDtnc=?= <per.nordlow gmail.com> writes:
Is it recommended to cast an unaliased array to `immutable` after 
it has been initialized?

The reason for asking is that I would like the following function

void[] rawReadNullTerminated(string path)
      safe
{
     import std.stdio : File;
     auto file = File(path, `rb`);

     import std.array : uninitializedArray;
     ubyte[] data = uninitializedArray!(ubyte[])(file.size + 1);
     file.rawRead(data);
     data[file.size] = 0;     // null terminator for sentinel

     return data;                // TODO can we cast this to 
`immutable(void)[]`?
}

to have an immutable return type.

I'm aware of that I need to verify the contexts as UTF-8 if I 
want to treat it as text.
Aug 29 2017
next sibling parent =?UTF-8?Q?Ali_=c3=87ehreli?= <acehreli yahoo.com> writes:
On 08/29/2017 09:09 AM, Per Nordlöw wrote:
 Is it recommended to cast an unaliased array to `immutable` after it has
 been initialized?

 The reason for asking is that I would like the following function

 void[] rawReadNullTerminated(string path)
      safe
 {
     import std.stdio : File;
     auto file = File(path, `rb`);

     import std.array : uninitializedArray;
     ubyte[] data = uninitializedArray!(ubyte[])(file.size + 1);
     file.rawRead(data);
     data[file.size] = 0;     // null terminator for sentinel

     return data;                // TODO can we cast this to
 `immutable(void)[]`?
 }

 to have an immutable return type.

 I'm aware of that I need to verify the contexts as UTF-8 if I want to
 treat it as text.
Yes and assumeUnique does exactly that: https://dlang.org/library/std/exception/assume_unique.html Further, if your function is pure, the cast is implicit for the caller: void[] foo() pure { return new void[](10); } void main() { void[] a = foo(); immutable(void)[] b = foo(); // works } Ali
Aug 29 2017
prev sibling parent reply Jonathan M Davis via Digitalmars-d-learn writes:
On Tuesday, August 29, 2017 16:09:17 Per Nordlöw via Digitalmars-d-learn 
wrote:
 Is it recommended to cast an unaliased array to `immutable` after
 it has been initialized?

 The reason for asking is that I would like the following function

 void[] rawReadNullTerminated(string path)
       safe
 {
      import std.stdio : File;
      auto file = File(path, `rb`);

      import std.array : uninitializedArray;
      ubyte[] data = uninitializedArray!(ubyte[])(file.size + 1);
      file.rawRead(data);
      data[file.size] = 0;     // null terminator for sentinel

      return data;                // TODO can we cast this to
 `immutable(void)[]`?
 }

 to have an immutable return type.

 I'm aware of that I need to verify the contexts as UTF-8 if I
 want to treat it as text.
It's perfectly legitimate to construct an object as mutable and then cast it to immutable if there are no other mutable references to it - that's what std.exception.assumeUnique is for. It does the cast for you while documenting your intent. However, the better solution if you can do it is to create the object in a pure function that returns it. Then, it can be implicitly converted to immutable so long as the compiler can guarantee that the return value was not passed to the function. In this particular case, you'd probably create a pure, nested function that took the File object and returned the array. Now, as for immutable(void)[], that seems pretty weird to me. Normally, when folks use void[], it doesn't have any qualifiers on it. But I don't know that there's actually a problem using qualifiers on it. Certainly, it compiles. I'd probably just use immutable(ubyte)[] and not anything with void, but this is obviously just a snippet of your code, and I have no idea what the rest of it is doing, so something with void instead of ubyte may very well be the correct solution. You'll obviously have to be the judge of that. But pretty much the only time that I'd use any kind of void array though is when accepting arbitrary arrays of data that is going to be converted to bytes (e.g. for a socket). I wouldn't pass it around. I don't know what other folks would do though. Regardless, using assumeUnique or using a pure function to construct the object and implicitly convert it to immutable works for types in general. - Jonathan M Davis
Aug 29 2017
parent =?UTF-8?B?Tm9yZGzDtnc=?= <per.nordlow gmail.com> writes:
On Tuesday, 29 August 2017 at 16:41:48 UTC, Jonathan M Davis 
wrote:
 Regardless, using assumeUnique or using a pure function to 
 construct the object and implicitly convert it to immutable 
 works for types in general.

 - Jonathan M Davis
I'm, as always, grateful for your thorough answers, Jonathan. Thank you.
Aug 29 2017