www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.learn - Populating nested AAs; "This wouldn't be so verbose in Ada 2020"

reply mipri <mipri minimaltype.com> writes:
Hello,

I've got this code:

   struct UserStats {
     int ok, evil;
   }

   // module-level variable
   UserStats[string][string] userHistory;

and this code that populates it:

   // loop over DB query

   if (host !in userHistory)
       userHistory[host] = typeof(userHistory[host]).init;

   if (user !in userHistory[host])
       userHistory[host][user] = 
typeof(userHistory[host][user]).init;

   if (ok) ++userHistory[host][user].ok;
   else ++userHistory[host][user].evil;

The joke of the thread title is that in pseudo-Ada2020, those
assignments would look like

   User_History (host) = typeof ( ).init;
   User_History (host) (user) = typeof ( ).init;

as   is a shortcut for the left hand side of an assignment.
It's what Ada has instead of += and friends.

Of course, I don't propose that   be added to D; I just want to
know if there's a good idiom for new assignments to nested AAs
like this. A nice alternative for my specific use is

   struct UserStats {
     static int[Tuple!(string, string)] ok, evil;
   }

and

   // loop over DB query
   if (ok) ++UserStats.ok[tuple(host, user)];
   else ++UserStats.evil[tuple(host, user)];

But of course this would be less convenient if f.e. I wanted to
pattern my data structures after a JSON production result.
Dec 07 2019
parent reply Paul Backus <snarwin gmail.com> writes:
On Sunday, 8 December 2019 at 04:17:45 UTC, mipri wrote:
 Hello,

 I've got this code:

   struct UserStats {
     int ok, evil;
   }

   // module-level variable
   UserStats[string][string] userHistory;

 and this code that populates it:

   // loop over DB query

   if (host !in userHistory)
       userHistory[host] = typeof(userHistory[host]).init;

   if (user !in userHistory[host])
       userHistory[host][user] = 
 typeof(userHistory[host][user]).init;

   if (ok) ++userHistory[host][user].ok;
   else ++userHistory[host][user].evil;
You can use the `require` function [1] for this: with (userHistory.require(host).require(user)) { if (isOk) ++ok; // renamed to avoid shadowing else ++evil; } Many "methods" for built-in AAs are located in the `object` module. It makes them a bit tricky to find in the documentation, if you don't already know they're there. https://dlang.org/phobos/object.html#.require
Dec 07 2019
parent mipri <mipri minimaltype.com> writes:
On Sunday, 8 December 2019 at 06:42:22 UTC, Paul Backus wrote:
 You can use the `require` function [1] for this:

 with (userHistory.require(host).require(user)) {
     if (isOk) ++ok; // renamed to avoid shadowing
     else ++evil;
 }

 Many "methods" for built-in AAs are located in the `object` 
 module. It makes them a bit tricky to find in the 
 documentation, if you don't already know they're there.

 https://dlang.org/phobos/object.html#.require
Thanks! I wasn't aware of the 'object' doc. Looks like the language documentation does mention require() in "Inserting if not present", but combining it with 'with' is a neat trick.
Dec 07 2019