"bearophile" <bearophileh...@lycos.com> schrieb im Newsbeitrag news:qqcdemwimcylaizjy...@forum.dlang.org... > Christof Schardt: > >> By "trickery" I meant having to know about things like >> "import std.exception : assumeUnique" for this basic kind of task. > > Your function has signature (you use "ref" instead of "in" or "out" > because it performs read/write): > > void rw(ref string x) > > A string is a immutable(char)[], that is a dynamic array of immutable > (UTF-8) chars. In D a dynamic array is a struct (so it's a value) that > contains a length of the string (here in multiple of char.sizeof, that are > bytes) and a pointer to the actual string data. Your function gets a > string by reference, so it's a pointer to a mutable struct that points to > immutable chars. > > The else branch suggested by John Colvin was: > >> else >> { >> size_t size; >> _f.rawRead((&size)[0..1]); >> auto tmp = new char[size]; >> _f.rawRead(tmp); >> import std.exception : assumeUnique; >> x = tmp.assumeUnique; >> } > > This allocated a GC-managed dymamic array of chars (the buffer tmp), and > loads the data into them: > > auto tmp = new char[size]; > _f.rawRead(tmp); > > Now you can't just perform: > > x = tmp; > > D manages the pointer to the dynamic array x automatically, so x can be > seen as a dynamic array array. But their type is different, x refers to > immutable(char)[] while tmp is a char[]. In general you can't implicitly > convert immutable data with indirections to mutable data with > indirections, because this breaks the assumptions immutability is based on > (while in D you can assign a char[] to a const(char)[] variable. It's the > difference between const an immutable). So the "trickery" comes from > satisfying the strong typing of D. It's the price you have to pay for > safety and (in theory) a bit of improvements in concurrent code. > > assumeUnique is essentially a better documented cast, that converts > mutable to immutable. It's similar to cast(immutable). D doesn't have > uniqueness typing so in many cases the D compiler is not able to infer the > uniqueness of data for you (and unique data can be implicitly converted to > immutable). But the situation on this is improving (this is already > partially implemented and merged, and will be present in D 2.066: > http://wiki.dlang.org/DIP29 ). > > when the function you are calling is pure (unlike rawRead) you don't need > assumeUnique: > > import std.exception: assumeUnique; > > void foo(out char[] s) pure { > foreach (immutable i, ref c; s) > c = cast(char)i; > } > > // Using assumeUnique: > void bar1(ref string s) { > auto tmp = new char[10]; > foo(tmp); > s = tmp.assumeUnique; > } > > // Using the D type system: > void bar2(ref string s) { > static string local() pure { > auto tmp = new char[10]; > foo(tmp); > return tmp; > } > s = local; > } > > void main() {} > > Bye, > bearophile
Great, thanks for this insight. Christof