Re: How to work with and load/save sparse compressed matrices? (numir, mir.sparse)
On Tuesday, 29 September 2020 at 04:52:11 UTC, Shaleen Chhabra wrote: I wish to use load / save for sparse compressed matrices using mir. import mir.sparse; auto sp = sparse!double(5, 8); auto crs = sp.compress; How can I save/load sparse compressed arrays in `npz` format? (format: ``csc``, ``csr``, ``bsr``, ``dia`` or coo``) Mir doesn't have I/O support for sparse tensors for now. how can i again decompress the compressed sparse array to dense? // http://mir-algorithm.libmir.org/mir_ndslice_allocation.html#.slice import mir.ndslice.allocation: slice; // for DOK: auto dense = slice(sp); For crs you may need to iterate with byCoordinateValue http://mir.libmir.org/mir_sparse.html#.byCoordinateValue and initialize the dense slice. To estimate the raw length one may need to iterate all rows and get the maximum of the last element indices. Thanks Shaleen
Re: QuickSort on ranges
On 10/4/20 6:50 AM, jerome wrote: Thanks you very much Ali, I will try to wrap my head around your inputs, and get a better understanding of ranges in the process. I feel there is a lot of power in D ranges, and like the hammer of Thor, I am not worthy yet :) Just to elaborate a bit further: Templates work by pattern matching. When you say quickSort(T)(T[] r) You are saying, match the parameter T[] to what is passed, and if it's a match, set T to the part of the parameter that matches. Therefore: int[] => T = int ubyte[] => T = ubyte But if you leave off the array brackets: quickSort(T)(T r) Now T matches *any type* that you pass in, including ranges. Most range functions use templates because there is no supertype for ranges. They are checked by trying to compile the range primitives on them. How you do more advanced checks other than pattern matching, is to use a template constraint, as Ali suggests. In fact, since you are just using std.algorithm.pivotPartition, you can just look at the constraints it uses: if (isRandomAccessRange!Range && hasLength!Range && hasSlicing!Range && hasAssignableElements!Range) -Steve
Re: Taking arguments by value or by reference
On Sunday, 4 October 2020 at 14:26:43 UTC, Anonymouse wrote: On Saturday, 3 October 2020 at 23:47:32 UTC, Max Haughton wrote: The guiding principle to your function parameters should be correctness - if I am passing a big struct around, if I want to take ownership of it I probably want to take it by value but if I want to modify it I should take it by reference (or by pointer but don't overcomplicate, notice in the previous example they lower to the same thing). If I just want to look at it, it should be taken by const ref if possible (D const isn't the same as C++ const, this may catch you out). Const-correctness is a rule to live by especially with an big unwieldy struct. I would avoid the new in for now, but I would go with const ref from what you've described so far. I mostly really only want a read-only view of the struct, and whether a copy was done or not is academic. However, profiling showed (what I interpret as) a lot of copying being done in release builds specifically. https://i.imgur.com/JJzh4Zc.jpg Naturally a situation where I need ref I'd use ref, and in the rare cases where it actually helps to have a mutable copy directly I take it mutable. But if I understand what you're saying, and ignoring --preview=in, you'd recommend I use const ref where I would otherwise use const? Is there some criteria I can go by when making this decision, or does it always reduce to looking at the disassembly? This is skill you only really hone with experience, but it's not too bad once you're used to it. For a big struct, I would just stick to expressing what you want it to *do* rather than how you want it to perform. If you want to take ownership you basically have to take by value, but if you (as you said) want a read only view definitely const ref. If I was reading your code, ref immediately tells me not to think about ownership and const ref immediately tells me you just want to look at the goods. One thing I haven't mentioned so far is that not all types have non-trivial semantics when it comes to passing them around by value, so if you are writing generic code it is often best to avoid these.
Re: Dub build failure
On Sunday, 4 October 2020 at 20:25:48 UTC, Andre Pany wrote: On Sunday, 4 October 2020 at 18:45:34 UTC, jerome wrote: I am trying to compile a simple lib, and a simple demo using this lib. [...] If I am not wrong there is following issue: in D a package is a folder. Having the package.d file as child of folder source is not correct. Moving the file package.d into folder source/dterrent/ should solve the issue. Kind regards Andre Hi Andre, your solution solved the problem. Thanks. Reading again the error message, with the solution at hand, I think your answer may be completed. I explain: The message was: source/app.d(9,8): Error: module dterrent is in file 'dterrent.d' which cannot be read I think dub looked for a dterrent.d file in registered paths. Then it also looked for a dterrent directory in paths, possibly verifying that a package.d file was present in that directory. Finding neither nor, it concluded that the module should have been in an eponymous dterrent.d file somewhere, and displayed that ambiguous error message. So it seems that dub does not parse any file looking for the line "module dterrent;" as I thought. It just looks for a file or directory named dterrent(.d) Maybe it also verify that an eponymous folder has a package.d, in this case we can say "a folder must have a normative package.d file". Maybe. Thanks again for your fast answer.
Re: dub fetching dependencies for wrong configuration(s)
On Sunday, 4 October 2020 at 20:08:31 UTC, Andre Pany wrote: On Sunday, 4 October 2020 at 14:08:24 UTC, Anonymouse wrote: At the moment the only chance to avoid these additional dependencies would be to split requests into 2 dub packages. The core package which uses std, and an additional package which is based on the core package and is using vibe-d. Kind regards Andre Thanks, Andre! I'll split requests as you suggested (increasing minor version, so that this change will not hurt anybody who build current requests package for vibe-d).
Re: Taking arguments by value or by reference
On Sunday, 4 October 2020 at 15:30:48 UTC, IGotD- wrote: I don't agree with this, especially if the struct is 432 bytes. It takes time and memory to copy such structure. If the compiler chooses to inline the function (which happens quite frequently with optimizations turned on), no copy takes place regardless of how you write it if the compiler can see it is unnecessary. Returning a struct by value rarely means a copy either since the compiler actually passed a pointer to where it wants it up front, so it is constructed in-place. So like "pass by value" in the language is not necessarily big copies in the generated binary. That's why the irc folks were advising to not worry about it unless you see a problem coming up that the profiles points here.
Re: Dub build failure
On Sunday, 4 October 2020 at 18:45:34 UTC, jerome wrote: I am trying to compile a simple lib, and a simple demo using this lib. [...] If I am not wrong there is following issue: in D a package is a folder. Having the package.d file as child of folder source is not correct. Moving the file package.d into folder source/dterrent/ should solve the issue. Kind regards Andre
Re: dub fetching dependencies for wrong configuration(s)
On Sunday, 4 October 2020 at 14:08:24 UTC, Anonymouse wrote: My project depends on the requests dub package, which has two build configurations; one with an extra vibe-d dependency, one without (default). "configurations": [ { "name": "std" }, { "name": "vibed", "versions": ["vibeD"], "dependencies": { "vibe-d": ">=0.8.0" } } ], I only ever use the default "std" configuration, but dub always pulls the additional multiple vibe-d dependencies, regardless of what I pick. Adding a subConfiguration restriction does not seem to help. $ dub upgrade Upgrading project in /home/zorael/src/kameloso Fetching vibe-core 1.10.2 (getting selected version)... Fetching memutils 1.0.4 (getting selected version)... Fetching taggedalgebraic 0.11.18 (getting selected version)... Fetching vibe-d 0.9.2 (getting selected version)... Fetching botan-math 1.0.3 (getting selected version)... Fetching stdx-allocator 2.77.5 (getting selected version)... Fetching botan 1.12.18 (getting selected version)... Fetching diet-ng 1.7.4 (getting selected version)... Fetching openssl 1.1.6+1.0.1g (getting selected version)... Fetching eventcore 0.9.9 (getting selected version)... Fetching mir-linux-kernel 1.0.1 (getting selected version)... Fetching libasync 0.8.6 (getting selected version)... Is there any way to stop this? The reasoning is explained here: https://github.com/dlang/dub/wiki/FAQ#why-are-dependencies-downloaded-that-belong-to-configurations-that-are-not-being-built While these dependencies are downloaded, they will not be part of your binary. At the moment the only chance to avoid these additional dependencies would be to split requests into 2 dub packages. The core package which uses std, and an additional package which is based on the core package and is using vibe-d. Kind regards Andre
Learn D while updating Rosetta code
Just a tip to everyone. If you're trying to learn D, you can try to implement some of these missing tasks and update the corresponding page: http://rosettacode.org/wiki/Reports:Tasks_not_implemented_in_D
Dub build failure
I am trying to compile a simple lib, and a simple demo using this lib. So I have 2 directories at the same level in the same DEV directory: demo1 Dterrent In the Dterrent directory, the dub.json is pretty common, compiling as a lib: "name": "dterrent", "targetPath": "libs", Inside Dterrent, I also have a regular "source" directory, which contains a package.d file: Dterrent |-> source |-> package.d The first line of package.d is : module dterrent; If I am in the Dterrent directory, a `dub build` command compiles the library dterrent properly, exactly as expected. *** I go back up to DEV, then go down into demo1. There I have again a dub.json file, with : "dependencies": { ... "dterrent" : { "path": "../Dterrent" }, In the demo1 directory, I also have a regular source/app.d file, whose first line is: import dterrent; Then I try a `dub build`: jerome@laptop:/DATA/DEV/demo1$ dub build Performing "debug" build using /home/jerome/dlang/dmd-2.093.1/linux/bin64/dmd for x86_64. dterrent ~master: target for configuration "library" is up to date. demo1 ~master: building configuration "application"... source/app.d(9,8): Error: module dterrent is in file 'dterrent.d' which cannot be read import path[0] = source/ import path[4] = ../Dterrent/source/ import path[5] = /home/jerome/dlang/dmd-2.093.1/linux/bin64/../../src/phobos import path[6] = /home/jerome/dlang/dmd-2.093.1/linux/bin64/../../src/druntime/import /home/jerome/dlang/dmd-2.093.1/linux/bin64/dmd failed with exit code 1. Well, the module dterrent is obviously not in dterrent.d dterrent.d does not exist as it, since it is a package.d file with the "module dterrent;" line. If I change package.d for dterrent.d, I get some other errors. But at this point, I think we agree I should not have to change the name of package.d, right? What am I doing wrong? What would be the right way? Or is there a workaround. Thanks
Re: cannot call impure function
On Sunday, 4 October 2020 at 18:02:11 UTC, Michael wrote: On Sunday, 4 October 2020 at 17:43:13 UTC, Michael wrote: [...] I used the dmg file: dmd.2.094.0.dmg I reinstalled using the installation script (install.sh) and now it works. Still don't know why the dmg-based intstallation did not work. https://dlang.org/install.html Anyway, thanks for your responses! I think there might have been a mismatch between the compiler used, and the Phobos library used. This might happen if you used multiple sources for installation, e.g. brew / macports / dmg (install script is self contained and never affected).
Re: cannot call impure function
On Sunday, 4 October 2020 at 17:43:13 UTC, Michael wrote: On Sunday, 4 October 2020 at 17:37:52 UTC, Mathias LANG wrote: On Sunday, 4 October 2020 at 17:05:33 UTC, Michael wrote: On Sunday, 4 October 2020 at 17:01:44 UTC, Paul Backus wrote: On Sunday, 4 October 2020 at 16:48:24 UTC, Michael wrote: Dear all, Sorry for the potentially stupid question, but I'm a complete newbie to D. Why does compiling the following trivial code fail? import std.stdio; void main() { writeln(3.14); } Works fine for me using DMD 2.094.0 on Linux. What OS and compiler version are you using, and how did you install DMD? DMD64 D Compiler v2.094.0 on macOS 10.15.6 I cannot reproduce locally (macOS 10.15.6 too). How did you install DMD ? I used the dmg file: dmd.2.094.0.dmg I reinstalled using the installation script (install.sh) and now it works. Still don't know why the dmg-based intstallation did not work. https://dlang.org/install.html Anyway, thanks for your responses!
Re: cannot call impure function
On Sunday, 4 October 2020 at 17:37:52 UTC, Mathias LANG wrote: On Sunday, 4 October 2020 at 17:05:33 UTC, Michael wrote: On Sunday, 4 October 2020 at 17:01:44 UTC, Paul Backus wrote: On Sunday, 4 October 2020 at 16:48:24 UTC, Michael wrote: Dear all, Sorry for the potentially stupid question, but I'm a complete newbie to D. Why does compiling the following trivial code fail? import std.stdio; void main() { writeln(3.14); } Works fine for me using DMD 2.094.0 on Linux. What OS and compiler version are you using, and how did you install DMD? DMD64 D Compiler v2.094.0 on macOS 10.15.6 I cannot reproduce locally (macOS 10.15.6 too). How did you install DMD ? I used the dmg file: dmd.2.094.0.dmg
Re: cannot call impure function
On Sunday, 4 October 2020 at 16:48:24 UTC, Michael wrote: Dear all, Sorry for the potentially stupid question, but I'm a complete newbie to D. Why does compiling the following trivial code fail? [...] I have tried my best to make it fail, but can't. Maybe it's something with the combination of dmd64 and MACOS?
Re: cannot call impure function
On Sunday, 4 October 2020 at 17:05:33 UTC, Michael wrote: On Sunday, 4 October 2020 at 17:01:44 UTC, Paul Backus wrote: On Sunday, 4 October 2020 at 16:48:24 UTC, Michael wrote: Dear all, Sorry for the potentially stupid question, but I'm a complete newbie to D. Why does compiling the following trivial code fail? import std.stdio; void main() { writeln(3.14); } Works fine for me using DMD 2.094.0 on Linux. What OS and compiler version are you using, and how did you install DMD? DMD64 D Compiler v2.094.0 on macOS 10.15.6 I cannot reproduce locally (macOS 10.15.6 too). How did you install DMD ?
Re: cannot call impure function
On Sunday, 4 October 2020 at 17:05:33 UTC, Michael wrote: On Sunday, 4 October 2020 at 17:01:44 UTC, Paul Backus wrote: On Sunday, 4 October 2020 at 16:48:24 UTC, Michael wrote: Dear all, Sorry for the potentially stupid question, but I'm a complete newbie to D. Why does compiling the following trivial code fail? import std.stdio; void main() { writeln(3.14); } Works fine for me using DMD 2.094.0 on Linux. What OS and compiler version are you using, and how did you install DMD? DMD64 D Compiler v2.094.0 on macOS 10.15.6 I did not use any compiler flags, but just: dmd test1.d
Re: cannot call impure function
On Sunday, 4 October 2020 at 17:01:44 UTC, Paul Backus wrote: On Sunday, 4 October 2020 at 16:48:24 UTC, Michael wrote: Dear all, Sorry for the potentially stupid question, but I'm a complete newbie to D. Why does compiling the following trivial code fail? import std.stdio; void main() { writeln(3.14); } Works fine for me using DMD 2.094.0 on Linux. What OS and compiler version are you using, and how did you install DMD? DMD64 D Compiler v2.094.0 on macOS 10.15.6
Re: cannot call impure function
On Sunday, 4 October 2020 at 16:48:24 UTC, Michael wrote: Dear all, Sorry for the potentially stupid question, but I'm a complete newbie to D. Why does compiling the following trivial code fail? import std.stdio; void main() { writeln(3.14); } Works fine for me using DMD 2.094.0 on Linux. What OS and compiler version are you using, and how did you install DMD?
cannot call impure function
Dear all, Sorry for the potentially stupid question, but I'm a complete newbie to D. Why does compiling the following trivial code fail? import std.stdio; void main() { writeln(3.14); } Error message: /Library/D/dmd/src/phobos/std/format.d(1601): Error: pure function std.format.FormatSpec!char.FormatSpec.toString cannot call impure function std.format.FormatSpec!char.FormatSpec.toString!(Appender!string).toString /Library/D/dmd/src/phobos/std/format.d(478): Error: template instance std.format.FormatSpec!char error instantiating /Library/D/dmd/src/phobos/std/stdio.d(1590):instantiated from here: formattedWrite!(LockingTextWriter, char, double) /Library/D/dmd/src/phobos/std/stdio.d(3927):instantiated from here: write!(double, char) test1.d(5):instantiated from here: writeln!double Cheers, Michael
Re: Taking arguments by value or by reference
On Sunday, 4 October 2020 at 14:26:43 UTC, Anonymouse wrote: [...] I mostly really only want a read-only view of the struct, and whether a copy was done or not is academic. However, profiling showed (what I interpret as) a lot of copying being done in release builds specifically. https://i.imgur.com/JJzh4Zc.jpg Naturally a situation where I need ref I'd use ref, and in the rare cases where it actually helps to have a mutable copy directly I take it mutable. But if I understand what you're saying, and ignoring --preview=in, you'd recommend I use const ref where I would otherwise use const? Is there some criteria I can go by when making this decision, or does it always reduce to looking at the disassembly? If the struct adds overhead to copy, use `const ref`. But if you do, you might end up with another set of problems. Aliasing is one of them, and the dangers of it are discussed at length in the thread about `-preview=in` in general. The other issue is that `const ref` means you cannot pass rvalues. This is when people usually turn towards `auto ref`. Unfortunately, it requires you to use templates, which is not always possible. So, in short: `auto ref const` if it's a template and aliasing is not a concern, `const ref` if the copy adds overhead, and add a `const` non-`ref` overload to deal with rvalues if needed. If you want to be a bit more strict, throwing `scope` in the mix is good practice, too. -- Now, about `-preview=in`: The aim of this switch is to address *exactly* this use case. While it is still experimental and I don't recommend using it in critical projects just yet, giving it a try should be straightforward and any feedback is appreciated. What I mean by "should be straightforward", is that the only thing `-preview=in` will complain about is `in ref` (it triggers an error). The main issue at the moment is that, if you use `dub`, you need to have control over the dependencies to add a configuration, or use `DFLAGS="-preview=in" dub` in order for it to work. Working on a fix to that right now. For reference, this is what adapting code to use `-preview=in` feels like in my project: https://github.com/Geod24/agora/commit/a52419851a7e6e4ef241c4617ebe0c8cc0ebe5cc You can see that I added it pretty much everywhere the type `Hash` was used, because `Hash` is a 64 bytes struct but I needed to support rvalues.
Re: Taking arguments by value or by reference
On Saturday, 3 October 2020 at 23:00:46 UTC, Anonymouse wrote: I'm passing structs around (collections of strings) whose .sizeof returns 432. The readme for 2.094.0 includes the following: This release reworks the meaning of in to properly support all those use cases. in parameters will now be passed by reference when optimal, [...] * Otherwise, if the type's size requires it, it will be passed by reference. Currently, types which are over twice the machine word size will be passed by reference, however this is controlled by the backend and can be changed based on the platform's ABI. However, I asked in #d a while ago and was told to always pass by value until it breaks, and only then resort to ref. [18:32:16] at what point should I start passing my structs by ref rather than by value? some are nested in others, so sizeofs range between 120 and 620UL [18:33:43] when you start getting stack overflows [18:39:09] so if I don't need ref for the references, there's no inherent merit to it unless I get in trouble without it? [18:39:20] pretty much [18:40:16] in many cases the copying is merely theoretical and doesn't actually happen when optimized I've so far just been using const parameters. What should I be using? I don't agree with this, especially if the struct is 432 bytes. It takes time and memory to copy such structure. I always use "const ref" when I pass structures because that's only a pointer. Classes are references by themselves so its not applicable there. Only "ref" when I want to modify the contents. However there are some exceptions to this rule in D as D support slice parameters. In this case you want a copy as slice of the array, often because the slice is often casted from something else. Basically the array slice parameter become an lvalue. This copy of parameters to the stack is an abomination in computer science and only useful in some cases but mostly not. The best would be if the compiler itself could determine what is the most efficient. Nim does this and it was not long ago suggested that the "in" keyword should have a new life as such optimization, is that the change that has entered in 2.094.0? Why wasn't this a DIP? I even see this in some C++ program code where strings are passed as value which means that the string is copied including a possible memory allocation which certainly slow things down. Do not listen to people who says "pass everything by value" because that is in general not ideal in imperative languages.
Re: Taking arguments by value or by reference
On Saturday, 3 October 2020 at 23:47:32 UTC, Max Haughton wrote: The guiding principle to your function parameters should be correctness - if I am passing a big struct around, if I want to take ownership of it I probably want to take it by value but if I want to modify it I should take it by reference (or by pointer but don't overcomplicate, notice in the previous example they lower to the same thing). If I just want to look at it, it should be taken by const ref if possible (D const isn't the same as C++ const, this may catch you out). Const-correctness is a rule to live by especially with an big unwieldy struct. I would avoid the new in for now, but I would go with const ref from what you've described so far. I mostly really only want a read-only view of the struct, and whether a copy was done or not is academic. However, profiling showed (what I interpret as) a lot of copying being done in release builds specifically. https://i.imgur.com/JJzh4Zc.jpg Naturally a situation where I need ref I'd use ref, and in the rare cases where it actually helps to have a mutable copy directly I take it mutable. But if I understand what you're saying, and ignoring --preview=in, you'd recommend I use const ref where I would otherwise use const? Is there some criteria I can go by when making this decision, or does it always reduce to looking at the disassembly?
Re: dub fetching dependencies for wrong configuration(s)
On Sunday, 4 October 2020 at 14:08:24 UTC, Anonymouse wrote: My project depends on the requests dub package, which has two build configurations; one with an extra vibe-d dependency, one without (default). "configurations": [ { "name": "std" }, { "name": "vibed", "versions": ["vibeD"], "dependencies": { "vibe-d": ">=0.8.0" } } ], I only ever use the default "std" configuration, but dub always pulls the additional multiple vibe-d dependencies, regardless of what I pick. Adding a subConfiguration restriction does not seem to help. $ dub upgrade Upgrading project in /home/zorael/src/kameloso Fetching vibe-core 1.10.2 (getting selected version)... Is there any way to stop this? AFAIK this is dub feature, which you cant't avoid easily. Naybe there are some reasons behind this feature, idk. But I'd like to avoid it too.
dub fetching dependencies for wrong configuration(s)
My project depends on the requests dub package, which has two build configurations; one with an extra vibe-d dependency, one without (default). "configurations": [ { "name": "std" }, { "name": "vibed", "versions": ["vibeD"], "dependencies": { "vibe-d": ">=0.8.0" } } ], I only ever use the default "std" configuration, but dub always pulls the additional multiple vibe-d dependencies, regardless of what I pick. Adding a subConfiguration restriction does not seem to help. $ dub upgrade Upgrading project in /home/zorael/src/kameloso Fetching vibe-core 1.10.2 (getting selected version)... Fetching memutils 1.0.4 (getting selected version)... Fetching taggedalgebraic 0.11.18 (getting selected version)... Fetching vibe-d 0.9.2 (getting selected version)... Fetching botan-math 1.0.3 (getting selected version)... Fetching stdx-allocator 2.77.5 (getting selected version)... Fetching botan 1.12.18 (getting selected version)... Fetching diet-ng 1.7.4 (getting selected version)... Fetching openssl 1.1.6+1.0.1g (getting selected version)... Fetching eventcore 0.9.9 (getting selected version)... Fetching mir-linux-kernel 1.0.1 (getting selected version)... Fetching libasync 0.8.6 (getting selected version)... Is there any way to stop this?
GC and sensible data read by File
Hello, I'm new to D and try to find out a memory leak in my program. I inspected the private bytes with VmMap on Windows to see which data is still kept. Besides the actual memory leak I was surprised to find out there are contents of my previoulsy read configuration INI file. So my question is: Is this expected behaviour? Why does the GC then not overwrite the contents with 0? Or did I something wrong in my function or does File not clear the data afterwards? And if so, how can I read sensible data from a file with standard methods which should not kept in memory? I also tried manually GC.free() on buf and other places but still same result. Basically this (removed some encforce() statements) and do not show Converter method here because the string in memory is raw string like a INI-comment which is never passed to my converter, so it's not relevant and cannot cause the problem. Variant[string][string] parse() { size_t lineNr; char[] buf; string sectionName; string keyName; Variant[string][string] sections; auto fp = File(_fileName); while (!fp.eof()) { buf.length = 0; fp.readln(buf); string line = to!string(buf).trim(); ++lineNr; // filter out empty lines if (line.length == 0) continue; // filter out comments if (line.startsWith(";")) continue; if (line.startsWith("[")) { // section start / previous section complete sectionName = line.trim("[]"); continue; } // regular entry Variant v; ptrdiff_t sepPos = line.indexOf("="); keyName = to!string(line[0 .. sepPos]).trim(); bool isArrayEntry = keyName.indexOf("[]") > -1 && keyName.endsWith("]"); string tmpVal = to!string(line[sepPos + 1 .. $]).trim(); // trim text delimiter chars, if any tmpVal = tmpVal.trim("'\""); // if array, just append to existing value or create it if (isArrayEntry) { keyName = keyName.trim("[]"); // array is always considered as string // other values makes no sense in this syntax string oldVal; if (auto sectionPtr = sectionName in sections) { if (auto keyPtr = keyName in *sectionPtr) { oldVal = (*keyPtr).get!(string); } } v = Variant(oldVal ~ tmpVal); } else { v = Converter.autoConvertFromString(tmpVal); } sections[sectionName][keyName] = v; } return sections; }
Re: QuickSort on ranges
Thanks you very much Ali, I will try to wrap my head around your inputs, and get a better understanding of ranges in the process. I feel there is a lot of power in D ranges, and like the hammer of Thor, I am not worthy yet :)
Re: How to write a counterpart to C++ std::invoke that works with both free functions and methods?
On Tuesday, 29 September 2020 at 01:19:48 UTC, Adam D. Ruppe wrote: On Sunday, 27 September 2020 at 05:22:36 UTC, 60rntogo wrote: How would I check if it is actually a free function? but this doesn't even compile since I defined add inside my main function ah that's not a free function!! OK, I see. That makes sense I suppose. Thanks for putting this together, but I'm afraid that I managed to break it again and this time it is really baffling. --- module foo; auto invoke(alias fun, Args...)(Args args) { static if(__traits(isStaticFunction, fun) || __traits(isNested, fun)) return fun(args); else return __traits(child, args[0], fun)(args[1 .. $]); } unittest { import std : approxEqual; assert(invoke!approxEqual(2.0, 2.001)); } --- This gives me these errors: --- source/foo.d(6,48): Error: aggregate or function expected instead of approxEqual(T, U, V)(T value, U reference, V maxRelDiff = 0.01, V maxAbsDiff = 1e-05) source/foo.d(9,41): Error: template std.math.approxEqual cannot deduce function from argument types !()(double), candidates are: /usr/include/dmd/phobos/std/math.d(8479,6):approxEqual(T, U, V)(T value, U reference, V maxRelDiff = 0.01, V maxAbsDiff = 1e-05) source/foo.d(15,28): Error: template instance foo.invoke!(approxEqual, double, double) error instantiating --- Confusingly, these errors disappear if I include the unit test in my main file (i.e., just add it to the code you posted) rather than foo.d or if I use a function like add defined in the module instead of imported approxEqual. Any ideas?