digitalmars.D - Const-correctness and uniqueness. Again.
- Dicebot (27/27) Feb 09 2015 Doing a lot of porting from D1 to D2 recently I have realized
- Jakob Ovrum (14/24) Feb 09 2015 The following works as well:
- Jakob Ovrum (2/5) Feb 09 2015 Err, implicitly convertible to *mutable*. It goes both ways.
- "Marc =?UTF-8?B?U2Now7x0eiI=?= <schuetzm gmx.net> (4/9) Feb 09 2015 It does? Not according to my tests. And it would be bad if it
- Tobias Pankrath (24/34) Feb 09 2015 join returns a mutable array, that can be implicitly casted to
- "Marc =?UTF-8?B?U2Now7x0eiI=?= <schuetzm gmx.net> (3/17) Feb 09 2015 I'm talking about the general case. Jacob seems to be saying that
- Kenji Hara via Digitalmars-d (7/20) Feb 09 2015 In general, pure function can access immutable global data, and can retu...
- Jakob Ovrum (3/8) Feb 09 2015 Sorry, this is indeed nonsense, I take it back. It only goes one
- Dicebot (2/5) Feb 09 2015 Ahha, I have missed that part. Thanks!
- deadalnix (3/30) Feb 09 2015 Someone is starting to see where I'm getting at when I'm pushing
Doing a lot of porting from D1 to D2 recently I have realized that we still don't have any idiomatic way to express function result types that can be both mutable and immutable. Consider this trivial snippet: ```D import std.array : join; void main() { auto s = join([ "aaa", "bbb", "ccc" ]); pragma(msg, typeof(s)); } ``` It outputs "string" which stands for immutable buffer. However, actual allocated buffer is not yet truly immutable - it has just been allocated to hold the result of join algorithm and may be interpreted both as mutable and immutable, depending on caller desire. In this specific case if caller wanted to get a mutable buffer instead, it would need to do cast from immutable which is very dangerous - especially considering implementation of `join` may change. And doing .dup on buffer that has just been allocated is quite a waste. Right now I am leaning towards personal convention to always return mutable or const buffers and do assumeUnique at caller side where necessary. But this does, of course, suck. What is current conventional wisdom on topic? Can we probably start using std.typecons.Unique for such functions?
Feb 09 2015
On Monday, 9 February 2015 at 10:56:31 UTC, Dicebot wrote:Consider this trivial snippet: ```D import std.array : join; void main() { auto s = join([ "aaa", "bbb", "ccc" ]); pragma(msg, typeof(s)); } ``` It outputs "string" which stands for immutable buffer.The following works as well: --- void main() { import std.array : join; import std.stdio : writeln; char[] s = join(["foo", "bar"]); writeln(s); //foobar } --- std.array.join is strongly pure (with appropriate template arguments), so its return value is implicitly convertible to immutable.
Feb 09 2015
On Monday, 9 February 2015 at 11:37:23 UTC, Jakob Ovrum wrote:std.array.join is strongly pure (with appropriate template arguments), so its return value is implicitly convertible to immutable.Err, implicitly convertible to *mutable*. It goes both ways.
Feb 09 2015
On Monday, 9 February 2015 at 11:38:23 UTC, Jakob Ovrum wrote:On Monday, 9 February 2015 at 11:37:23 UTC, Jakob Ovrum wrote:It does? Not according to my tests. And it would be bad if it did, because the returned immutable value could actually reside in read-only memory.std.array.join is strongly pure (with appropriate template arguments), so its return value is implicitly convertible to immutable.Err, implicitly convertible to *mutable*. It goes both ways.
Feb 09 2015
On Monday, 9 February 2015 at 12:39:06 UTC, Marc Schütz wrote:On Monday, 9 February 2015 at 11:38:23 UTC, Jakob Ovrum wrote:join returns a mutable array, that can be implicitly casted to immutable if join is pure. BTW, that was hard to figure out, because ElementEncodingType!(ElementType!RoR)[] join(RoR, R)(RoR ror, R sep) if (isInputRange!RoR && isInputRange!(Unqual!(ElementType!RoR)) && isInputRange!R && is(Unqual!(ElementType!(ElementType!RoR)) == Unqual!(ElementType!R))); ElementEncodingType!(ElementType!RoR)[] join(RoR)(RoR ror) if (isInputRange!RoR && isInputRange!(Unqual!(ElementType!RoR))); and ElementEncodingType is not linked. That would read so much better as let alias C = ElementEncodingType!(ElementType!RoR) alias ERT = Unqual!(ElementType!RoR) alias ET = ElementType!ERT in C[] join(RoR, R)(RoR ror, R sep) if( isInputRange!(RoR) && isInputRange!ERT && isInputRange!R && is(ET == ElementType!R)) C[] join(RoR)(RoR ror) if( isInputRange!RoR) && isInputRange!ERT ) Do our planned ddo[c|x] enhancement make this possible?On Monday, 9 February 2015 at 11:37:23 UTC, Jakob Ovrum wrote:It does? Not according to my tests. And it would be bad if it did, because the returned immutable value could actually reside in read-only memory.std.array.join is strongly pure (with appropriate template arguments), so its return value is implicitly convertible to immutable.Err, implicitly convertible to *mutable*. It goes both ways.
Feb 09 2015
On Monday, 9 February 2015 at 13:19:24 UTC, Tobias Pankrath wrote:On Monday, 9 February 2015 at 12:39:06 UTC, Marc Schütz wrote:I'm talking about the general case. Jacob seems to be saying that a unique _immutable_ value is implicitly convertible to mutable.On Monday, 9 February 2015 at 11:38:23 UTC, Jakob Ovrum wrote:join returns a mutable array, that can be implicitly casted to immutable if join is pure.On Monday, 9 February 2015 at 11:37:23 UTC, Jakob Ovrum wrote:It does? Not according to my tests. And it would be bad if it did, because the returned immutable value could actually reside in read-only memory.std.array.join is strongly pure (with appropriate template arguments), so its return value is implicitly convertible to immutable.Err, implicitly convertible to *mutable*. It goes both ways.
Feb 09 2015
2015-02-10 0:15 GMT+09:00 via Digitalmars-d <digitalmars-d puremagic.com>:On Monday, 9 February 2015 at 13:19:24 UTC, Tobias Pankrath wrote:eOn Monday, 9 February 2015 at 12:39:06 UTC, Marc Sch=C3=BCtz wrote:I'm talking about the general case. Jacob seems to be saying that a uniqu=It does? Not according to my tests. And it would be bad if it did, because the returned immutable value could actually reside in read-only memory.join returns a mutable array, that can be implicitly casted to immutable if join is pure._immutable_ value is implicitly convertible to mutable.In general, pure function can access immutable global data, and can return its address. Therefore, if a pure function returns immutable data, the returned pointer/reference to immutable a data should not be convertible to mutable. Kenji Hara
Feb 09 2015
On Monday, 9 February 2015 at 11:38:23 UTC, Jakob Ovrum wrote:On Monday, 9 February 2015 at 11:37:23 UTC, Jakob Ovrum wrote:Sorry, this is indeed nonsense, I take it back. It only goes one way.std.array.join is strongly pure (with appropriate template arguments), so its return value is implicitly convertible to immutable.Err, implicitly convertible to *mutable*. It goes both ways.
Feb 09 2015
On Monday, 9 February 2015 at 11:37:23 UTC, Jakob Ovrum wrote:std.array.join is strongly pure (with appropriate template arguments), so its return value is implicitly convertible to immutable.Ahha, I have missed that part. Thanks!
Feb 09 2015
On Monday, 9 February 2015 at 10:56:31 UTC, Dicebot wrote:Doing a lot of porting from D1 to D2 recently I have realized that we still don't have any idiomatic way to express function result types that can be both mutable and immutable. Consider this trivial snippet: ```D import std.array : join; void main() { auto s = join([ "aaa", "bbb", "ccc" ]); pragma(msg, typeof(s)); } ``` It outputs "string" which stands for immutable buffer. However, actual allocated buffer is not yet truly immutable - it has just been allocated to hold the result of join algorithm and may be interpreted both as mutable and immutable, depending on caller desire. In this specific case if caller wanted to get a mutable buffer instead, it would need to do cast from immutable which is very dangerous - especially considering implementation of `join` may change. And doing .dup on buffer that has just been allocated is quite a waste. Right now I am leaning towards personal convention to always return mutable or const buffers and do assumeUnique at caller side where necessary. But this does, of course, suck. What is current conventional wisdom on topic? Can we probably start using std.typecons.Unique for such functions?Someone is starting to see where I'm getting at when I'm pushing for owned...
Feb 09 2015
On Monday, 9 February 2015 at 23:40:31 UTC, deadalnix wrote:Someone is starting to see where I'm getting at when I'm pushing for owned...I don't think this specific case is a good justification for your proposal - it is simple enough to accept a library based solution. We need more accumulated anecdotal evidence.
Feb 11 2015
On Wednesday, 11 February 2015 at 13:54:12 UTC, Dicebot wrote:On Monday, 9 February 2015 at 23:40:31 UTC, deadalnix wrote:We do have. That is simply one more. On the top of my head: - Plug hole in the type system (implicit sharing). - Use the guarantee the type system is supposed to provide to get a better GC. - Construction of immutable objects. - make nogc actually useful for something else than trivias (throw, defers usage of GC to the caller). - make std.concurency and std.parallelism safe end to end. - Be able to lock tree of objects. - Generating less garbage overall. - ...Someone is starting to see where I'm getting at when I'm pushing for owned...I don't think this specific case is a good justification for your proposal - it is simple enough to accept a library based solution. We need more accumulated anecdotal evidence.
Feb 11 2015
On Wednesday, 11 February 2015 at 18:37:42 UTC, deadalnix wrote:On Wednesday, 11 February 2015 at 13:54:12 UTC, Dicebot wrote:Or we can add an easier hack for each of these. That is gonna scale well.On Monday, 9 February 2015 at 23:40:31 UTC, deadalnix wrote:We do have. That is simply one more. On the top of my head: - Plug hole in the type system (implicit sharing). - Use the guarantee the type system is supposed to provide to get a better GC. - Construction of immutable objects. - make nogc actually useful for something else than trivias (throw, defers usage of GC to the caller). - make std.concurency and std.parallelism safe end to end. - Be able to lock tree of objects. - Generating less garbage overall. - ...Someone is starting to see where I'm getting at when I'm pushing for owned...I don't think this specific case is a good justification for your proposal - it is simple enough to accept a library based solution. We need more accumulated anecdotal evidence.
Feb 11 2015