January 21, 2022
On Friday, 21 January 2022 at 21:01:11 UTC, forkit wrote:
>

even better, I got rid of all those uncessary arrays ;-)

// ---

int[][int][] CreateDataSet
(const(int) recordsNeeded, const(int)valuesPerRecord)
{
    int[][int][] records;
    records.reserve(recordsNeeded);

    foreach(i, id; iota(iotaStartNum, iotaStartNum + recordsNeeded).enumerate)
    {
        records ~= [ id: iota(valuesPerRecord).map!(valuesPerRecord => cast(int)rnd.dice(0.6, 1.4)).array ];
    }

    return records.dup;
}

// ---

January 21, 2022
On Friday, 21 January 2022 at 21:43:38 UTC, forkit wrote:
>

oops... should be:

// ---

int[][int][] CreateDataSet
(const(int) recordsNeeded, const(int)valuesPerRecord)
{
    int[][int][] records;
    records.reserve(recordsNeeded);

    const int iotaStartNum = 100_000_001;

    foreach(i, id; iota(iotaStartNum, iotaStartNum + recordsNeeded).enumerate)
    {
        records ~= [ id: iota(valuesPerRecord).map!(valuesPerRecord => cast(int)rnd.dice(0.6, 1.4)).array ];
    }

    return records.dup;
}

// ---


January 21, 2022
On Fri, Jan 21, 2022 at 09:43:38PM +0000, forkit via Digitalmars-d-learn wrote:
> On Friday, 21 January 2022 at 21:01:11 UTC, forkit wrote:
[...]
> even better, I got rid of all those uncessary arrays ;-)
> 
> // ---
> 
> int[][int][] CreateDataSet
> (const(int) recordsNeeded, const(int)valuesPerRecord)
> {
>     int[][int][] records;
>     records.reserve(recordsNeeded);
> 
>     foreach(i, id; iota(iotaStartNum, iotaStartNum +
> recordsNeeded).enumerate)
>     {
>         records ~= [ id: iota(valuesPerRecord).map!(valuesPerRecord =>
> cast(int)rnd.dice(0.6, 1.4)).array ];
>     }
> 
>     return records.dup;

What's the point of calling .dup here?  The only reference to records is going out of scope, so why can't you just return it?  The .dup is just creating extra work for nothing.


T

-- 
Unix was not designed to stop people from doing stupid things, because that would also stop them from doing clever things. -- Doug Gwyn
January 21, 2022
On Friday, 21 January 2022 at 21:56:33 UTC, H. S. Teoh wrote:
>
> What's the point of calling .dup here?  The only reference to records is going out of scope, so why can't you just return it?  The .dup is just creating extra work for nothing.
>
>
> T

good pickup. thanks ;-)

// ----

module test;
@safe:

import std.stdio : write, writef, writeln, writefln;
import std.range : iota, enumerate;
import std.array : array, byPair, Appender, appender;
import std.random : Random, unpredictableSeed, dice, randomCover;
import std.algorithm : map;
import std.conv : to;
import std.format;
import std.stdio : File;
import std.file : exists;
import std.exception : enforce;

debug { import std; }

Random rnd;
static this() {  rnd = Random(unpredictableSeed); }

void main(string[] args)
{
    int recordsNeeded, valuesPerRecord;
    string fname;

    if(args.length < 4)
    {
        recordsNeeded = 10; // default
        valuesPerRecord= 8; // default

        fname = "D:/rnd_records.txt"; // default
        //fname = "./rnd_records.txt"; // default
    }
    else
    {
        // assumes valid values being passed in ;-)
        recordsNeeded = to!int(args[1]);
        valuesPerRecord = to!int(args[2]);
        fname = args[3];
    }

    debug
        { writefln("%s records, %s values for record, will be written to file: %s", recordsNeeded, valuesPerRecord, fname); }
    else
        {
            enforce(!exists(fname), "Oop! That file already exists!");
            enforce(recordsNeeded <= 1_000_000_000, "C'mon! That's too many records!");
        }

    int[][int][] records = CreateDataSet(recordsNeeded, valuesPerRecord);

    ProcessDataSet(records, fname);

    writefln("All done. Check if records written to %s", fname);
}

