Jump to page: 1 2
Thread overview
Const-correctness and uniqueness. Again.
Feb 09, 2015
Dicebot
Feb 09, 2015
Jakob Ovrum
Feb 09, 2015
Jakob Ovrum
Feb 09, 2015
Marc Schütz
Feb 09, 2015
Tobias Pankrath
Feb 09, 2015
Marc Schütz
Feb 09, 2015
Kenji Hara
Feb 09, 2015
Jakob Ovrum
Feb 09, 2015
Dicebot
Feb 09, 2015
deadalnix
Feb 11, 2015
Dicebot
Feb 11, 2015
deadalnix
Feb 11, 2015
deadalnix
February 09, 2015
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?
February 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.
February 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.
February 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!
February 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:
>> 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.

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.
February 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:
>> 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.
>
> 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.

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?
February 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:
>> 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:
>>>> 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.
>>
>> 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.

I'm talking about the general case. Jacob seems to be saying that a unique _immutable_ value is implicitly convertible to mutable.
February 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:
>
>> On Monday, 9 February 2015 at 12:39:06 UTC, Marc Schütz 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.
>>>
>>
>> join returns a mutable array, that can be implicitly casted to immutable if join is pure.
>>
>
> I'm talking about the general case. Jacob seems to be saying that a unique _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


February 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:
>> 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.

Sorry, this is indeed nonsense, I take it back. It only goes one way.
February 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...
« First   ‹ Prev
1 2