April 20, 2018
On Thursday, 19 April 2018 at 08:20:02 UTC, Giles Bathgate wrote:
> On Wednesday, 18 April 2018 at 21:04:53 UTC, Jordan Wilson wrote:
>> Thinking seems sound, although having a name starting with "get" does have the advantage of being more related to the existing get.
>
> Ah yes, good point. I think now we've had the discussion about other use cases though that ultimately there might need to be an "atomic" AddOrUpdate style function too, which I was thinking could just be called 'update'. The necessity to keep them all starting with get seemed less important.

How about something like "forceGet" to make clear you will get it, even if it wasn't there before.
April 20, 2018
On 04/20/2018 10:24 AM, Nick Treleaven wrote:
> On Wednesday, 18 April 2018 at 16:47:50 UTC, ag0aep6g wrote:
>> You can get a pointer from the ref return:
>>
>>     Value* p = &aa.slot("key", { inserted = true; return Value.init; });
> 
> This is not @safe, even with -dip1000:
> 
> Error: cannot take address of ref return of f() in @safe function main

Hm. Do you know why that's not allowed? I can't see how it would be less safe than returning a pointer, and I can't find a mention of it in DIP 1000 [1]. Maybe it's just a case of incomplete/buggy implementation?


[1] https://github.com/dlang/DIPs/blob/master/DIPs/DIP1000.md
April 20, 2018
On Friday, April 20, 2018 10:56:37 ag0aep6g via Digitalmars-d wrote:
> On 04/20/2018 10:24 AM, Nick Treleaven wrote:
> > On Wednesday, 18 April 2018 at 16:47:50 UTC, ag0aep6g wrote:
> >> You can get a pointer from the ref return:
> >>
> >>     Value* p = &aa.slot("key", { inserted = true; return Value.init;
> >> });
> >
> > This is not @safe, even with -dip1000:
> >
> > Error: cannot take address of ref return of f() in @safe function main
>
> Hm. Do you know why that's not allowed? I can't see how it would be less safe than returning a pointer, and I can't find a mention of it in DIP 1000 [1]. Maybe it's just a case of incomplete/buggy implementation?
>
>
> [1] https://github.com/dlang/DIPs/blob/master/DIPs/DIP1000.md

The compiler assumes that a pointer is valid when determining whether code is @safe. It then disallows operations that it can't guarantee are @safe even if the pointer is valid, and it disallows taking the address in cases where it can't guarantee that that's @safe. Basically, it verifies the @safety of pointers when they're created and then assumes that they're @safe after that. So, passing around a pointer is perfectly @safe, whereas taking the address of a ref return value to get a pointer is not.

- Jonathan M Davis

April 20, 2018
On Friday, 20 April 2018 at 09:24:26 UTC, Jonathan M Davis wrote:
> The compiler assumes that a pointer is valid when determining whether code is @safe.
[...]
> Basically, it verifies the @safety of pointers when they're created and then assumes that they're @safe after that.

Can't it do the same for ref returns? Unsafe stuff like returning a ref to a local is already disallowed, just like returning a pointer to a local. So the compiler checks the safety on creation, at least in some cases.

> So, passing around a pointer is perfectly @safe, whereas taking the address of a ref return value to get a pointer is not.

It's still not clear to me how taking the address of a ref return is necessarily less safe than using a returned pointer. Do you maybe have an example in code that shows the difference?

It seems to me that refs and pointers are very much equivalent. I should always be able to turn one into the other.
April 20, 2018
On Friday, 20 April 2018 at 08:37:59 UTC, Nick Treleaven wrote:
> Again, would the delegate calls always be inlined, in all cases?
>
> I think having a low-level API in druntime is appropriate, it's a runtime library after all.

So the low-level API you are requesting is part of the pull request, the low-level API is called _aaGetX, whereas the previous API was _aaGetY, the new API adds a boolean out parameter `found` and if you really wanted to you could do this:

-----
extern (C) void* _aaGetX(void** paa, const TypeInfo_AssociativeArray ti, in size_t valuesize, in void* pkey, out bool found) pure nothrow;

V* slot(K, V)(ref V[K] aa, K key, out bool found)
{
    return cast(V*) _aaGetX(cast(void**)&aa, typeid(V[K]), V.sizeof, &key, found);
}
-----

I am also benchmarking the `update` function I talked about previously.
https://gist.github.com/GilesBathgate/8409b5889ebb7b1302627c50f342a28b

The results seem to indicate that there isn't much in it performance wise.

test1 [56 ms, 377 µs, and 4 hnsecs]
test2 [56 ms, 262 µs, and 2 hnsecs]

I can't fathom why the delegates version is faster, but I am just putting it down to luck ;)
April 20, 2018
On Friday, 20 April 2018 at 02:12:37 UTC, Jonathan M Davis wrote:
> Out of all of those, I _really_ hope that you don't go with require. It sounds like the sort of thing that you'd get in a library having to do with unit testing or contracts and gives no indication whatsoever as to what it does.