int[][int][] CreateDataSet
(const(int) recordsNeeded, const(int) valuesPerRecord)
{
    const int iotaStartNum = 100_000_001;

    int[][int][] records;
    records.reserve(recordsNeeded);
    debug { writefln("records.capacity is %s", records.capacity); }

    foreach(i, id; iota(iotaStartNum, iotaStartNum + recordsNeeded).enumerate)
    {
        // NOTE: below does register with -profile=gc
        records ~= [ id: iota(valuesPerRecord).map!(valuesPerRecord => cast(int)rnd.dice(0.6, 1.4)).array ];
    }

    debug { writefln("records.length = %s", records.length); }
    return records;
}

// this creates a big string of 'formatted' records, and outputs that string to a file.
void ProcessDataSet
(in int[][int][] records, const(string) fname)
{
    auto file = File(fname, "w");
    scope(exit) file.close;

    Appender!string bigString = appender!string;
    bigString.reserve(records.length);
    debug { writefln("bigString.capacity is %s", bigString.capacity); }

    // NOTE: forward declaration required for this nested function
    void processRecord(const(int) id, const(int)[] values)
    {
        bigString ~= id.to!string ~ "," ~ values.format!"%(%s,%)" ~ "\n";
    }

    foreach(ref const record; records)
    {
        foreach (ref rp; record.byPair)
        {
            processRecord(rp.expand);
        }
    }

    debug { writeln; writeln(bigString[].until("\n")); writeln; } // display just one record

    file.write(bigString[]);
}
// ----


January 21, 2022
On Friday, 21 January 2022 at 22:25:32 UTC, forkit wrote:
>

I really like how alias and mixin can simplify my code even further:

//---

int[][int][] CreateDataSet
(const(int) recordsNeeded, const(int) valuesPerRecord)
{
    int[][int][] records;
    records.reserve(recordsNeeded);

    const int iotaStartNum = 100_000_001;
    alias iotaValues = Alias!"iota(iotaStartNum, iotaStartNum + recordsNeeded).enumerate";
    alias recordValues = Alias!"iota(valuesPerRecord).map!(valuesPerRecord => cast(int)rnd.dice(0.6, 1.4)).array";

    foreach(i, id; mixin(iotaValues))
    {
        records ~= [ id: mixin(recordValues) ];
    }

    return records;
}

//---

January 21, 2022

On 1/21/22 6:24 PM, forkit wrote:

>

On Friday, 21 January 2022 at 22:25:32 UTC, forkit wrote:

>

I really like how alias and mixin can simplify my code even further:

//---

int[][int][] CreateDataSet
(const(int) recordsNeeded, const(int) valuesPerRecord)
{
    int[][int][] records;
    records.reserve(recordsNeeded);

    const int iotaStartNum = 100_000_001;
    alias iotaValues = Alias!"iota(iotaStartNum, iotaStartNum + recordsNeeded).enumerate";
    alias recordValues = Alias!"iota(valuesPerRecord).map!(valuesPerRecord => cast(int)rnd.dice(0.6, 1.4)).array";

oof! use enums for compile-time strings ;)

enum iotaValues = "iota(...";
>

    foreach(i, id; mixin(iotaValues))
    {
        records ~= [ id: mixin(recordValues) ];
    }

    return records;
}

Not sure I agree that the mixin looks better.

Also, I'm curious about this code:

iota(valuesPerRecord).map!(valuesPerRecord => cast(int)rnd.dice(0.6, 1.4)).array;

That second valuesPerRecord is not used in the lambda, and also it's not referring to the original element, it's the name of a parameter in the lambda.

