Re: automate tuple creation
On Friday, 21 January 2022 at 04:08:33 UTC, forkit wrote: // -- void ProcessRecords (in int[][int][] recArray, const(string) fname) { auto file = File(fname, "w"); scope(exit) file.close; Appender!string bigString = appender!string; bigString.reserve(recArray.length); debug { writefln("bigString.capacity is %s", bigString.capacity); } void processRecord(const(int) id, const(int)[] values) { bigString ~= id.to!string ~ values.format!"%(%s,%)" ~ "\n"; } foreach(ref const record; recArray) { foreach (ref rp; record.byPair) { processRecord(rp.expand); } } file.write(bigString[]); } // --- actually something not right with Appender I think... 100_000 records took 20sec (ok) 1_000_000 records never finished - after 1hr/45min I cancelled the process. ??
Re: automate tuple creation
On Friday, 21 January 2022 at 03:57:01 UTC, H. S. Teoh wrote: std.array.appender is your friend. T :-) // -- void ProcessRecords (in int[][int][] recArray, const(string) fname) { auto file = File(fname, "w"); scope(exit) file.close; Appender!string bigString = appender!string; bigString.reserve(recArray.length); debug { writefln("bigString.capacity is %s", bigString.capacity); } void processRecord(const(int) id, const(int)[] values) { bigString ~= id.to!string ~ values.format!"%(%s,%)" ~ "\n"; } foreach(ref const record; recArray) { foreach (ref rp; record.byPair) { processRecord(rp.expand); } } file.write(bigString[]); } // ---
Re: automate tuple creation
On Fri, Jan 21, 2022 at 03:50:37AM +, forkit via Digitalmars-d-learn wrote: [...] > I might have to use a kindof stringbuilder instead, then write a > massive string once to the file. [...] std.array.appender is your friend. T -- Meat: euphemism for dead animal. -- Flora
Re: automate tuple creation
On Friday, 21 January 2022 at 03:45:08 UTC, forkit wrote: On Friday, 21 January 2022 at 02:30:35 UTC, Ali Çehreli wrote: The bigger question is, why did 'formattedRecords' exist at all? You could have written the output directly to the file. Oh. this was intentional, as I wanted to write once, and only once, to the file. oops. looking back at that code, it seems I didn't write what i intended :-( I might have to use a kindof stringbuilder instead, then write a massive string once to the file. similar to C#: File.WriteAllText(Path, finalString);
Re: automate tuple creation
On Friday, 21 January 2022 at 02:30:35 UTC, Ali Çehreli wrote: The bigger question is, why did 'formattedRecords' exist at all? You could have written the output directly to the file. Oh. this was intentional, as I wanted to write once, and only once, to the file. The consequence of that decision of course, is the extra memory allocations... But in my example code I only create 10 records. In reality, my dataset will have 100,000's of records, so I don't want to write 100,000s of time to the same 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 Yes, that does look worse ;-) But I'm looking into that code to see if I can salvage something from it ;-)
Re: -debug question
On Friday, 21 January 2022 at 02:10:34 UTC, Steven Schveighoffer wrote: thanks Steven (and Ali too).
Re: -debug question
On 1/20/22 18:07, forkit wrote: I have a line of code, that I do NOT want executed when -debug is passed in. enforce(!exists(fname), "Oop! That file already exists!"); Is this even possible? (with using -version ..) The following should do it: debug {} else { foo(); } Ali
Re: automate tuple creation
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
Re: -debug question
On 1/20/22 9:07 PM, forkit wrote: I have a line of code, that I do NOT want executed when -debug is passed in. enforce(!exists(fname), "Oop! That file already exists!"); Is this even possible? (with using -version ..) `debug` is like a `version` block. ```d debug {} else { // code that runs when -debug is not present } ``` -Steve
-debug question
I have a line of code, that I do NOT want executed when -debug is passed in. enforce(!exists(fname), "Oop! That file already exists!"); Is this even possible? (with using -version ..)
Re: automate tuple creation
On Friday, 21 January 2022 at 01:35:40 UTC, forkit wrote: oops. nasty mistake to make ;-) module test; @safe should be: module test; @safe:
Re: automate tuple creation
On Thursday, 20 January 2022 at 23:49:59 UTC, Ali Çehreli wrote: so here is final code, in idiomatic D, as far as I can tell ;-) curious output when using -profile=gc .. a line referring to: std.array.Appender!(immutable(char)[]).Appender.Data std.array.Appender!string.Appender.this C:\D\dmd2\windows\bin\..\..\src\phobos\std\array.d:3330 That's not real helpful, as I'm not sure what line of my code its referrring to. // --- /+ = This program create a sample dataset consisting of 'random' records, and then outputs that dataset to a file. Arguments can be passed on the command line, or otherwise default values are used instead. Example of that output can be seen at the end of this code. = +/ module test; @safe import std.stdio : write, writef, writeln, writefln; import std.range : iota; import std.array : array, byPair; import std.random : Random, unpredictableSeed, dice, choice, uniform; import std.algorithm : map, uniq, canFind; import std.conv : to; import std.stdio : File; import std.format; debug { import std; } Random rnd; static this() { rnd = Random(unpredictableSeed); } // thanks Ali void main(string[] args) { int recordsNeeded, valuesPerRecord; string fname; if(args.length < 4) { recordsNeeded = 10; valuesPerRecord= 8; fname = "D:/rnd_records.txt"; } else { // assumes valid values being passed in ;-) recordsNeeded = to!int(args[1]); valuesPerRecord = to!int(args[2]); fname = args[3]; } int[] idArray; createUniqueIDArray(idArray, recordsNeeded); int[][] valuesArray; createValuesArray(valuesArray, recordsNeeded, valuesPerRecord); int[][int][] records = CreateDataSet(idArray, valuesArray, recordsNeeded); ProcessRecords(records, fname); writefln("All done. Check if records written to %s", fname); } void createUniqueIDArray (ref int[] idArray, const(int) recordsNeeded) { idArray.reserve(recordsNeeded); debug { writefln("idArray.capacity is %s", idArray.capacity); } int i = 0; int x; while(i != recordsNeeded) { // id needs to be 9 digits, and needs to start with 999 x = uniform(999*10^^6, 10^^9); // thanks Stanislav // ensure every id added is unique. if (!idArray.canFind(x)) { idArray ~= x; // NOTE: does NOT appear to register with -profile=gc i++; } } } void createValuesArray (ref int[][] valuesArray, const(int) recordsNeeded, const(int) valuesPerRecord) { valuesArray = iota(recordsNeeded) .map!(i => iota(valuesPerRecord) .map!(valuesPerRecord => cast(int)rnd.dice(0.6, 1.4)) .array).array; // NOTE: does register with -profile=gc } int[][int][] CreateDataSet (const(int)[] idArray, int[][] valuesArray, const(int) numRecords) { int[][int][] records; records.reserve(numRecords); debug { writefln("records.capacity is %s", records.capacity); } foreach(i, const id; idArray) { // NOTE: below does register with -profile=gc records ~= [ idArray[i] : valuesArray[i] ]; } return records.dup; } void ProcessRecords (in int[][int][] recArray, const(string) fname) { auto file = File(fname, "w"); scope(exit) file.close; string[] formattedRecords; formattedRecords.reserve(recArray.length); debug { writefln("formattedRecords.capacity is %s", formattedRecords.capacity); } void processRecord(const(int) id, const(int)[] values) { // NOTE: below does register with -profile=gc formattedRecords ~= id.to!string ~ values.format!"%(%s,%)"; } foreach(ref const record; recArray) { foreach (ref rp; record.byPair) { processRecord(rp.expand); } } foreach(ref rec; formattedRecords) file.writeln(rec); } /+ sample file output: 9992511730,1,0,1,0,1,0,1 9995369731,1,1,1,1,1,1,1 9993136031,1,0,0,0,1,0,0 9998979051,1,1,1,1,0,1,1 9998438090,1,1,0,1,1,0,0 9995132750,0,0,1,0,1,1,1 9997123630,0,1,1,1,0,1,1 9998351590,1,0,0,1,1,1,1 9991454121,1,1,1,1,1,0,1 9997673520,1,1,1,1,1,1,1 +/ // ---
Re: automate tuple creation
On 1/20/22 6:01 PM, forkit wrote: On Thursday, 20 January 2022 at 22:31:17 UTC, Steven Schveighoffer wrote: Because it would allow altering const data. I'm not sure I understand. At what point in this function is valuesArray modified, and thus preventing it being passed in with const? The compiler rules aren't enforced based on what code you wrote, it doesn't have the capability of proving that your code doesn't modify things. Instead, it enforces simple rules that allow prove that const data cannot be modified. I'll make it into a simpler example: ```d const int[] arr = [1, 2, 3, 4 5]; int[] arr2 = arr; ``` This code does not modify any data in arr. But that in itself isn't easy to prove. In order to ensure that arr is never modified, the compiler would have to analyze all the code, and every possible way that arr2 might escape or be used somewhere at some point to modify the data. It doesn't have the capability or time to do that (if I understand correctly, this is NP-hard). Instead, it just says, you can't convert references from const to mutable without a cast. That guarantees that you can't modify const data. However, it does rule out a certain class of code that might not modify the const data, even if it has the opportunity to. It's like saying, "we don't let babies play with sharp knives" vs. "we will let babies play with sharp knives but stop them just before they stab themselves." -Steve
Re: automate tuple creation
On 1/20/22 15:10, Ali Çehreli wrote: > void foo(const int[]) {} // Idiomatic As H. S. Teoh would add at this point, that is not idiomatic but the following are (with different meanings): void foo(const(int)[]) {} // Idiomatic void foo(const(int[])) {} // Idiomatic > void foo(in int[]) {} // Intentful :) I still like that one. :) Ali
Re: automate tuple creation
On 1/20/22 15:01, forkit wrote: > On Thursday, 20 January 2022 at 22:31:17 UTC, Steven Schveighoffer wrote: >> >> Because it would allow altering const data. >> > > I'm not sure I understand. At what point in this function is valuesArray > modified, and thus preventing it being passed in with const? > > // --- > > int[][int][] CreateDataSet > ref const int[] idArray, ref int[][] valuesArray, const int numRecords) > { > int[][int][] records; Elements of records are mutable. > records.reserve(numRecords); > > foreach(i, const id; idArray) > records ~= [ idArray[i] : valuesArray[i] ]; If that were allowed, you could mutate elements of record and would break the promise to your caller. Aside: There is no reason to pass arrays and associative arrays as 'ref const' in D as they are already reference types. Unlike C++, there is no copying of the elements. When you pass by value, just a couple of fundamental types are copied. Furthermore and in theory, there may be a performance penalty when an array is passed by reference because elements would be accessed by dereferencing twice: Once for the parameter reference and once for the .ptr property of the array. (This is in theory.) void foo(ref const int[]) {} // Unnecessary void foo(const int[]) {} // Idiomatic void foo(in int[]) {} // Intentful :) Passing arrays by reference makes sense when the function will mutate the argument. Ali
Re: automate tuple creation
On Thursday, 20 January 2022 at 22:31:17 UTC, Steven Schveighoffer wrote: Because it would allow altering const data. I'm not sure I understand. At what point in this function is valuesArray modified, and thus preventing it being passed in with const? // --- int[][int][] CreateDataSet ref const int[] idArray, ref int[][] valuesArray, const int numRecords) { int[][int][] records; records.reserve(numRecords); foreach(i, const id; idArray) records ~= [ idArray[i] : valuesArray[i] ]; return records.dup; } //
Re: automate tuple creation
On 1/20/22 5:07 PM, forkit wrote: On Thursday, 20 January 2022 at 21:16:46 UTC, forkit wrote: Cannot work out why I cannot pass valuesArray in as ref const?? get error: Error: cannot append type `const(int[])[const(int)]` to type `int[][int][]` Because it would allow altering const data. e.g.: ```d const(int[])[const(int)] v = [1: [1, 2, 3]]; int[][int][] arr = [v]; // assume this works arr[0][1][0] = 5; // oops, just set v[1][0] ``` General rule of thumb is that you can convert the HEAD of a structure to mutable from const, but not the TAIL (the stuff it points at). An associative array is a pointer-to-implementation construct, so it's a reference. -Steve
Re: automate tuple creation
On Thursday, 20 January 2022 at 21:16:46 UTC, forkit wrote: Cannot work out why I cannot pass valuesArray in as ref const?? get error: Error: cannot append type `const(int[])[const(int)]` to type `int[][int][]` // -- int[][int][] CreateDataSet(ref const int[] idArray, ref const(int[][]) valuesArray, const int numRecords) { int[][int][] records; records.reserve(numRecords); foreach(i, id; idArray) records ~= [ idArray[i] : valuesArray[i] ]; return records.dup; } // ---
Re: automate tuple creation
On Thursday, 20 January 2022 at 12:40:09 UTC, Stanislav Blinov wrote: Allocating 4 megs to generate 10 numbers??? You can generate a random number between 99900 and 10. ... // id needs to be 9 digits, and needs to start with 999 x = uniform(999*10^^6, 10^^9); // ensure every id added is unique. if (!result[0 .. i].canFind(x)) result[i++] = x; } import std.exception : assumeUnique; return result.assumeUnique; ... Nice. Thanks. I had to compromise a little though, as assumUnique is @system, and all my code is @safe (and trying to avoid the need for inline @system wrapper ;-) //--- void createUniqueIDArray(ref int[] idArray, int recordsNeeded) { idArray.reserve(recordsNeeded); debug { writefln("idArray.capacity is %s", idArray.capacity); } int i = 0; int x; while(i != recordsNeeded) { // generate a random 9 digit id that starts with 999 x = uniform(999*10^^6, 10^^9); // thanks Stanislav! // ensure every id added is unique. if (!idArray.canFind(x)) { idArray ~= x; // NOTE: does NOT register with -profile=gc i++; } } } //---
Re: Meaning of in, out and inout
On 1/20/22 8:28 AM, Paul Backus wrote: The explanation you quoted is from 2005, and `inout` does not mean the same thing in 2022 as it did in 2005. The current meaning of inout is explained in the D language specification on dlang.org. Here is a link to the relevant section: https://dlang.org/spec/function.html#inout-functions Note that in 2005, D2 did not exist, `inout` in D1 used to mean what `ref` now means in D2. So if you are looking for that specific meaning, use `ref`. -Steve
Re: Trying to cross compile from windows to android
On Thu, Jan 20, 2022 at 07:10:40PM +, Jerry via Digitalmars-d-learn wrote: > Hello, followed the guide at https://wiki.dlang.org/Build_D_for_Android > but got stuck on figuring out what linker to use. > > "../ldc_android/ldc/bin/ldc2.exe" -mtriple=armv7a--linux-andro > ideabi main.d > clang: error: invalid linker name in argument '-fuse-ld=bfd' > Error: ldc_android/android_ndk/toolchains/llvm/prebuilt/windows-x86_64/bin > /aarch64-linux-android21-clang.cmd failed with status: 1 > > Do I need to install a GNU linker with cross compile compatabilities or is > my system not configured properly? You're trying to use bfd as your linker, and I think that only exists on the Linux version of the NDK. Maybe try looking somewhere under ldc_android/android_ndk/toolchains/x86_64-*/prebuilt/windows-x86_64/bin to see what linkers are shipped with your NDK, and specify that instead? On Linux, I see a bunch of binaries named x86_64-linux-android-*, including *-ld, *-ld.bfd, *-ld.gold, which are the 3 linkers that can be used via -fuse-ld=bfd, -fuse-ld=gold, etc.. I'm not sure how it works on Windows, but there should be corresponding binaries that might give a hint as to what's the correct -fuse-ld=... option you need to use. T -- Famous last words: I *think* this will work...
Trying to cross compile from windows to android
Hello, followed the guide at https://wiki.dlang.org/Build_D_for_Android but got stuck on figuring out what linker to use. "../ldc_android/ldc/bin/ldc2.exe" -mtriple=armv7a--linux-andro ideabi main.d clang: error: invalid linker name in argument '-fuse-ld=bfd' Error: ldc_android/android_ndk/toolchains/llvm/prebuilt/windows-x86_64/bin /aarch64-linux-android21-clang.cmd failed with status: 1 Do I need to install a GNU linker with cross compile compatabilities or is my system not configured properly?
Re: number ranges
On 1/19/22 21:24, Salih Dincer wrote: > ```d >size_t length() inout { > //return last_ - first_ + 1 - empty_;/* > auto len = 1 + last_ - first_; > return cast(size_t)len;//*/ >} > ``` Good catch but we can't ignore '- empty_'. Otherwise an empty range will return 1. > But it only works on integers. After fixing the size_t issue, it should work on user-defined types as well. In fact, it is better to leave the return type as auto so that it works with user-defined types that support the length expression but is a different type like e.g. MyDiffType. Having said that, floating point types don't make sense with the semantics of a *bidirectional and inclusive* range. :) Let's see how it looks for ranges where the step size is 0.3: import std.stdio; void main() { float beg = 0.0; float end = 1.0; float step = 0.3; writeln("\nIncrementing:"); for (float f = beg; f <= end; f += step) { report(f); } writeln("\nDecrementing:"); for (float f = end; f >= beg; f -= step) { report(f); } } void report(float f) { writefln!"%.16f"(f); } Here is the output: Incrementing: 0. 0.300119209290 0.600238418579 0.900357627869 <-- Where is 1.0? Decrementing: 1. 0.699880790710 0.399761581421 0.099642372131 <-- Where is 0.0? So if we add the 1.0 value after 0.900357627869 to be *inclusive*, then that last step would not be 0.3 anymore. (Thinking about it, step would mess up things for integral types as well; so, it must be checked during construction.) The other obvious issue in the output is that a floating point iota cannot be bidirectional because the element values would be different. Ali
Re: Meaning of in, out and inout
On Thursday, 20 January 2022 at 13:28:54 UTC, Paul Backus wrote: On Thursday, 20 January 2022 at 13:19:06 UTC, Sergey wrote: [...] The explanation you quoted is from 2005, and `inout` does not mean the same thing in 2022 as it did in 2005. The current meaning of inout is explained in the D language specification on dlang.org. Here is a link to the relevant section: https://dlang.org/spec/function.html#inout-functions Thanks a lot.
Re: How to alias
On Friday, 14 January 2022 at 17:48:41 UTC, kyle wrote: ```d void main() { import std.stdio; Broke foo = Broke(10); Broke bar = Broke(20); writeln(foo + 15); //prints 25 as expected writeln(foo + bar); //prints 20 } ``` I guess what you want to do is something like this: ```d struct Broke { double num; Broke opBinary(string op)(Broke rhs) if(op == "+") { return Broke(this.num + rhs.num);/* this.num += rhs.num; return this;//*option 2*/ } Broke opBinary(string op)(double rhs) if(op == "+") { return Broke(this.num + rhs);/* this.num += rhs; return this;//*option 2*/ } } void main() { import std.stdio; Broke foo = Broke(5); Broke bar = Broke(15); bar = foo + bar;// #1 bar == Broke(20) writeln(foo + 15); // #2 print ok => 20 writeln(foo + bar); // #3 print ok => 25 } ``` So you don't need to use alias. If you want it the other way (option 2), turn off option 1 then option 2 will open automatically. Thus, same Broke() gets values: 20, 35 and 55. regards, - Salih
Re: Meaning of in, out and inout
On Thursday, 20 January 2022 at 13:19:06 UTC, Sergey wrote: https://forum.dlang.org/post/17nwtnp4are5q$.1ddtvmj4e23iy@40tude.net On Tuesday, 10 May 2005 at 01:06:14 UTC, Derek Parnell wrote: [...] Thanks a lot for your explanation. I started to learn D language recently and I have trouble with understanding some part of language. I do your example on Linux and it works very well, especially func_rthee(). when I try to repeat code on Windows 10, I get errors: Error: cannot modify `inout` expression `X[0]` Error: cannot modify `inout` expression `X` Error: cannot modify `inout` expression `Y` Error: cannot modify `inout` expression `Y` Very strange situation for me. I expect next behavior of the parameters X and Y could get value and could change it on Windows but now I am not sure what is goin on. PS. I am using DMD64 D Compiler v2.098.1-dirty on Debian 10 Linux and Windows 10. The explanation you quoted is from 2005, and `inout` does not mean the same thing in 2022 as it did in 2005. The current meaning of inout is explained in the D language specification on dlang.org. Here is a link to the relevant section: https://dlang.org/spec/function.html#inout-functions
Meaning of in, out and inout
https://forum.dlang.org/post/17nwtnp4are5q$.1ddtvmj4e23iy@40tude.net On Tuesday, 10 May 2005 at 01:06:14 UTC, Derek Parnell wrote: On Tue, 10 May 2005 00:30:57 + (UTC), Oliver wrote: Hello D-ers The documentation is very short on the keywords in, out and inout. Is is inout sth like a reference ? But then, what is in and what is out? in: The argument is preserved, such that when control returns to the caller, the argument as passed by the caller is unchanged. This means that the called function can do anything it likes to the argument but those changes are never returned back to the caller. There is a bit of confusion here when it comes to passing class objects and dynamic arrays. In both these cases, a reference to the data is passed. Which means that for 'in' references, the called function is free to modify the reference data (which is what is actually passed) in the full knowledge that any changes will *not* be returned to the caller. However, if you make any changes to the data being referenced, that modified data is 'returned'. Which means that, for example, if you pass a char[] variable, the reference will be preserved but the data in the string can be changed. out: The argument is always initialized automatically by the called function before its code is executed. Any changes to the argument by the called function are returned to the caller. The called function never gets to see the value of the argument as it was before the called function gets control. The argument must a RAM item and not a literal or temporary value. inout: The argument is passed to the called function without before its code is executed. Any changes to the argument by the called function are returned to the caller. In other words, the called function can see what value was passed to it before changing it. The argument must a RAM item and not a literal or temporary value. Examples: char[] a; intb; void func_one(in char[] X, in int Y) { X[0] = 'a'; // Modifies the string contents. X = "zxcvb"; // Modifies the string reference but is not returned. Y = 3; // Modifies the data but is not returned. } a = "qwerty"; b = 1; func_one(a,b); writefln("%s %d", a,b); // --> awerty 1 void func_two(out char[] X, out int Y) { X[0] = 'a'; // Modifies the string contents. X = "zxcvb"; // Modifies the string reference. if (b == 1) Y = 3; // never executed because Y is always zero on entry. else Y = 4; // Modifies the data. } a = "qwerty"; b = 1; func_two(a,b); writefln("%s %d", a,b); // --> zxcvb 4 void func_three(inout char[] X, inout int Y) { X[0] = 'a'; // Modifies the string contents. X = "zxcvb"; // Modifies the string reference. if (b == 1) Y = 3; // Modifies the data. else Y = 4; // Modifies the data. } a = "qwerty"; b = 1; func_two(a,b); writefln("%s %d", a,b); // --> zxcvb 3 Thanks a lot for your explanation. I started to learn D language recently and I have trouble with understanding some part of language. I do your example on Linux and it works very well, especially func_rthee(). when I try to repeat code on Windows 10, I get errors: Error: cannot modify `inout` expression `X[0]` Error: cannot modify `inout` expression `X` Error: cannot modify `inout` expression `Y` Error: cannot modify `inout` expression `Y` Very strange situation for me. I expect next behavior of the parameters X and Y could get value and could change it on Windows but now I am not sure what is goin on. PS. I am using DMD64 D Compiler v2.098.1-dirty on Debian 10 Linux and Windows 10.
Re: automate tuple creation
On Thursday, 20 January 2022 at 12:15:56 UTC, forkit wrote: void createUniqueIDArray(ref int[] idArray, int recordsNeeded) { idArray.reserve(recordsNeeded); debug { writefln("idArray.capacity is %s", idArray.capacity); } // id needs to be 9 digits, and needs to start with 999 // below will contain 1_000_000 records that we can choose from. int[] ids = iota(999_000_000, 1_000_000_000).array; // NOTE: does NOT register with -profile=gc int i = 0; int x; while(i != recordsNeeded) { x = ids.choice(rnd); // ensure every id added is unique. if (!idArray.canFind(x)) { idArray ~= x; // NOTE: does NOT register with -profile=gc i++; } } } Allocating 4 megs to generate 10 numbers??? You can generate a random number between 99900 and 10. ``` immutable(int)[] createUniqueIDArray(int recordsNeeded) { import std.random; import std.algorithm.searching : canFind; int[] result = new int[recordsNeeded]; int i = 0; int x; while(i != recordsNeeded) { // id needs to be 9 digits, and needs to start with 999 x = uniform(999*10^^6, 10^^9); // ensure every id added is unique. if (!result[0 .. i].canFind(x)) result[i++] = x; } import std.exception : assumeUnique; return result.assumeUnique; } void main() { import std.stdio; createUniqueIDArray(10).writeln; } ``` Only one allocation, and it would be tracked with -profile=gc...
Re: automate tuple creation
On Thursday, 20 January 2022 at 10:11:10 UTC, bauss wrote: Don't make them random then, but use an incrementor. If you can have ids that aren't integers then you could use uuids too. https://dlang.org/phobos/std_uuid.html The 'uniqueness' of id would actually be created in the database. I just creating a dataset to simulate an export. I'm pretty much done, just wish -profile=gc was working in createUniqueIDArray(..) // --- module test; @safe: import std.stdio : write, writef, writeln, writefln; import std.range : iota, isForwardRange, hasSlicing, hasLength, isInfinite; import std.array : array, byPair; import std.random : Random, unpredictableSeed, dice, choice; import std.algorithm : map, uniq, canFind; debug { import std; } Random rnd; static this() { rnd = Random(unpredictableSeed); } void main() { const int recordsNeeded = 10; const int valuesPerRecord = 8; int[] idArray; createUniqueIDArray(idArray, recordsNeeded); int[][] valuesArray; createValuesArray(valuesArray, recordsNeeded, valuesPerRecord); int[][int][] records = CreateDataSet(idArray, valuesArray, recordsNeeded); ProcessRecords(records); } void ProcessRecords(ref const(int[][int][]) recArray) { void processRecord(ref int id, ref const(int)[] result) { writef("%s\t%s", id, result); } foreach(ref record; recArray) { foreach (ref rp; record.byPair) { processRecord(rp.expand); } writeln; } } int[][int][] CreateDataSet(ref int[] idArray, ref int[][] valuesArray, int numRecords) { int[][int][] records; records.reserve(numRecords); debug { writefln("records.capacity is %s", records.capacity); } foreach(i, id; idArray) records ~= [ idArray[i] : valuesArray[i] ]; // NOTE: does register with -profile=gc return records.dup; } void createValuesArray(ref int[][] m, size_t recordsNeeded, size_t valuesPerRecord) { m = iota(recordsNeeded) .map!(i => iota(valuesPerRecord) .map!(valuesPerRecord => cast(int)rnd.dice(0.6, 1.4)) .array).array; // NOTE: does register with -profile=gc } void createUniqueIDArray(ref int[] idArray, int recordsNeeded) { idArray.reserve(recordsNeeded); debug { writefln("idArray.capacity is %s", idArray.capacity); } // id needs to be 9 digits, and needs to start with 999 // below will contain 1_000_000 records that we can choose from. int[] ids = iota(999_000_000, 1_000_000_000).array; // NOTE: does NOT register with -profile=gc int i = 0; int x; while(i != recordsNeeded) { x = ids.choice(rnd); // ensure every id added is unique. if (!idArray.canFind(x)) { idArray ~= x; // NOTE: does NOT register with -profile=gc i++; } } } /+ sample output: 999623777 [0, 0, 1, 1, 1, 0, 0, 0] 999017078 [1, 0, 1, 1, 1, 1, 1, 1] 999269073 [1, 1, 0, 0, 1, 1, 0, 1] 999408504 [0, 1, 1, 1, 1, 1, 0, 0] 999752314 [1, 0, 0, 1, 1, 1, 1, 0] 999660730 [0, 1, 0, 0, 1, 1, 1, 1] 999709822 [1, 1, 1, 0, 1, 1, 0, 0] 999642248 [1, 1, 1, 0, 0, 1, 1, 0] 999533069 [1, 1, 1, 0, 0, 0, 0, 0] 999661591 [1, 1, 1, 1, 1, 0, 1, 1] +/ // ---
Re: automate tuple creation
On Thursday, 20 January 2022 at 04:00:59 UTC, forkit wrote: On Thursday, 20 January 2022 at 00:30:44 UTC, H. S. Teoh wrote: Do the id's have to be unique? yep... Don't make them random then, but use an incrementor. If you can have ids that aren't integers then you could use uuids too. https://dlang.org/phobos/std_uuid.html