Yes I know. I gave up on trying to find a single verb or runTogetherWords that would describe exactly what it does, and instead opted for something that I like, and added documentation to describe what it does.

I don't think I will find a name that everybody likes. But I am open to more suggestions as its probably the easiest aspect of the PR to change.
April 20, 2018
On 4/20/18 4:24 AM, Nick Treleaven wrote:
> On Wednesday, 18 April 2018 at 16:47:50 UTC, ag0aep6g wrote:
>> You can get a pointer from the ref return:
>>
>>     Value* p = &aa.slot("key", { inserted = true; return Value.init; });
> 
> This is not @safe, even with -dip1000:
> 
> Error: cannot take address of ref return of f() in @safe function main

Hm... I would have expected it to work in dip1000.

Hard for me to understand what dip1000 is doing, but it seems like an omission:

@safe ref int foo(return ref int x) { return x; }

void main() @safe
{
   int x;
   scope int *xp = &x; // OK with dip1000
   xp = foo(x); // Error, even though it's exactly the same
}

And in this case, it doesn't even need to be scope, as it's GC data. How does one communicate that the ref return is of GC data and can be escaped as much as you want?

-Steve
April 20, 2018
On Friday, 20 April 2018 at 14:02:17 UTC, Steven Schveighoffer wrote:
> On 4/20/18 4:24 AM, Nick Treleaven wrote:
>> On Wednesday, 18 April 2018 at 16:47:50 UTC, ag0aep6g wrote:
>>> You can get a pointer from the ref return:
>>>
>>>     Value* p = &aa.slot("key", { inserted = true; return Value.init; });
>> 
>> This is not @safe, even with -dip1000:
>> 
>> Error: cannot take address of ref return of f() in @safe function main
>
> Hm... I would have expected it to work in dip1000.
>
> Hard for me to understand what dip1000 is doing, but it seems like an omission:
>
> @safe ref int foo(return ref int x) { return x; }
>
> void main() @safe
> {
>    int x;
>    scope int *xp = &x; // OK with dip1000
>    xp = foo(x); // Error, even though it's exactly the same
> }
>
> And in this case, it doesn't even need to be scope, as it's GC data. How does one communicate that the ref return is of GC data and can be escaped as much as you want?
>
> -Steve

The error seems to be about type mismatching, it works if you use auto. I don't see how you could convert the `ref int` to `int *`
https://run.dlang.io/is/eIJMIK
April 20, 2018
On 4/20/18 10:34 AM, Uknown wrote:
> On Friday, 20 April 2018 at 14:02:17 UTC, Steven Schveighoffer wrote:
>> On 4/20/18 4:24 AM, Nick Treleaven wrote:
>>> On Wednesday, 18 April 2018 at 16:47:50 UTC, ag0aep6g wrote:
>>>> You can get a pointer from the ref return:
>>>>
>>>>     Value* p = &aa.slot("key", { inserted = true; return Value.init; });
>>>
>>> This is not @safe, even with -dip1000:
>>>
>>> Error: cannot take address of ref return of f() in @safe function main
>>
>> Hm... I would have expected it to work in dip1000.
>>
>> Hard for me to understand what dip1000 is doing, but it seems like an omission:
>>
>> @safe ref int foo(return ref int x) { return x; }
>>
>> void main() @safe
>> {
>>    int x;
>>    scope int *xp = &x; // OK with dip1000
>>    xp = foo(x); // Error, even though it's exactly the same
>> }
>>
>> And in this case, it doesn't even need to be scope, as it's GC data. How does one communicate that the ref return is of GC data and can be escaped as much as you want?
>>
> 
> The error seems to be about type mismatching, it works if you use auto. I don't see how you could convert the `ref int` to `int *`
> https://run.dlang.io/is/eIJMIK

Sorry, it was a typo. In my real code I have:

xp = &(foo(x));

That's what I get for hand-typing instead of copy-pasting :)

-Steve
April 20, 2018
On Friday, 20 April 2018 at 15:00:39 UTC, Steven Schveighoffer wrote:
> On 4/20/18 10:34 AM, Uknown wrote:
>> On Friday, 20 April 2018 at 14:02:17 UTC, Steven Schveighoffer wrote:
>>> On 4/20/18 4:24 AM, Nick Treleaven wrote:
>>>> On Wednesday, 18 April 2018 at 16:47:50 UTC, ag0aep6g wrote:
>>>>> [...]
>
> Sorry, it was a typo. In my real code I have:
>
> xp = &(foo(x));
>
> That's what I get for hand-typing instead of copy-pasting :)
>
> -Steve

It seems like a bug. Changing foo to take and return an `int *` works as expected
https://run.dlang.io/is/3NYXYv