Are you sure this is doing what you want?

-Steve

January 22, 2022
On Saturday, 22 January 2022 at 01:33:16 UTC, Steven Schveighoffer wrote:
>

so I why watching this video by Andrei:

https://www.youtube.com/watch?v=mCrVYYlFTrA

In it, he talked about writing the simplest design that could possibly work....

Which got me thinking....

// ----

module test;
@safe:

import std.stdio : write, writef, writeln, writefln;
import std.range : iota, enumerate;
import std.array : array, byPair, Appender, appender;
import std.random : Random, unpredictableSeed, dice, randomCover;
import std.algorithm : map;
import std.conv : to;
import std.format;
import std.stdio : File;
import std.file : exists;
import std.exception : enforce;
import std.meta : Alias;

debug { import std; }

Random rnd;
static this() {  rnd = Random(unpredictableSeed); }

void main(string[] args)
{
    int recordsNeeded, valuesPerRecord;

    string fname;

    if(args.length < 4) // then set defaults
    {
        recordsNeeded = 10;
        valuesPerRecord= 8;

        version(Windows) { fname = "D:/rnd_records.txt"; }
        version(linux) { fname = "./rnd_records.txt"; }
    }
    else
    {
        // assumes valid values being passed in ;-)
        recordsNeeded = to!int(args[1]);
        valuesPerRecord = to!int(args[2]);
        fname = args[3];
    }

    debug
        { writefln("%s records (where a record is: id and %s values), will be written to file: %s", recordsNeeded, valuesPerRecord, fname); }
    else
        {
            enforce(!exists(fname), "Oops! That file already exists!");
            enforce(recordsNeeded <= 1_000_000_000, "C'mon! That's too many records!");
        }

    CreateDataFile(recordsNeeded, valuesPerRecord, fname);

    writefln("All done. Check if records written to %s", fname);
}

void CreateDataFile(const(int) recordsNeeded, const(int) valuesPerRecord, const(string) fname)
{
    auto file = File(fname, "w");
    scope(exit) file.close;

    Appender!string bigString = appender!string;
    bigString.reserve(recordsNeeded);

    const int iotaStartNum = 100_000_001;

    foreach(i, id; iota(iotaStartNum, iotaStartNum + recordsNeeded).enumerate)
    {
        bigString
            ~= id.to!string
            ~ ","
            ~ valuesPerRecord.iota.map!(valuesPerRecord => cast(int)rnd.dice(0.6, 1.4)).format!"%(%s,%)"
            ~ "\n";
    }

    file.write(bigString[]);
}

// ----
January 22, 2022
On Saturday, 22 January 2022 at 01:33:16 UTC, Steven Schveighoffer wrote:
>
>
> That second `valuesPerRecord` is not used in the lambda, and also it's not referring to the original element, it's the name of a parameter in the lambda.
>
> Are you sure this is doing what you want?
>
> -Steve

It just worked, so i didn't think about it too much.. but it seems to work either way.

And to be honest, the only part of it I understand, is the dice part ;-)

In any case I changed it:

from: valuesPerRecord =>
to:  i =>

// ----

void CreateDataFile(const(int) recordsNeeded, const(int) valuesPerRecord, const(string) fname)
{
    auto rnd = Random(unpredictableSeed);

    auto file = File(fname, "w");
    scope(exit) file.close;

    Appender!string bigString = appender!string;
    bigString.reserve(recordsNeeded);

    const int iotaStartNum = 100_000_001;

    foreach(i, id; iota(iotaStartNum, iotaStartNum + recordsNeeded).enumerate)
    {
        bigString
            ~= id.to!string
            ~ ","
            ~ valuesPerRecord.iota.map!(i => rnd.dice(0.6, 1.4)).format!"%(%s,%)"
            ~ "\n";
    }

    file.write(bigString[]);
}

// ---
1 2 3 4 5
Next ›   Last »