automate tuple creation

Ali Çehreli acehreli at yahoo.com
Fri Jan 21 02:30:35 UTC 2022


On 1/20/22 17:35, forkit wrote:

 > module test;
 > @safe

Does that make just the following definition @safe or the entire module 
@safe? Trying... Yes, I am right. To make the module safe, use the 
following syntax:

@safe:

 >      idArray.reserve(recordsNeeded);
[...]
 >             idArray ~= x; // NOTE: does NOT appear to register with
 > -profile=gc

Because you've already reserved enough memory above. Good.

 >      int[][int][] records;
 >      records.reserve(numRecords);

That's good for the array part. However...

 >          // NOTE: below does register with -profile=gc
 >          records ~= [ idArray[i] : valuesArray[i] ];

The right hand side is a freshly generated associative array. For every 
element of 'records', there is a one-element AA created. AA will need to 
allocate memory for its element. So, GC allocation is expected there.

 >      string[] formattedRecords;
 >      formattedRecords.reserve(recArray.length);
[...]
 >          // NOTE: below does register with -profile=gc
 >          formattedRecords ~= id.to!string ~ values.format!"%(%s,%)";

Again, although 'formattedRecords' has reserved memory, the right hand 
side has dynamic memory allocations.

1) id.to!string allocates

2) format allocates memory for its 'string' result (I think the Appender 
report comes from format's internals.)

3) Operator ~ makes a new string from the previous two

(Somehow, I don't see three allocations though. Perhaps an NRVO is 
applied there. (?))

I like the following better, which reduces the allocations:

         formattedRecords ~= format!"%s%(%s,%)"(id.to!string, values);

 >      foreach(ref rec; formattedRecords)
 >          file.writeln(rec);

The bigger question is, why did 'formattedRecords' exist at all? You 
could have written the output directly to the file. But even *worse* and 
with apologies, ;) here is something crazy that achieves the same thing:

void ProcessRecords
(in int[][int][] recArray, const(string) fname)
{
     import std.algorithm : joiner;
     auto toWrite = recArray.map!(e => e.byPair);
     File("rnd_records.txt", 
"w").writefln!"%(%(%(%s,%(%s,%)%)%)\n%)"(toWrite);
}

I've done lot's of trial and error for the required number of nested %( 
%) pairs. Phew...

Ali



More information about the Digitalmars-d-learn mailing list