Re: Feature to get or add value to an associative array.
On Tuesday, 24 April 2018 at 09:09:37 UTC, Andrea Fontana wrote: Just one question: does this work for value-types? The intention is that it will work for value types. I will add some unit tests to check that use case. - Giles
Re: Feature to get or add value to an associative array.
On Sunday, 15 April 2018 at 22:52:47 UTC, Giles Bathgate wrote: Hi, I wanted a way to lazily insert a value into an associative array, and I am proposing a new function called getOrAdd in https://github.com/dlang/druntime/pull/2162 Yes please :) Just one question: does this work for value-types? This is a pretty common case for me (simplified and not optimized version): size_t[string] counter; ... foreach(e; elements) { if (e.something !in counter) counter[e.something] = 0; else counter[e.something]++; } So will this work? foreach(e; elements) counter.update(e.something, { return 0; }, (size_t v) { return v+1; }) Andrea Andrea
Re: Feature to get or add value to an associative array.
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
Re: Feature to get or add value to an associative array.
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 = ("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 = // 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
Re: Feature to get or add value to an associative array.
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 = ("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 = // 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
Re: Feature to get or add value to an associative array.
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 = ("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 = // 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
Re: Feature to get or add value to an associative array.
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.
Re: Feature to get or add value to an associative array.
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**), typeid(V[K]), V.sizeof, , 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 ;)
Re: Feature to get or add value to an associative array.
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.
Re: Feature to get or add value to an associative array.
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 = ("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
Re: Feature to get or add value to an associative array.
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 = ("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
Re: Feature to get or add value to an associative array.
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.
Re: Feature to get or add value to an associative array.
On Wednesday, 18 April 2018 at 16:04:13 UTC, Giles Bathgate wrote: I understand where you are coming from, but I am not sure it is appropriate to shoehorn every use case into one api. It is not shoehorning, the difference here is just returning by ref vs pointer. I understand that, as the pointer address is not needed by the caller, it is cleaner to use ref. The problem is that local refs are not supported by D, and so I would need to do this (at least in safe code): import std.functional : unaryFun; bool ins; aa.update("key", {ins = true; return 1;}).unaryFun!((v){ if (ins) v++; }); This seems pretty convoluted. It could be made a bit better if D supported UFCS for lambdas, then unaryFun wouldn't be needed. BTW, I like the name `update`. void createOrUpdate(K, V)(ref V[K] aa, K key, V delegate() create, void delegate(V*) update); 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.
Re: Feature to get or add value to an associative array.
On Wednesday, 18 April 2018 at 16:47:50 UTC, ag0aep6g wrote: You can get a pointer from the ref return: Value* p = ("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
Re: Feature to get or add value to an associative array.
On Wednesday, April 18, 2018 17:19:45 Giles Bathgate via Digitalmars-d wrote: > On Sunday, 15 April 2018 at 22:55:41 UTC, Giles Bathgate wrote: > > Time for a bikeshed discussion... > > I have had some thoughts about the name and would like to share > my idea. > > Firstly to summarise here are the names that have been > found/discussed so far: > > C# : GetOrAdd > Java : computeIfAbsent > Python : setdefault > Rust : entry(key).or_insert_with > > Jordan Wilson: getOrAdd, getOrSet > User1234 : valueOrDefault > Nicholas Wilson : getOrInsert > Steven Schveighoffer : getPtr, getRef, getInitialized > Nick Treleaven : slot > MrSmith : getOrCreate > > My latest idea is just a working title, but I think I prefer it > to my original getOrAdd. > > Giles Bathgate : require > > My thinking is that if you `require` there to be a value in the > associative array, then you should have the ability to add one > iff it doesn't exist. It name also has parallels with the term in > other programming languages to require a module, meaning to > import it if it hasn't already been loaded. 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. The only one in that list that seems similarly opaque is slot. Those names say nothing about either getting a value or adding / inserting one. Every other name at least gives some clue as to what the function does. If I were adding it, and we already had get, I would just make it an optional argument to get, which wouldn't necessarily be clear about inserting, but it would at least be clear about getting. However, since we used overloaded operators, there's no get. Another option would be getOrInit, though I agree that they're all kind of ugly. Either way, IMHO, getOrAdd is infinitely better than require. - Jonathan M Davis
Re: Feature to get or add value to an associative array.
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.
Re: Feature to get or add value to an associative array.
On Wednesday, 18 April 2018 at 17:19:45 UTC, Giles Bathgate wrote: On Sunday, 15 April 2018 at 22:55:41 UTC, Giles Bathgate wrote: Time for a bikeshed discussion... I have had some thoughts about the name and would like to share my idea. Firstly to summarise here are the names that have been found/discussed so far: C# : GetOrAdd Java : computeIfAbsent Python : setdefault Rust : entry(key).or_insert_with Jordan Wilson: getOrAdd, getOrSet User1234 : valueOrDefault Nicholas Wilson : getOrInsert Steven Schveighoffer : getPtr, getRef, getInitialized Nick Treleaven : slot MrSmith : getOrCreate My latest idea is just a working title, but I think I prefer it to my original getOrAdd. Giles Bathgate : require My thinking is that if you `require` there to be a value in the associative array, then you should have the ability to add one iff it doesn't exist. It name also has parallels with the term in other programming languages to require a module, meaning to import it if it hasn't already been loaded. Thinking seems sound, although having a name starting with "get" does have the advantage of being more related to the existing get. Weirdly, in all cases if I replace "Or" with "Else", it seems to read easier for me... getElseAdd, getElseCreate, etc. Ultimately I'm not too bothered with any name really, I'm just looking forward to using it eventually :-) Jordan
Re: Feature to get or add value to an associative array.
On Sunday, 15 April 2018 at 22:55:41 UTC, Giles Bathgate wrote: Time for a bikeshed discussion... I have had some thoughts about the name and would like to share my idea. Firstly to summarise here are the names that have been found/discussed so far: C# : GetOrAdd Java : computeIfAbsent Python : setdefault Rust : entry(key).or_insert_with Jordan Wilson: getOrAdd, getOrSet User1234 : valueOrDefault Nicholas Wilson : getOrInsert Steven Schveighoffer : getPtr, getRef, getInitialized Nick Treleaven : slot MrSmith : getOrCreate My latest idea is just a working title, but I think I prefer it to my original getOrAdd. Giles Bathgate : require My thinking is that if you `require` there to be a value in the associative array, then you should have the ability to add one iff it doesn't exist. It name also has parallels with the term in other programming languages to require a module, meaning to import it if it hasn't already been loaded.
Re: Feature to get or add value to an associative array.
On 04/18/2018 11:41 AM, Nick Treleaven wrote: How do you implement this if the function returns with ref: bool inserted; auto p = aa.slot("key", ); if (inserted) { ... // set *p } else { // read *p ... // set *p } You can get a pointer from the ref return: Value* p = ("key", { inserted = true; return Value.init; }); Then do with the pointer whatever you want.
Re: Feature to get or add value to an associative array.
On Wednesday, 18 April 2018 at 09:41:48 UTC, Nick Treleaven wrote: How do you implement this if the function returns with ref: I understand where you are coming from, but I am not sure it is appropriate to shoehorn every use case into one api. I think actually what you are describing here is the AddOrUpdate style method https://msdn.microsoft.com/en-us/library/ee378665(v=vs.110).aspx Perhaps the implementation could be: void createOrUpdate(K, V)(ref V[K] aa, K key, V delegate() create, void delegate(V*) update); C newc; aa.createOrUpdate("key", { /* set *p */ newc = new C; return newc; }, (C* u){ // read *p newc = *u; // set *p *u = new C; }); assert(aa["key"] == newc); ¯\_(ツ)_/¯
Re: Feature to get or add value to an associative array.
On Tuesday, 17 April 2018 at 20:49:30 UTC, Steven Schveighoffer wrote: Why do you think it's less efficient to use a lazy parameter? Wouldn't an extra function call have to happen, at least in some cases? This pattern needs a pointer to be returned, instead of using `ref`. Note that `` is valid in @safe code, but only with -dip1000. I called the function `slot` because it always returns the address of the slot which the value is stored in. Returning ref makes more sense to me -- you are never going to return null. How do you implement this if the function returns with ref: bool inserted; auto p = aa.slot("key", ); if (inserted) { ... // set *p } else { // read *p ... // set *p } There is a common basic use case for this - counting the occurrence of a key in a data set. If the key doesn't exist, initialize and insert the value. *Iff* it does exist, increment the value - I don't think you can do this without functional contortions with your ref return. (A side benefit is that returning a pointer is consistent with `in`.)
Re: Feature to get or add value to an associative array.
On Tuesday, 17 April 2018 at 21:40:55 UTC, Giles Bathgate wrote: Rust calls its version of this function `or_insert_with` (blegh) Of course, a rustic API could be built atop this PR: template entry(K, V) { static struct Entry { alias get this; V[K] aa; K key; V get() { return aa[key]; } V orInsert() { return aa.getOrAdd(key); } V orInsertWith(lazy V value = V.init) { return aa.getOrAdd(key, value); } } Entry entry(ref V[K] aa, K key) { return Entry(aa,key); } } void main() { class C{} C[string] aa; auto v1 = aa.entry("foo"); auto v2 = aa.entry("bar").orInsert(); auto v3 = aa.entry("baz").orInsertWith(new C); } But I think, this would be out of scope.
Re: Feature to get or add value to an associative array.
On Tuesday, 17 April 2018 at 20:49:30 UTC, Steven Schveighoffer wrote: Not as straightforward, but it can be done: bool inserted = false; auto p = aa.getOrAdd("key", {inserted = true; return new Person; }); Yes, I like that approach. I don't want to bloat the feature at this stage, although there is nothing stopping adding an overload later. I agree returning ref makes sense since we never return null. Consequently, I am leaning toward thinking it should be called getOrCreate now though. Rust calls its version of this function `or_insert_with` (blegh) https://doc.rust-lang.org/std/collections/hash_map/enum.Entry.html#method.or_insert_with
Re: Feature to get or add value to an associative array.
On 4/17/18 12:18 PM, Nick Treleaven wrote: On Sunday, 15 April 2018 at 22:52:47 UTC, Giles Bathgate wrote: The function provides a means to get a value corresponding to the key, but if the value doesn't exist it will evaluate the lazy argument to create a new value, add this to the associative array and then return it. auto p = lookup.getOrAdd("giles", new Person); Thanks for making this pull, I've thought about solving this before. I think the function needs to provide a way to tell if the value was already present. Not as straightforward, but it can be done: bool inserted = false; auto p = aa.getOrAdd("key", {inserted = true; return new Person; }); Note that most of the time, the only reason you need to know it's new is to initialize it. But the lazy parameter takes care of that for you. I also think it's more ergonomic not to have to use a lazy argument, and probably more efficient, so I had in mind: Value* slot(AA aa, K key, scope bool* inserted = null); I like the name slot. I'm less enthused about the extra machinery needed for initializing the value. Why do you think it's less efficient to use a lazy parameter? This pattern needs a pointer to be returned, instead of using `ref`. Note that `` is valid in @safe code, but only with -dip1000. I called the function `slot` because it always returns the address of the slot which the value is stored in. Returning ref makes more sense to me -- you are never going to return null. -Steve
Re: Feature to get or add value to an associative array.
On Tuesday, 17 April 2018 at 19:33:16 UTC, MrSmith wrote: You may need to perform extra logic when value is inserted in the container and something else when value already existed. Fair enough, I will consider adding this and some tests to the PR, a function overload seems like the way to go.
Re: Feature to get or add value to an associative array.
On Tuesday, 17 April 2018 at 17:27:02 UTC, Giles Bathgate wrote: I like the name. I think your version is quite low level which ultimately provides more power at the expense of making the callee code less clean. I am not sure with D which of those two aspects is preferred. Perhaps both functions could be provided? What is the use case for knowing whether a value was inserted. You may need to perform extra logic when value is inserted in the container and something else when value already existed. I have a special version of function for that: Value* getOrCreate(Key key, out bool wasCreated, Value default_value = Value.init) here is an example of usage: https://github.com/MrSmith33/voxelman/blob/master/plugins/voxelman/entity/entityobservermanager.d#L33
Re: Feature to get or add value to an associative array.
On Tuesday, 17 April 2018 at 16:18:32 UTC, Nick Treleaven wrote: I called the function `slot` because it always returns the address of the slot which the value is stored in. I like the name. I think your version is quite low level which ultimately provides more power at the expense of making the callee code less clean. I am not sure with D which of those two aspects is preferred. Perhaps both functions could be provided? What is the use case for knowing whether a value was inserted.
Re: Feature to get or add value to an associative array.
On Sunday, 15 April 2018 at 22:52:47 UTC, Giles Bathgate wrote: The function provides a means to get a value corresponding to the key, but if the value doesn't exist it will evaluate the lazy argument to create a new value, add this to the associative array and then return it. auto p = lookup.getOrAdd("giles", new Person); Thanks for making this pull, I've thought about solving this before. I think the function needs to provide a way to tell if the value was already present. I also think it's more ergonomic not to have to use a lazy argument, and probably more efficient, so I had in mind: Value* slot(AA aa, K key, scope bool* inserted = null); bool inserted; auto p = aa.slot("key", ); if (inserted) { ... *p = new Value(...); } // use *p This pattern needs a pointer to be returned, instead of using `ref`. Note that `` is valid in @safe code, but only with -dip1000. I called the function `slot` because it always returns the address of the slot which the value is stored in.
Re: Feature to get or add value to an associative array.
On Tuesday, 17 April 2018 at 09:21:14 UTC, Giles Bathgate wrote: The java name for such a function is `computeIfAbsent` More names from other languages, this time python: https://docs.python.org/3/library/stdtypes.html#dict.setdefault It's horrid though, a method called `set` that returns a value? Maybe I am biased against anything pythonic ;)
Re: Feature to get or add value to an associative array.
On 4/15/18 6:52 PM, Giles Bathgate wrote: I find this later code clunky and it requires two hashes/lookups. The proposed implementation adds support directly to rt/aaA.d to avoid this. I should also point out that the allocation of a new Person in the example is trivial, but it might often be the case that the person instance is created by fetching a record from a db, or an Image loaded from disk, or a movie downloaded from the internet. I think this is a great addition. I've always disliked the double-lookup requirement for ensuring a key was initialized. I'll note that C++ gets around this by always initializing on any access. The name "getOrAdd" is a bit mechanical sounding. The real reason you want this is to ensure that key's value is initialized. ensureInitialized is long. get is already taken (if get weren't already taken, I'd suggest that name). Others have suggested using flags, but I'll note to them, `Flag` and `Yes` are part of std.typecons, and not accessible here. getWithDefault sounds reasonable but probably would be confusing with the current `get` overload. Maybe getInitialized? I don't know that either of these are giant leaps ahead of getOrAdd. Another possibility is getPtr. get currently gets a value, or returns a default value if it doesn't exist. But getPtr would return a pointer to the value, ensuring it's initialized. In any case, thumbs up to the concept, and I'm ambivalent on the name. -Steve
Re: Feature to get or add value to an associative array.
On Tuesday, 17 April 2018 at 07:40:23 UTC, Giles Bathgate wrote: My personal reason for not liking it is because the same name is used by Microsoft The java name for such a function is `computeIfAbsent` https://docs.oracle.com/javase/8/docs/api/java/util/Map.html#computeIfAbsent-K-java.util.function.Function-
Re: Feature to get or add value to an associative array.
On Tuesday, 17 April 2018 at 00:04:32 UTC, Cym13 wrote: "in" returns a pointer to the object, there'es not double lookup necessary: // if we don't know .get(key, default) exists auto ptr = key in aa; auto value = ptr ? *ptr : default; This doesn't work. `in` returns null when the key doesn't exist. So you are de-referencing null: https://github.com/dlang/druntime/blob/master/src/rt/aaA.d#L417 is a new flag/method really that necessary? In my experience if you have trouble naming it you haven't found its true purpose yet. My personal reason for not liking it is because the same name is used by Microsoft: https://msdn.microsoft.com/en-us/library/ee378676(v=vs.110).aspx I think I have clearly explained its purpose.
Re: Feature to get or add value to an associative array.
On Tuesday, 17 April 2018 at 00:04:32 UTC, Cym13 wrote: auto value = ptr ? *ptr : *ptr = default; That is going to crash if ptr is null. is a new flag/method really that necessary? In my experience if you have trouble naming it you haven't found its true purpose yet. I think `getOrInsert` is a good name for this function
Re: Feature to get or add value to an associative array.
On Monday, 16 April 2018 at 18:59:54 UTC, Giles Bathgate wrote: On Monday, 16 April 2018 at 12:41:07 UTC, JN wrote: It's only one additional "in", but makes the code more explicit and clear. I think in most cases, you will want to check if you are dealing with a fetched object or a default created one, so that will complicate the function even further. You can still use a combination of `in` and the update syntax if you want, this doesn't take that away. In the future, for a concurrent implementation of associative arrays, a way of getting or adding an element as an atomic operation becomes more important. Either way the beauty of hashed based lookups is that they average O(1), seems a shame to double that up for no reason ;) "in" returns a pointer to the object, there'es not double lookup necessary: // if we don't know .get(key, default) exists auto ptr = key in aa; auto value = ptr ? *ptr : default; // to set default value on the fly auto value = ptr ? *ptr : *ptr = default; is a new flag/method really that necessary? In my experience if you have trouble naming it you haven't found its true purpose yet.
Re: Feature to get or add value to an associative array.
On Sunday, 15 April 2018 at 22:55:41 UTC, Giles Bathgate wrote: On Sunday, 15 April 2018 at 22:52:47 UTC, Giles Bathgate wrote: I am proposing a new function called getOrAdd in I posted details of the PR here because at least 2 people do not like the name getOrAdd (and one of those people being myself) Time for a bikeshed discussion... It's hard to name... I cant find better than "valueOrDefault"
Re: Feature to get or add value to an associative array.
On Monday, 16 April 2018 at 12:41:07 UTC, JN wrote: It's only one additional "in", but makes the code more explicit and clear. I think in most cases, you will want to check if you are dealing with a fetched object or a default created one, so that will complicate the function even further. You can still use a combination of `in` and the update syntax if you want, this doesn't take that away. In the future, for a concurrent implementation of associative arrays, a way of getting or adding an element as an atomic operation becomes more important. Either way the beauty of hashed based lookups is that they average O(1), seems a shame to double that up for no reason ;)
Re: Feature to get or add value to an associative array.
On Sunday, 15 April 2018 at 22:52:47 UTC, Giles Bathgate wrote: Hi, I wanted a way to lazily insert a value into an associative array, and I am proposing a new function called getOrAdd in https://github.com/dlang/druntime/pull/2162 I am not sure if it's a good idea to combine accessor and insertion in a same method call. Is it really such a big overhead to do "if in assocarray then take else create new"? It's only one additional "in", but makes the code more explicit and clear. I think in most cases, you will want to check if you are dealing with a fetched object or a default created one, so that will complicate the function even further.
Re: Feature to get or add value to an associative array.
On Monday, 16 April 2018 at 03:42:18 UTC, Jordan Wilson wrote: On Sunday, 15 April 2018 at 22:55:41 UTC, Giles Bathgate wrote: On Sunday, 15 April 2018 at 22:52:47 UTC, Giles Bathgate wrote: I am proposing a new function called getOrAdd in I posted details of the PR here because at least 2 people do not like the name getOrAdd (and one of those people being myself) Time for a bikeshed discussion... I think Adding a Yes.add flag to the existing get makes sense, but property functions only have max 2 args. S...getOrAdd or getOrSet would be my pick. Jordan I'm opposed to flags. I hate the whole "yes" "no" thing when it comes to such things, just like the "true" "false"... It's a no go for me. A function name that fits would be perfect in my opinion.
Re: Feature to get or add value to an associative array.
On Monday, 16 April 2018 at 03:42:18 UTC, Jordan Wilson wrote: I think Adding a Yes.add flag to the existing get makes sense That's an interesting idea. I forgot to mention that getOrAdd is a mutable function whereas get is inout, so that might also be problematic.
Re: Feature to get or add value to an associative array.
On Sunday, 15 April 2018 at 22:55:41 UTC, Giles Bathgate wrote: On Sunday, 15 April 2018 at 22:52:47 UTC, Giles Bathgate wrote: I am proposing a new function called getOrAdd in I posted details of the PR here because at least 2 people do not like the name getOrAdd (and one of those people being myself) Time for a bikeshed discussion... I think Adding a Yes.add flag to the existing get makes sense, but property functions only have max 2 args. S...getOrAdd or getOrSet would be my pick. Jordan
Re: Feature to get or add value to an associative array.
On Sunday, 15 April 2018 at 22:52:47 UTC, Giles Bathgate wrote: I am proposing a new function called getOrAdd in I posted details of the PR here because at least 2 people do not like the name getOrAdd (and one of those people being myself) Time for a bikeshed discussion...