Re: Challenge Tuples
On Friday, 26 April 2024 at 13:25:34 UTC, Salih Dincer wrote: You have a 5-item data tuples as Tuple(1, 2, 3, [1, 3], 5) and implement the sum (total = 15) with the least codes using the sum() function of the language you are coding... Let's start with D: ```d import std.typecons : tuple; import std.algorithm : sum; void main() { auto t = tuple(1, 2, 3, [1, 3], 5); int[] arr; t.each!(e => arr ~= e); assert(arr.sum == 15); } ``` and bonus: ```d import std.typecons : tuple; import std.stdio : writeln; void main() { auto t = tuple(1, 2, 3, [1, 3], 5); auto results = [0]; foreach (data; t) { static if (is(typeof(data) == int[])) { int sum; foreach (d; data) { sum += d; } results ~= sum; } else { results ~= data; } } results.writeln; // [0, 1, 2, 3, 4, 5] ``` I bet you won't be able to do it this easily with other languages! Note: I tried with C# and Python and it didn't work! SDB@79 Shorter and without allocations: ```d import std.typecons : tuple; import std.algorithm : sum, each; auto sum(int i) => i; void main() { auto t = tuple(1, 2, 3, [1, 3], 5); int res=0; t.each!(e => res += sum(e)); assert(res == 15); } ```
Re: Is a shorter statement possible in this case?
On Sunday, 5 November 2023 at 18:36:40 UTC, Ctn-Dev wrote: Is there a more concise way of getting the same result? Try this: ```d switch(range.map!(_ => (_== "Two" ? 2 : _=="One" ? 1 : 0)).fold!((a,b) => a | b)(0)) { case 3: writeln("both"); break; case 2: writein("only two"); break; case 1: writeln("only one"); break; default: writeln("none"); break; } ``` Where `range` is input array.
Re: DUB: Is it possible to set release as a default build for a dub package?
On Friday, 3 November 2023 at 19:21:42 UTC, BoQsc wrote: However I would want to try to enforce this behaviour from the `dub.json` or `dub.sdl` file. IMHO this is not something that should be enforced from package build configuration, however there can be a way to configure it on system level (like in `dub.conf` if it exists).
Re: Keyword "package" prevents from importing a package module "package.d"
On Friday, 3 November 2023 at 18:04:58 UTC, Jonathan M Davis wrote: - Jonathan M Davis Thanks a lot for detailed explanation!
Re: Keyword "package" prevents from importing a package module "package.d"
On Friday, 3 November 2023 at 00:52:18 UTC, H. S. Teoh wrote: Supposedly you can do this: /* Original: */ // pkg/mymodule.d module mymodule; ... // code here // main.d import mymodule; void main() { ... } /* Split */ // pkg/mymodule/pub_submod.d module mymodule.pub_submod; ... // code here // pkg/mymodule/priv_submod.d module mymodule.priv_submod; ... // code here // pkg/mymodule/package.d module mymodule; public import priv_submod; // main.d import mymodule; void main() { ... } Barring the issues listed above, of course. I know how to do this with package.d but my question was about "package.d is bad design decision" - How would I do this refactoring without dedicated "main package file"? Python, for example, has __init__.py as well
Re: Keyword "package" prevents from importing a package module "package.d"
On Thursday, 2 November 2023 at 19:43:01 UTC, Adam D Ruppe wrote: On Thursday, 2 November 2023 at 19:30:58 UTC, Jonathan M Davis wrote: The entire reason that it was added to the language was to be able to split up existing modules without breaking code. And it does that well. No, it doesn't do that well at all. In fact, it does that so extremely poorly that (as you might recall) there were a very large number of support requests shortly after Phobos started using it about broken builds, since it would keep the old file and the new file when you updated and this stupid, idiotic design can't handle that situation. This only subsided because enough time has passed that nobody tries using it to break up existing modules anymore. It is just a *terrible* design that never should have passed review. It is randomly inconsistent with the rest of the language and this manifests as several bugs. (including but not limited to: https://issues.dlang.org/show_bug.cgi?id=14687 doesn't work with .di https://issues.dlang.org/show_bug.cgi?id=17699 breaks if you try to use it for its intended purpose https://issues.dlang.org/show_bug.cgi?id=20563 error messages hit random problems all-at-once vs separate compilation of package leads to inconsistent reflection results im sure the list went on if i spent a few more minutes looking for my archives) package.d is indeed completely unnecessary for creating a module that publicly imports other modules in order to be able to import a single module and get several modules. Yeah, it is a terrible feature that is poorly designed, hackily implemented, and serves no legitimate use case. Is there any guide how one can refactor single-module package into multi-module package with distinction between public and private modules?
Re: Key and value with ranges
On Tuesday, 3 October 2023 at 19:57:06 UTC, christian.koestlin wrote: On Tuesday, 3 October 2023 at 01:55:43 UTC, Andrey Zherikov wrote: On Monday, 2 October 2023 at 18:46:14 UTC, christian.koestlin wrote: [...] Slightly improved: ```d import std; [...] Thanks .. the thing with ref result is very clever! Should `ref result` be `return result`? `ref` might not be necessary fo AA but I'm not sure. `fold` requires function to return something (see [doc](https://dlang.org/phobos/std_algorithm_iteration.html#fold)): for each element x in range, result = fun(result, x) gets evaluated.
Re: Key and value with ranges
On Monday, 2 October 2023 at 18:46:14 UTC, christian.koestlin wrote: On Monday, 2 October 2023 at 02:47:37 UTC, Joel wrote: How can I improve this code? Like avoiding using foreach. You could fold into a hash that counts the occurrences like that: ```d import std.uni : toLower; import std.array : split, array; import std.stdio : writeln; import std.algorithm : fold, sort, map; auto data="I went for a walk, and fell down a hole. a went"; int main(string[] args) { int[string] wc; data .toLower .split .fold!((result, element) { result[element] += 1; return result; })(wc) .byKeyValue .array .sort!((pair1, pair2) => pair1.value > pair2.value) .map!(pair => pair.key) .writeln ; return 0; } ``` Not sure how to get rid of the declaration of the empty wc hash though. Kind regards, Christian Slightly improved: ```d import std; auto data="I went for a walk, and fell down a hole. a went"; int main(string[] args) { data .toLower .split .fold!((ref result, element) { ++result[element]; return result; })(uint[string].init) .byKeyValue .array .sort!((pair1, pair2) => pair1.value > pair2.value) .each!(pair => writeln("Word: ", pair.key, " - number of instances: ", pair.value)) ; return 0; } ``` Output: ``` Word: a - number of instances: 3 Word: went - number of instances: 2 Word: and - number of instances: 1 Word: i - number of instances: 1 Word: hole. - number of instances: 1 Word: for - number of instances: 1 Word: down - number of instances: 1 Word: fell - number of instances: 1 Word: walk, - number of instances: 1 ```
Re: Function template as template parameter
On Sunday, 11 December 2022 at 16:24:30 UTC, Ali Çehreli wrote: On 12/11/22 05:54, Salih Dincer wrote: > On Sunday, 11 December 2022 at 09:43:34 UTC, Andrey Zherikov wrote: >> Note that callback parameter must be compile-time parameter as it >> represents a member of a type during introspection done by `foo`. > > I can't quite understand the question, this already works: I think the OP is trying to create an anonymous template. Yes The following does not work when one attempts to use the template anonymously. Just trying to pass a template just like a lambda Thanks for confirming this.
Function template as template parameter
I have this (very simplified) code: ```d void foo(alias callback)() { callback!5; } static void print(int i)() { writeln(i); } foo!print; ``` Is there a way to merge two last lines into one of a form like `foo!(...something...)`? Note that callback parameter must be compile-time parameter as it represents a member of a type during introspection done by `foo`.
Re: Is defining get/set methods for every field overkill?
On Saturday, 19 November 2022 at 10:17:19 UTC, []() {}() wrote: On Saturday, 19 November 2022 at 09:51:09 UTC, []() {}() wrote: ... no. in C# it breaks ABI. that is why its not acceptable in my team. of course that's not the reason we don't use public member variables in classes. the reason we don't use them, is because (1) we always anticpiate change including the need to implement (and change) business rules associated with the objects data (using setter/getters), and (2) we always prioritise the stability of the public interface of a class at the time of design. if neither of those are your concern, in production-level code, I'd be really surprised (and shocked). We don't use public members either in most cases - we use them in simple structs. We have teams that do care and prioritize stability of public interface because they ship their libraries to end-users. Other teams care much less because all their users are internal so they can fix whatever they break. Regarding ABI compatibility: it's usually driven by what dependencies your software has. In your case (as far as I got) you ship .dll that is used by already deployed software so your library must be ABI compatible with it. In our case, our software has only system-level dependencies like C runtime, WinSocks so we don't have such a thing as ABI incompatibility between different parts of our software but we care about system-level ABI.
Re: Is defining get/set methods for every field overkill?
On Saturday, 19 November 2022 at 09:49:18 UTC, thebluepandabear wrote: I am too dumb to know what ABI is https://en.wikipedia.org/wiki/Application_binary_interface
Re: Is defining get/set methods for every field overkill?
On Saturday, 19 November 2022 at 09:51:09 UTC, []() {}() wrote: no. in C# it breaks ABI. that is why its not acceptable in my team. Every company works differently. Yours are using .net and (I guess) ships dlls so you must care about ABI with existing software. In my company we use static linking so the only ABI compatibility we care about is with libc. I expect it would also break ABI in D. I'd like to know the answer so I hope someone from D core step in and shed a light on it.
Re: Is defining get/set methods for every field overkill?
On Saturday, 19 November 2022 at 09:12:26 UTC, thebluepandabear wrote: That's the point many people have given here which is not convincing him, even though it is quite great. I think we all know the answer here IMHO you are both right :) You are speaking about API compatibility, `[]() {}()` speaks about ABI compatibility. The latter makes sense in long-running production software. So we know that there are no issues in API compatibility but we don't know anything about ABI.
Re: Is defining get/set methods for every field overkill?
On Saturday, 19 November 2022 at 09:12:26 UTC, thebluepandabear wrote: That's the point many people have given here which is not convincing him, even though it is quite great. I think we all know the answer here IMHO you are both right :) You are speaking about API compatibility, `[]() {}()` speaks about ABI compatibility. The latter makes sense in long-running production software. So we know that there are no issues in API compatibility but we don't know anything about ABI.
Re: Is defining get/set methods for every field overkill?
On Saturday, 19 November 2022 at 09:05:42 UTC, []() {}() wrote: Once you refactor your class (creating actual private member variables and creating getter/setter methods, you are almost certainly going to break binary compatability, and when you send your update compiler library to your customer, there code will stop working - cause they'll have to recompile it against the new library. I think you are speaking about shipping dynamic library to users. I think compiler authors can clarify whether introducing getters/setters breaks ABI or not. On the other side if it breaks then it can be easily checked: create simple program that uses dynamic library, then change the latter to use getters/setters and run program again without recompiling.
Re: Is defining get/set methods for every field overkill?
On Saturday, 19 November 2022 at 04:13:33 UTC, []() {}() wrote: oh. so i get it now. you have to refactor your class (change member variable names and also do it in all places where they are used througout the class. then add new methods, overloading them in this way and that way, all because you're initial design never factored in the possibility of change (or even some validation of the vale being returned to the client, or validation of value coming from the client). You are not required to rename everything, just actual members. D has nice feature to convert `foo.bar` to `foo.bar()` and `foo.bar = value` to `foo.bar(value)` that doesn't exist in C/C++ for example. This reduces some headache in planning the API ahead. Let's we have this class and its usage: ```d class Rect2D { int width; int height; auto area() const { return width * height; } } Rect2D rect = new Rect2D(); rect.width = 5; rect.height = 5; writeln(rect.area); // note that this is seamlessly translated to rect.area() ``` Then you decided that you want getters/setters so you add them without changing anything: ```d class Rect2D { int width_; int height_; auto width() const { return width_; } void width(int w) { width_ = w; } auto height() const { return height_; } void height(int h) { height_ = h; } auto area() const { return width * height; } // no changes here - using getters } Rect2D rect = new Rect2D(); rect.width = 5; // no changes here - using setter rect.height = 5; // no changes here - using setter writeln(rect.area); ``` You can also use UFCS instead of class members but it has a caveat: plain `width`/`height` won't work within class so you have to either use `width_`/`height_` directly or `this.width`/`this.height`: ```d class Rect2D { int width_; int height_; auto area() const { return this.width * this.height; } // UFCS calls to global width() and height() functions } // These functions have to be in global scope for UFCS to work auto width(const Rect2D rect) { return rect.width_; } void width(ref Rect2D rect, int w) { rect.width_ = w; } auto height(const Rect2D rect) { return rect.height_; } void height(ref Rect2D rect, int h) { rect.height_ = h; } void main() { // Still no changes in user code Rect2D rect = new Rect2D(); rect.width = 5; rect.height = 5; writeln(rect.area); } ```
Re: ImportC linking issue
On Saturday, 12 November 2022 at 10:02:12 UTC, confuzzled wrote: Why would I have to search for libcrypto, libminizip, libexpat, and more that I haven't even figured out what library they are? I thought those dependencies would already be linked into libxlsxio_read.a which is a statically linked library. This is called transitive dependencies. For Unix systems linking a static library is not a linking per se, it means putting object files (.o) into an archive (.a) using [ar](https://linux.die.net/man/1/ar). So "libfoo.a" is just a set of object files that don't know anything about their dependencies and if you use something from libfoo.a, you might need to add another library to you link line. Technically there are two possible cases: (1) function that you use doesn't depend on anything else, then you don't need to add anything to your link line; and (2) function uses something from, say libbar.a - then you have to add libbar.a to your link line. Dynamic libraries (.so) are treated the same way as executables: they are created by linker ([ld](https://linux.die.net/man/1/ld) for example) and so they have to have all symbols resolved. This means that if libfoo.so depends on libbar.a then the latter is already baked in into the former so your don't need to specify it when you link with libfoo.so. TBH I don't remember whether you should add libbar.so (dynamic library) which is a dependency of libfoo.so to your link line.
Re: Is "auto t=T();" not the same as "T t;"?
On Wednesday, 26 October 2022 at 04:40:17 UTC, Salih Dincer wrote: On Tuesday, 25 October 2022 at 13:51:30 UTC, Andrey Zherikov wrote: Does the second piece of code shows a bug or my expectation is not correct (and why if so)? As a result, if this is a bug, Andrey has the right to report it. Bug tracking system doesn't work with gmail emails so I'm not able to report.
Re: Is "auto t=T();" not the same as "T t;"?
On Tuesday, 25 October 2022 at 14:53:50 UTC, Adam D Ruppe wrote: On Tuesday, 25 October 2022 at 13:51:30 UTC, Andrey Zherikov wrote: A[] a = [A.init]; This is a problem - this is referring to a static array instance, shared across all copies of B. You almost certainly don't want this. That B.a[0] is the *same object* across different default-constructed Bs... unless the optimizer hits it or something. Is it a bad idea to trigger copy on write before modification of B.a so it behaves as below? ```d B b1; b1.a = b1.a.dup; // copy on write b1.a[0].i ~= '1'; b1.a ~= A.init; b1.a[0].i ~= '2'; b1.a[1].i ~= '3'; b1.writeln;// B([A("12"), A("3")]) B b2; b2.writeln;// B([A("")]) ```
Re: Is "auto t=T();" not the same as "T t;"?
On Tuesday, 25 October 2022 at 14:53:50 UTC, Adam D Ruppe wrote: But just don't do this. Only basic values and immutable strings are good to initialize this way. With the array or class objects, you're liable to get some shared thing. If you change this to be initialized in a constructor (which will require an argument in D) or factory function, you'll get far more consistent behavior as each instance will have its own array. I'd like to tune default ctor but structs can't have custom one. Adding a ctor with parameter seems a hack to me - and compiler still allows default construction even when default ctor is disabled: ```d struct A { int[] i; } struct B { A[] a; @disable this(); this(bool) { A[] a = [A.init]; } } void main() { auto b1 = B.init; b1.a[0].i ~= 1; b1.a ~= A.init; b1.a[0].i ~= 11; b1.a[1].i ~= 12; b1.writeln; auto b2 = B.init; b2.writeln; } ``` This fails in run time, not compile time: ``` core.exception.ArrayIndexError@onlineapp.d(19): index [0] is out of bounds for array of length 0 ??:? _d_arraybounds_indexp [0x55b558b8ec55] ./onlineapp.d:19 _Dmain [0x55b558b6bd5f] ``` As for why B() and B.init are different here... i don't know, probably some subtly of the compiler's implementation. Actually `auto b = B.init;` behaves the same way as `auto b = B();` but they don't do the same as `B b;`
Is "auto t=T();" not the same as "T t;"?
I have the following types (simplified version of my code): ```d struct A { int[] i; } struct B { A[] a = [A.init]; } ``` This code: ```d auto b1 = B.init; b1.a[0].i ~= 1; b1.a ~= A.init; b1.a[0].i ~= 11; b1.a[1].i ~= 12; b1.writeln; auto b2 = B(); b2.writeln; ``` prints this as expected: ``` B([A([1, 11]), A([12])]) B([A([])]) ``` But this code: ```d B b1; // auto b1 = B.init; b1.a[0].i ~= 1; b1.a ~= A.init; b1.a[0].i ~= 11; b1.a[1].i ~= 12; b1.writeln; B b2; // auto b2 = B(); b2.writeln; ``` prints this which is not expected: ``` B([A([1, 11]), A([12])]) B([A([1])]) ``` Does the second piece of code shows a bug or my expectation is not correct (and why if so)?
Re: Hipreme's #2 Tip of the day - Reducing .di files dependency
On Sunday, 23 October 2022 at 20:12:46 UTC, Hipreme wrote: This will greatly reduce the number of import and dependencies you need if you ever need to distribute a library. Could you elaborate more on the benefit? Does it reduce compilation time for dependency? If so then how much?
Re: rotate left an array
On Monday, 3 October 2022 at 18:09:05 UTC, Fausto wrote: Hello all, I am trying to rotate left an array. I found a very basic way, and I am not sure if there is something clever than this :) maybe using slices... the external for represents how many times you are rotating (in this case 2). If you don't need to add or remove the data from your array then I'd go with constant array and translating external index to an internal one for this array. So it's gonna be something like a "rotated view".
Re: How I can pass the WndProc as a parameter?
On Saturday, 10 September 2022 at 10:39:12 UTC, Injeckt wrote: server.d(29): Error: function `server.WndProc(void* hwnd, uint message, uint wParam, int lParam)` is not callable using argument types `()` I think you need to get address of a function: ```d wndclass.lpfnWndProc = ```
Re: Validate static asserts
On Friday, 9 September 2022 at 15:22:30 UTC, Ali Çehreli wrote: I added and removed '&& false' to every 'static assert' condition manually one by one. :/ It's not CI-friendly :( Perhaps a new compiler switch can compile every 'static assert' with an automatic 'false' and dump all their text to the output. What's about new `compileOutput` trait that returns compiler output? ```d static assert(__traits(compileOutput, { }) == "message"); ```
Validate static asserts
I have bunch of `static assert(, )` in my code and would like to validate that specific code triggers specific assert by checking what `` is thrown. Right now I do `static assert(!__traits(compiles, { }));` but since `` might not compile due to many different reasons, I might not be testing original `static assert` and might miss breaking change. One way to do this is to extract `` and `` into some function and test it outside of `static assert`: ```d auto check() { return tuple(false, // check result ('false' is just for example) "message"); } void f() { enum result = check(); static assert(result.condition, result.message); } unittest { enum result = check(); static assert(result.condition); static assert(result.message == "message"); } ``` But I don't like this approach because unit test doesn't really test `f()` (it tests duplicated code) so it can't guarantee that `f()` works as expected. Is there a way to validate static asserts in unit tests?
Re: typeof(func!0) != typeof(func!0())
On Monday, 22 August 2022 at 17:40:59 UTC, Andrey Zherikov wrote: I'm providing a struct (`U` in examples above) with some API and I'm looking for this struct as an UDA (through `hasUDA`/`getUDAs`). And actually I already have a mix of member-functions and free-functions in my API so it's gonna be more consistent if I make all of them free-functions. Just checked - free functions work so I'll migrate API to them. Thanks everyone for answering my questions.
Re: typeof(func!0) != typeof(func!0())
On Monday, 22 August 2022 at 16:42:50 UTC, Paul Backus wrote: It's probably not worth completely changing your API design just to work around this issue. Also, even if you do this, it is still possible for a user to run into a same problem with a member function of one of their own types; for example: ```d import your.library; struct MyStruct { U myFunc() { /* ... */ } } @(MyStruct.myFunc) whatever; ``` This will be users' issue then, not mine :) I'm providing a struct (`U` in examples above) with some API and I'm looking for this struct as an UDA (through `hasUDA`/`getUDAs`). And actually I already have a mix of member-functions and free-functions in my API so it's gonna be more consistent if I make all of them free-functions.
Re: typeof(func!0) != typeof(func!0())
On Monday, 22 August 2022 at 15:20:46 UTC, Paul Backus wrote: On Monday, 22 August 2022 at 14:43:24 UTC, Andrey Zherikov wrote: But the question is still opened: why is `typeof(U().func!0)` not the same as `typeof(U().func!0())`? Probably because if it were the same, it would be completely impossible to introspect on the type of `U.func!0` directly. The closest you could get would be to examine `typeof(!0)`; i.e., the type of the function pointer rather than the function itself. I'm not totally convinced that the current behavior is the correct decision here, but there is a real tradeoff. I have an impression that template function can be called without parenthesis if it doesn't have run-time parameters so `func!0` is the same as `func!0()`. Am I wrong? If we consider free function vs. member function, why is `typeof(u.func!0)` not the same as `typeof(u.func2!0)` here? ```d struct U { ref U func(int i)() { return this; } } ref U func2(int i)(ref U u) { return u; } void main() { U u; pragma(msg, typeof(u.func!0)); // pure nothrow @nogc ref @safe U() return pragma(msg, typeof(u.func2!0)); // U } ``` Is `typeof(u.func2!0)` correct in this case? If so then I'll just convert my API to free-standing functions and everything will work as a magic (without my own implementation of `getUDA`).
Re: typeof(func!0) != typeof(func!0())
On Monday, 22 August 2022 at 15:15:22 UTC, Paul Backus wrote: My first instinct is to say that this is the user's mistake. UDAs are not evaluated like normal expressions, and anyone using UDAs is going to have to learn that sooner or later. My feeling was that UDA expression is just an expression that's evaluated at compile time. Am I wrong? Where can I read about the differences between UDA and 'normal' expressions? That said, if you want to try and present a nicer API, my recommendation would be to accept *either* (a) an instance of `U`, or (b) a callable that returns a `U`, which you can do with code like the following: ```d import std.traits, std.meta; enum isOrReturnsU(alias attr) = is(typeof(attr) == U) || is(typeof(attr()) == U); alias getMyUDAs(alias sym) = Filter!(isOrReturnsU, getUDAs!sym); ``` Or if you want to generalize to arbitrary predicates: ```d alias filterUDAs(alias sym, alias pred) = Filter!(pred, getUDAs!sym); ``` Thanks for this suggestion, I'll try it out!
Re: typeof(func!0) != typeof(func!0())
But the question is still opened: why is `typeof(U().func!0)` not the same as `typeof(U().func!0())`? There is also inconsistency within UFCS - type depends on whether function is a member or standalone (even if I replace `auto ref` with `ref U`): ```d struct U { ref U func(int i)() { return this; } } ref U func2(int i)(ref U u) { return u; } void main() { U u; pragma(msg, typeof(u.func!0)); // pure nothrow @nogc ref @safe U() return pragma(msg, typeof(u.func2!0)); // U } ```
Re: typeof(func!0) != typeof(func!0())
On Monday, 22 August 2022 at 12:04:09 UTC, Paul Backus wrote: On Monday, 22 August 2022 at 11:24:59 UTC, Andrey Zherikov wrote: On Monday, 22 August 2022 at 06:01:11 UTC, JG wrote: Why not just change to: alias type = typeof(U().func!0()); This is user's code and `U().func!0` is legit syntax. Workaround: wrap it in a lambda. ```d import std.traits; alias type = ReturnType!(() => U().func!0); ``` My situation is that user can write some UDA expression and I'm checking whether it's of a type `U` using `hasUDA!(sym, U)` and `getUDAs!(sym, U)`. Is the users uses `U()` or `U().func!0()`, everything works. But `U().func!0` does not because its type is not `U`. So to handle this use case it seems I need to implement my own `hasUDA` and `getUDAs` based on `ReturnType`.
Re: typeof(func!0) != typeof(func!0())
On Monday, 22 August 2022 at 06:01:11 UTC, JG wrote: Why not just change to: alias type = typeof(U().func!0()); This is user's code and `U().func!0` is legit syntax.
Re: typeof(func!0) != typeof(func!0())
On Monday, 22 August 2022 at 05:25:50 UTC, Ali Çehreli wrote: This is where the @property keyword makes a difference: @property auto ref func(int i)() { return this; } Now U().func!0 will be a call in your expression. Is original `U().func!0` not a call? But I think std.traits.ReturnType is more explicit and does work in this case: import std.traits; alias type = ReturnType!(U().func!0); This works but looks strange - I'm checking the type of UDA expression: ```d @(U().func!0) int b; pragma(msg, __traits(getAttributes, b)); // tuple(U().func) pragma(msg, typeof(__traits(getAttributes, b)[0])); // pure nothrow @nogc ref @safe U() return pragma(msg, ReturnType!(__traits(getAttributes, b)[0]));// U pragma(msg, is(typeof(__traits(getAttributes, b)[0]) : U)); // false pragma(msg, hasUDA!(b, U)); // false ```
typeof(func!0) != typeof(func!0())
I have this simple code: ```d struct U { auto ref func(int i)() { return this; } } void main() { { alias type = typeof(U().func!0); pragma(msg, type); // pure nothrow @nogc ref @safe U() return pragma(msg, is(type : U)); // false auto u = U().func!0; pragma(msg, typeof(u)); // U } { alias type = typeof(U().func!0()); pragma(msg, type); // U pragma(msg, is(type : U)); // true auto u = U().func!0(); pragma(msg, typeof(u)); // U } } ``` Why does `typeof(U().func!0)` != `U`? How can I check that the returned value has type `U` in this case?
Re: My programs issues
On Wednesday, 10 August 2022 at 14:08:59 UTC, pascal111 wrote: This version has modern features, it's 1) functional 2) goto-less. There is nothing modern ;-D
Re: My programs issues
On Wednesday, 10 August 2022 at 13:34:53 UTC, pascal111 wrote: So, the program will be like this: Is this clearer? ```d import std.stdio; import std.algorithm; import std.range; double getNumber() { double x; write("Enter a number: "); readf(" %s\n", ); writeln; return x; } int getChoice() { while(true) { writeln("1) addition 2) subtraction 3) multiplication 4) division 0) exit -1) new"); ": ".write; int choice; readf(" %s\n", ); if(only(1,2,3,4,0,-1).canFind(choice)) return choice; } } int main() { double x, y; y = getNumber(); while(true) { int choice = getChoice(); if(choice==0) return 0; else if(choice==-1) y = getNumber(); else { write("Enter a number: "); readf(" %s\n", ); switch(choice){ case 1: y+=x; break; case 2: y-=x; break; case 3: y*=x; break; case 4: y/=x; break; default: break;} y.writeln; } } } ```
Re: A look inside "filter" function defintion
On Monday, 1 August 2022 at 23:35:13 UTC, pascal111 wrote: I think this line needs explanation: '''D return FilterResult!(unaryFun!predicate, Range)(range); ''' Create an object of type `FilterResult!(unaryFun!predicate, Range)` by passing `range` to its ctor, then return that object.
Re: Breaking ";" rule with lambda functions
On Monday, 1 August 2022 at 14:15:31 UTC, pascal111 wrote: We all know the strange syntax of lambda function within filter algorithm like "auto r = chain(a, b).filter!(a => a > 0);". TBH I don't find lambda syntax strange - it's pretty nice and there are two forms (unlike in C++): short one (`a => a > 0`) and long one (`(a) { return a > 0; }`). Compare to C++ lambda syntax: `[](auto a) { return a > 0; }` My note is, don't we break D rules by leaving ";" after lambda function syntax?! There is no breakage: `a => a > 0` in this example is a (template) parameter to `filter` function. You can rewrite it in different ways, like: `filter!((a) { return a > 0; })` or ```d alias criteria = (a) { return a > 0; }; auto r = chain(a, b).filter!criteria; ``` or even longer: ```d auto criteria(T)(T a) { return a > 0; } auto r = chain(a, b).filter!criteria; ``` Many of D rules are taken from C, we know that, so a general basic rule is to put ";" after each statement I think this is more or less correct but I personally like that I don't need to put ";" after definition of a class or struct unlike in C. so the previous statement of filter should be "auto r = chain(a, b).filter!(a => a > 0;);"? Why D leaves ";" in this case? No. it should not. The statement here is `auto r = chain(a, b).filter!(a => a > 0);`, not `a => a > 0`. If you use longer version of lambda syntax then yes, you'll see ";" there: `auto r = chain(a, b).filter!((a) { return a > 0; });` but ";" is not after lambda function, it's inside because you have `{...}` function body (which, I believe, is defined as a sequence of statements so you have ";" there). Again, both `a => a > 0` and `(a) { return a > 0; }` are just parameters to `filter` function. Parameters are not terminated with ";". This is the same as in C - you are not adding ";" after function parameter: ```cpp auto is_even = [](int i){ return i%2 == 0; }; auto result = std::find(..., ..., is_even); ```
Re: Is this a violation of const?
On Friday, 29 July 2022 at 22:16:26 UTC, H. S. Teoh wrote: This totally makes sense. Thanks for explanation!
Re: A converting problem in using "among" with arrays
On Friday, 29 July 2022 at 22:09:47 UTC, pascal111 wrote: I next code, we have a data type problem "54.among(to!uint[10](y)).writeln;": module main; import std.stdio; import std.string; import std.conv; import dcollect; import std.math; import std.algorithm; int main(string[] args) { int[] x=[23, 34,-88, 54, -90, -34]; auto y=x.filter!(a=>a<0); foreach(i; y) i.write(", "); 54.among(to!uint[10](y)).writeln; return 0; } Error message: "hello.d|19|error: only one index allowed to index void|" Did you mean `to!(uint[10])(y)`? This converts to `uint[10]`.
Is this a violation of const?
In the example below `func` changes its `const*` argument. Does this violates D's constness? ```d import std; struct S { string s; void delegate(string s) update; } void func(const S* s) { writeln(*s); s.update("func"); writeln(*s); } void main() { auto s = S("test"); s.update = (_) { s.s = _; }; writeln(s); func(); writeln(s); } ``` The output is: ``` S("test", void delegate(string)) const(S)("test", void delegate(string)) const(S)("func", void delegate(string)) S("func", void delegate(string)) ```
Re: Bug in dmd?
On Wednesday, 15 June 2022 at 16:53:13 UTC, mw wrote: Create a simple test case, file bug at: https://issues.dlang.org/ I tried. No luck.
Re: Bug in dmd?
On Wednesday, 15 June 2022 at 09:24:35 UTC, Dukc wrote: Now when I think of it, perhaps the fact that private `printHelp` has the same name as the public `printHelp` is somehow confusing dmd. If you try to rename the private `printHelp` and it's call in the public one to something else, you might get some insight on what triggers this behaviour. I tried `private void printHelp` -> `package void printHelp1`. It didn't help.
Re: Bug in dmd?
On Wednesday, 15 June 2022 at 09:21:28 UTC, user1234 wrote: On Tuesday, 14 June 2022 at 13:39:12 UTC, Andrey Zherikov wrote: I have [pretty simple code in my library](https://github.com/andrey- [Line (2) produces](https://github.com/andrey-zherikov/argparse/runs/6880350900?check_suite_focus=true#step:5:12) `undefined reference to '_D3std7sumtype__T7SumTypeTS8argparse4help2AATSQtQm2BBZQBl6__dtorMFNaNbNiNfZv'` (it demangles to `pure nothrow @nogc @safe void std.sumtype.SumType!(argparse.help.AA, argparse.help.BB).SumType.__dtor()`) If I comment line (2) then everything is good (no link errors). Note that there is the same code at (1) which doesn't produce any error. Any idea what's going on? That can be a template instance that's emitted somewhere else, i.e the thing is there but the mangle is different. maybe try to find if the dtor is there with `mn -S` on each object. Another thing to try in these situations is to see if that works with `-allinst`. I tried to call dmd the same way as dub does with `-allinst` added to all calls. Got the same linker issue. `nm` shows that `app.d` refers to dtor which is not defined in `.a`: ```bash $ nm .../liball_argparse.a|egrep 'argparse.+dtor' $ nm .../all_getting_started-basic.o|egrep 'argparse.+dtor' U _D3std7sumtype__T7SumTypeTS8argparse4help2AATSQtQm2BBZQBl6__dtorMFNaNbNiNfZv ```
Re: Bug in dmd?
On Wednesday, 15 June 2022 at 07:38:36 UTC, JG wrote: I tried to reproduce it but wasn't able (I guess it is some interplay with the rest of your code): I tried this first but got the same result as you. I think my small library overheats DMD's template engine.
Re: Bug in dmd?
On Tuesday, 14 June 2022 at 21:44:48 UTC, Dukc wrote: No idea. The functions seems indeed to be exactly the same, so I assume this is a DMD bug. It cannot be a bug in `std.sumtype`, since that would trigger in both of the templates. This definitely triggers some bug in DMD because this `private void printHelp ...` function is not really `private` as it's called from [another module](https://github.com/andrey-zherikov/argparse/blob/bug/source/argparse/internal.d#L786) and DMD doesn't catch this.
Bug in dmd?
I have [pretty simple code in my library](https://github.com/andrey-zherikov/argparse/blob/bug/source/argparse/help.d#L27-L47): ```d alias CC = SumType!(AA,BB); struct AA {} struct BB { CC[] c; } private void ppp(T, Output)(auto ref Output output, in CommandArguments!T cmd, in Config config) { auto cc = CC(AA()); // (1) } private void printHelp(T, Output)(auto ref Output output, in CommandArguments!T cmd, in Config config) { auto cc = CC(AA()); // (2) } void printHelp(T, Output)(auto ref Output output, in Config config) { ppp(output, CommandArguments!T(config), config); printHelp(output, CommandArguments!T(config), config); } ``` [Line (2) produces](https://github.com/andrey-zherikov/argparse/runs/6880350900?check_suite_focus=true#step:5:12) `undefined reference to '_D3std7sumtype__T7SumTypeTS8argparse4help2AATSQtQm2BBZQBl6__dtorMFNaNbNiNfZv'` (it demangles to `pure nothrow @nogc @safe void std.sumtype.SumType!(argparse.help.AA, argparse.help.BB).SumType.__dtor()`) If I comment line (2) then everything is good (no link errors). Note that there is the same code at (1) which doesn't produce any error. Any idea what's going on?
Re: Templatized delegates
On Tuesday, 31 May 2022 at 23:15:24 UTC, Andrey Zherikov wrote: On Tuesday, 31 May 2022 at 21:53:17 UTC, Paul Backus wrote: If you want compile-time polymorphism, three's no other way. Yes, I want compile-time polymorphism. In case if `S.doSomething` is NOT template function then the problem can be solved easily by wrapping access to `S` into another delegate: ```d import std.stdio: writeln; struct S { void doSomething(int value) { value.writeln; } } alias DG = void delegate (void delegate(int) doSomething); auto createDG(T)(T value) { return delegate (void delegate(int) doSomething) { doSomething(value); }; } struct R { DG dg; this(int value) { dg = createDG(value); } } void main() { auto r = R(5); S s; r.dg(_ => s.doSomething(_)); } ``` How to do the same for templated `S.doSomething`?
Re: Templatized delegates
On Tuesday, 31 May 2022 at 22:34:41 UTC, Christian Köstlin wrote: Would it help to not create the delegate in R's constructor, but feed the delegate into it (and create the delegate outside). This would also resemble your description (R is a delegate holder) more. That's possible but the problem is that `S` is part of `DG`.
Re: Templatized delegates
On Tuesday, 31 May 2022 at 21:53:17 UTC, Paul Backus wrote: If you want compile-time polymorphism, three's no other way. Yes, I want compile-time polymorphism. ```d import std.stdio; struct S { // function that should be called from delegate void doSomething(T)(T value) { value.writeln; } } interface I { void doSomething(int value); } class Adapter : I { S s; this(S s) { this.s = s; } void doSomething(int value) { s.doSomething(value); } } alias DG = void delegate (I i); auto createDG(int value) { return delegate (I i) { i.doSomething(value); }; } struct R { DG dg; this(int value) { dg = createDG(value); } } void main() { auto r = R(5); S s; r.dg(new Adapter(s)); } ``` Unfortunately this solution looses important feature: there is no more templated call to `S.doSomething` as `I.doSomething` is not template and adding override for every type is not maintainable.
Templatized delegates
I have tightly coupled code which I'd like to decouple but I'm a bit stuck. For simplicity, I reduced the amount of code to something simple to understand. So I have a struct `S` that has templated member function that does something. On the other side I have delegate holder `R` - this delegate takes `S` object as an argument and calls that function. My goal is to remove dependency from `R` to `S`. Here is code example: ```d import std.stdio: writeln; struct S { // function that should be called from delegate void doSomething(T)(T value) { value.writeln; } } alias DG = void delegate (ref S s); auto createDG(T)(T value) { return delegate (ref S s) { s.doSomething(value); }; } struct R { DG dg; this(int value) { dg = createDG(value); } } void main() { auto r = R(5); S s; r.dg(s); } ``` An obvious way is to add a type template parameter to `R`, `DG` and `createDG` but I would like to avoid this. Is there another way to do so? I think ideal solution would be having templatized delegate `void delegate (S)(ref S s)` and then call `r.dg!S(s)` but it's not available: `alias DG = void delegate (S) (ref S s)` gives unclear `Error: function declaration without return type. (Note that constructors are always named 'this')` message.
Re: How to fix "typesafe variadic function parameter"?
On Tuesday, 24 May 2022 at 22:51:50 UTC, Adam Ruppe wrote: On Tuesday, 24 May 2022 at 22:46:55 UTC, Andrey Zherikov wrote: return S(s); return S(s.dup); The variadic lives in a temporary array that expires at the end of the function. So copying it out to the GC lets it live on. Your code was wrong on 2.099 too, but the compiler didn't tell you. That works, thank you! Can this error message be improved some way so this fix becomes obvious?
How to fix "typesafe variadic function parameter"?
How to fix this? ```d struct S { string[] s; } auto foo(string[] s...) // Error: typesafe variadic function parameter `s` of type `string[]` cannot be marked `return` { return S(s); } void main() { import std.stdio: writeln; writeln(foo("Hello D")); } ``` This successfully compiles with dmd 2.099.1 but fails with 2.100.0 I tried to add `return`/`ref` but no luck.
Re: Is T.init allowed?
On Friday, 29 April 2022 at 12:05:35 UTC, Dennis wrote: On Friday, 29 April 2022 at 11:30:49 UTC, Andrey Zherikov wrote: Is it a compiler issue so this shouldn't be allowed? Members called `init` are in the process of being deprecated, see: https://github.com/dlang/dmd/pull/12512 That's nice!
Is T.init allowed?
Seems compiler allows custom nested type with `init` name: ```d struct T { struct init {} int b = 2; } void main() { T t; writeln(t);// T(2) //writeln(T.init); // Error: cannot pass type `init` as a function argument } ``` Is it a compiler issue so this shouldn't be allowed? If this is OK then how can I refer to an initial value of `T` (`T.init` doesn't work)?
Re: Calling template member function?
On Tuesday, 19 April 2022 at 20:29:01 UTC, Steven Schveighoffer wrote: You can work around the dual context, if you are OK with passing the second context explicitly. The easiest way is to move the member function to a UFCS function. an example: ```d struct X { int x; void applyToX(alias fn)() {fn(x);} } void applyToX_alt(alias fn)(ref X xval) { fn(xval.x); } void main() { auto s = X(5); int y = 6; void fn(ref int x) { x += y; } s.applyToX!fn; // error, dual context needed s.applyToX_alt!fn; // fine, only single context needed } ``` I used struct to understand the problem. I don't actually have an object context to pass like in your example, the only context I have is template parameters.
Re: Calling template member function?
On Tuesday, 19 April 2022 at 19:07:37 UTC, Ali Çehreli wrote: On 4/19/22 11:18, Andrey Zherikov wrote: > Is there a way/workaround to achieve the desired behavior? Can you describe the goal a little more. For example, I assume you really need a more useful lambda although the example you show seems unnecessary: enum dg = () => func(); That lambda looks suspiciously trivial. Will it actually need its context? Ali I have [old API function](https://github.com/andrey-zherikov/argparse/blob/master/source/argparse.d#L1228) that gets a function as a parameter and I want it to call (for backward compatibility) [new API function](https://github.com/andrey-zherikov/argparse/blob/remove-main/source/argparse.d#L1630) which accepts a function as a template parameter.
Re: Calling template member function?
I get the same error even with just `struct`: ```d struct S { static void f_new(alias func)() { func(); } } void f_new(alias func)() { func(); } void f(FUNC)(FUNC func) { f_new!(() => func()); // works // S.f_new!(() => func()); // doesn't work } ```
Re: Calling template member function?
On Tuesday, 19 April 2022 at 18:18:26 UTC, Andrey Zherikov wrote: Is there a way/workaround to achieve the desired behavior? Those two bugs pointed above were reported in 2017 and 2011 (!) which makes me think that they won't be fixed any time soon (I'm not sure that they are actually the same issue as I faced here). I tried to change the code to this: ```d void f(FUNC)(FUNC func) { enum dg = () => func(); T!int.f_new!dg; } ``` But I get this error: ``` onlineapp.d(7): Error: delegate `onlineapp.f!(void function() @safe).f.__lambda2` is a nested function and cannot be accessed from `onlineapp.T!int.f_new!(delegate () @safe { (*func)(); return ; } ).f_new` ```
Re: Calling template member function?
On Tuesday, 19 April 2022 at 16:38:42 UTC, Steven Schveighoffer wrote: On 4/19/22 11:46 AM, Paul Backus wrote: If you remove `static` from `f_new`, you get an error message talking about this explicitly: Interesting that `static` does anything there, since it's a no-op. -Steve I put `static` because it fixes "dual context" error. Is there a way/workaround to achieve the desired behavior? Those two bugs pointed above were reported in 2017 and 2011 (!) which makes me think that they won't be fixed any time soon (I'm not sure that they are actually the same issue as I faced here).
Calling template member function?
I want to migrate my library API from standalone function that takes delegate as argument to a template member function that takes delegate as a template parameter but compiler errors out. Here is code example: ```d import std.stdio; template T(P) { static void f_new(alias func)() { func(); } } void f(FUNC)(FUNC func) { T!int.f_new!(() => func()); } void main() { f(function () { __LINE__.writeln; }); } ``` Compiler error: ``` onlineapp.d(7): Error: `static` function `onlineapp.f!(void function() @safe).f.f_new!(delegate () @safe { (*func)(); return ; } ).f_new` cannot access delegate `__lambda2` in frame of function `onlineapp.f!(void function() @safe).f` onlineapp.d(13):`__lambda2` declared here onlineapp.d(13): Error: template instance `onlineapp.f!(void function() @safe).f.f_new!(delegate () @safe { (*func)(); return ; } )` error instantiating onlineapp.d(18):instantiated from here: `f!(void function() @safe)` ``` What confuses me a lot is that if I remove `template T` then everything works perfectly: ```d import std.stdio; void f_new(alias func)() { func(); } void f(FUNC)(FUNC func) { f_new!(() => func()); } void main() { f(function () { __LINE__.writeln; }); } ``` Is there an issue in template processing in compiler?
Re: How to unit-test behavior under "version"?
On Wednesday, 30 March 2022 at 04:15:24 UTC, Paul Backus wrote: Probably the easiest way is to split it into two functions ```d void f() { version (foo) fVersionFoo(); else fDefault(); } void fVersionFoo() { /* ... */ } void fDefault() { /* ... */ } ``` Then you can write separate unit tests for both `fVersionFoo` and `fDefault`, and they will both be tested regardless of what settings you build with. This is an option when you have big difference between foo and not-foo behavior. In my case they are 90% the same so I think I'll go this way: ```d void fImpl(bool fooMode)() { static if(fooMode) writeln("foo"); else writeln("no foo"); } version(foo) alias f = fImpl!true; else alias f = fImpl!false; unittest { // test fImpl!true } unittest { // test fImpl!false } ```
Re: How to unit-test behavior under "version"?
On Tuesday, 29 March 2022 at 20:20:46 UTC, Steven Schveighoffer wrote: So keep in mind that versions are *module-wide*, and usually *compilation-wide*. Which means that you won't be testing multiple version configurations in the same build. ... In the case where version is going to *affect the results of the function*, as yours does above, then what I would do is repeat the version tree as above, putting an individual unittest in each branch. But you could potentially do it inside the unittest itself. I just find that a bit convoluted. Right, I can do per-version unit tests and the question becomes how to build all versions. Since I'm using dub, there is a way to express different versions through "configuration" specs in dub.json. Is there a way to tell `dub test` to test all configurations?
How to unit-test behavior under "version"?
I have a function below (just an example). What's the recommended way to unit-test it for all `version` cases? ```d void f() { import std.stdio: writeln; version(foo) writeln("foo"); else writeln("no foo"); } ```
Re: Template with default parameter
On Friday, 11 March 2022 at 12:53:56 UTC, Adam D Ruppe wrote: On Friday, 11 March 2022 at 12:01:27 UTC, Andrey Zherikov wrote: There is some inconsistency between templates and template functions as this works as I want to: Yeah, functions have the special feature of implicit instantiation from the function arguments. No other template do, if you want an instance there, you need to specify it as a !(). And since functions can't return aliases to types you can't use that to get around it. There's no way to do what you want to do, you either need to write the !() or use a different alias name. Thanks for explanation!
Re: Template with default parameter
There is some inconsistency between templates and template functions as this works as I want to: ```d import std.stdio; void f(int i=3)() { writeln(i); } void main() { f!1; // 1 f!(); // 3 f;// 3 } ```
Re: Template with default parameter
On Friday, 11 March 2022 at 07:06:15 UTC, bauss wrote: Create an alias for T!() is the best you can do. Ex. ``` alias t = T!(); ``` There isn't really any better method as far as I know. I'd like to preserve the name (`t` != `T`) but `alias T = T!()` gives me `Error: declaration `T` is already defined`
Template with default parameter
I have simple template: ```d template T(int i=3) { mixin template M(int m) { enum t = i; } } { mixin T!1.M!1; pragma(msg, t); // 1 } { mixin T!().M!1; pragma(msg, t); // 3 } { mixin T.M!1; // Error: identifier `M` of `T.M` is not defined // Error: mixin `M!1` is not defined pragma(msg, t); // Error: undefined identifier `t` //while evaluating `pragma(msg, t)` } ``` What should I do to be able to write `T.M!...`? I want to omit verbose `!()` for `T`. Note that mixins are essential here.
Re: How to check that a member function is generated by compiler?
On Friday, 25 February 2022 at 16:24:46 UTC, Paul Backus wrote: On Friday, 25 February 2022 at 14:25:22 UTC, Andrey Zherikov wrote: Another interesting observation - is there any explanation why `typeof` returns different results for generated `opAssign`? [...] If I move `foreach` loop into a function (e.g. `main`) then the first pragma prints the same as the others. It sounds like this is probably an inconsistency in `.stringof`, not `typeof`. I couldn't say what causes it, but it's not the first time I've seen `.stringof` give inconsistent results. (E.g., https://issues.dlang.org/show_bug.cgi?id=18269) I see. Thanks
Re: How to check that a member function is generated by compiler?
On Friday, 25 February 2022 at 05:25:14 UTC, Ali Çehreli wrote: On 2/24/22 20:44, Andrey Zherikov wrote: How can I check that `opAssign` is generated by compiler and doesn't exist in the original code? I think this one: https://dlang.org/phobos/std_traits.html#hasElaborateAssign Ali This take a struct as an argument, not a member, so I need to do `if(sym == "opAssign")`. I gave this another thought and checking the symbol against `"opAssign"` would be good enough for my use case. Another interesting observation - is there any explanation why `typeof` returns different results for generated `opAssign`? ```d import std.sumtype: SumType; struct A { SumType!int b; } static foreach(sym; __traits(allMembers, A)) { // ref A(A p) return,opAssign pragma(msg, typeof(__traits(getMember, A, sym)).stringof,",",sym); // true,pure nothrow @nogc ref @safe A(A p) return,opAssign pragma(msg, is(typeof(__traits(getMember, A, sym)) == function),",", typeof(__traits(getMember, A, sym)).stringof,",",sym); // pure nothrow @nogc ref @safe A(A p) return,opAssign pragma(msg, typeof(__traits(getMember, A, sym)).stringof,",",sym); } ``` If I move `foreach` loop into a function (e.g. `main`) then the first pragma prints the same as the others.
How to check that a member function is generated by compiler?
This code ```d import std.sumtype: SumType; struct A { SumType!int b; } static foreach(sym; __traits(allMembers, A)) pragma(msg,sym); ``` prints ``` b opAssign ``` How can I check that `opAssign` is generated by compiler and doesn't exist in the original code?
Re: keyword as struct field
On Sunday, 20 February 2022 at 11:08:55 UTC, partypooper wrote: Hello, I'm new to D. Title is self described, is it possible to use keyword as struct field? Maybe it is XYproblem, so here I will describe a little what I need. I'm parsing some json currently with [mir-ion](https://code.dlang.org/packages/mir-ion) (better/simpler suggestions for only json de/serialization?), that has "version" as one of it's keys, so I can't use that as field in my struct. Maybe some annotation in mir library to parse "version" into other struct field name, can't find though (its docs pretty concise). Unfortunately I'm not able to help you with mir-ion. But I see two questions here: keyword as struct field I believe this is the case for the most languages - keyword is not allowed as a variable name. usage of `version` keyword as a variable name IMO having `version` keyword in D is unexpected language design. No one will complain about keywords that are widely used in the industry (like `struct`, `int` etc). But `version`?! I hit this problem multiple times already and the only solution for me was to use `version_` instead.
Re: Member function forwarding
On Thursday, 17 February 2022 at 20:59:43 UTC, Andrey Zherikov wrote: Another question: does `auto foo(ARGS...)(ARGS args) { return a.foo(args); }` correctly forward `ref`, `const` etc. arguments? Actually the answer is `NO`. I have to do `auto foo(ARGS...)(auto ref ARGS args) { return a.foo(args); }`. Also if `a.foo` is a `const` function then I have to add `const` to this definition as well.
Member function forwarding
I have a struct that has struct data member and I'd like to forward some (not all) functions from internal data member. Some thing like this: ```d struct A { void foo() const { writeln("A.foo"); } } struct B { A a; auto foo(ARGS...)(ARGS args) { return a.foo(args); } // alias foo = a.foo; } void main() { B b; b.foo(); // In "alias" case: Error: `this` for `foo` needs to be type `A` not type `B` } ``` Is there simpler way to achieve this? I tried `alias foo = a.foo` but it doesn't work: "Error: `this` for `foo` needs to be type `A` not type `B`" - when function is called (`b.foo()`). Another question: does `auto foo(ARGS...)(ARGS args) { return a.foo(args); }` correctly forward `ref`, `const` etc. arguments?
Re: Template sequence parameter and default value
On Thursday, 27 January 2022 at 03:19:59 UTC, Jaime wrote: You can accomplish this by heading off the template sequence parameter with several default template parameters. If you need them all under one name, you can recombine them in the function body with std.meta.AliasSeq, the effective "kind" of a template sequence parameter. Example: ```d void foo(string FirstModule = __MODULE__, RestModules...)() { alias Modules = AliasSeq!(FirstModule, RestModules); // things } // foo!(module1, module2) => alias Modules = (module1, module2) // foo!() => alias Modules = (__MODULE__) ``` Unfortunately `string FirstModule` doesn't work if I specify the module: https://run.dlang.io/is/BZd0KB The closest solution I have is this: ```d void foo(MODULES...)() { writeln(MODULES.stringof); } alias foo(string MODULE = __MODULE__) = foo!(mixin(MODULE)); void main() { writeln(1); foo(); writeln(2); foo!(onlineapp); writeln(3); foo!(onlineapp,onlineapp); } ``` It prints this: ``` 1 tuple(module onlineapp) 2 tuple(module onlineapp) 3 tuple(module onlineapp, module onlineapp) ``` So is it possible to get rid of the alias?
Template sequence parameter and default value
What is the best way to emulate a default value for template sequence parameter of a function? I want something like this: ```d void foo(MODULES... = __MODULE__)() {} // these should work: foo!(module1, module2); foo!(module1); foo(); // this should use current module (__MODULE__) according to default value ```
Re: Any workaround for "closures are not yet supported in CTFE"?
On Wednesday, 8 December 2021 at 17:05:49 UTC, Timon Gehr wrote: ```d import std.stdio, std.traits, core.lifetime; auto partiallyApply(alias fun,C...)(C context){ return class(move(context)){ C context; this(C context) { foreach(i,ref c;this.context) c=move(context[i]); } auto opCall(ParameterTypeTuple!fun[context.length..$] args) { return fun(context,forward!args); } }.opCall; } alias Action = void delegate(); Action createDelegate(string s){ import std.stdio; return partiallyApply!((string str) => writeln(str))(s); } struct A{ Action[] dg; } A create(){ A a; a.dg ~= createDelegate("hello"); a.dg ~= createDelegate("buy"); return a; } void main(){ enum a = create(); foreach(dg; a.dg) dg(); } ``` This is great, thanks you!
Re: Any workaround for "closures are not yet supported in CTFE"?
On Tuesday, 7 December 2021 at 18:50:04 UTC, Ali Çehreli wrote: I don't know whether the workaround works with your program but that delegate is the equivalent of the following struct (the struct should be faster because there is no dynamic context allocation). Note the type of 'dg' is changed accordingly: The problem with struct-based solution is that I will likely be stuck with only one implementation of delegate (i.e. opCall implementation). Or I'll have to implement dispatching inside opCall based on some "enum" by myself which seems weird to me. Do I miss anything?
Any workaround for "closures are not yet supported in CTFE"?
I have a struct `A` that stores delegates. The problem is that I'm getting "`Error: closures are not yet supported in CTFE`" if I create an compile-time constant value of type `A`: ```d struct A { void delegate()[] dg; } auto createDelegate(string s) { return { s.writeln; }; // Error: closures are not yet supported in CTFE } A create() { A a; a.dg ~= createDelegate("hello"); a.dg ~= createDelegate("buy"); return a; } void main() { enum a = create(); // If change 'enum' to 'auto' then everything works foreach(dg; a.dg) dg(); } ``` How can I workaround this and have compile-time object with delegates?
Re: need `this` on trying to use class method with parallelism Task! or task!
On Sunday, 14 November 2021 at 16:55:24 UTC, Alexey wrote: Remove "!"
Re: need `this` on trying to use class method with parallelism Task! or task!
On Sunday, 14 November 2021 at 14:41:21 UTC, Alexey wrote: On Sunday, 14 November 2021 at 14:24:00 UTC, Andrey Zherikov wrote: On Sunday, 14 November 2021 at 12:01:36 UTC, Alexey wrote: You just need two changes: - make `threadFunc` function static: `static void threadFunc()` - use `task` instead of `Task`: `auto t1 = task!threadFunc;` I need `this` to be available inside of threadFunc Just do `auto t1 = task()` in `threadCreator` then.
Re: need `this` on trying to use class method with parallelism Task! or task!
On Sunday, 14 November 2021 at 12:01:36 UTC, Alexey wrote: You just need two changes: - make `threadFunc` function static: `static void threadFunc()` - use `task` instead of `Task`: `auto t1 = task!threadFunc;`
Re: How to get the location (file, line) of UDA without parens?
On Sunday, 14 November 2021 at 07:06:25 UTC, user1234 wrote: On Sunday, 14 November 2021 at 05:12:58 UTC, Andrey Zherikov wrote: Here is my code: [...] `W()` (2) works as expected but is it possible to achieve the same without parenthesis so `getAttributes` trait returns `tuple(L("app.d", 16LU))` for (1)? No, without parens this is really the function template, as a symbol, that becomes the UDA. Can this be achieved with any other type of `W`? For example I can get the same result with struct (also changing `@W()` to `@W!()` on line (2)): ```d struct W(string f = __FILE__, size_t l = __LINE__) { auto loc = L(f,l); } ```
How to get the location (file, line) of UDA without parens?
Here is my code: ```d struct L { string file; size_t line; } auto W(string f = __FILE__,size_t l= __LINE__)() { return L(f,l); } struct A { @W // (1): line# 16 { int a; int b; } @W() // (2): line# 21 { int c; int d; } } void main() { pragma(msg, __traits(getAttributes, A.a)); // tuple(W(string f = __FILE__, ulong l = __LINE__)()) pragma(msg, __traits(getAttributes, A.b)); // tuple(W(string f = __FILE__, ulong l = __LINE__)()) pragma(msg, __traits(getAttributes, A.c)); // tuple(L("app.d", 21LU)) pragma(msg, __traits(getAttributes, A.d)); // tuple(L("app.d", 21LU)) } ``` `W()` (2) works as expected but is it possible to achieve the same without parenthesis so `getAttributes` trait returns `tuple(L("app.d", 16LU))` for (1)?
Re: How to return a reference to structs?
On Saturday, 6 November 2021 at 13:57:47 UTC, Ali Çehreli wrote: Have you considered std.range.indexed, which should at least cover the case of accessing: https://dlang.org/phobos/std_range.html#indexed I don't need to iterate over whole collection, but subset of it. Can you give a little more context for others to come up with a better answer? I have a [CLI-parsing library](https://github.com/andrey-zherikov/argparse) that creates a set of argument objects based on UDAs. They are [stored in array](https://github.com/andrey-zherikov/argparse/blob/master/source/argparse.d#L436) right now. I want to introduce some grouping having something like `struct Group { size_t[] args; }` but face the problem of addressing the objects. As of now I need to be able to iterate over the arguments within a group as well as those that satisfy some condition.
Re: How to return a reference to structs?
On Saturday, 6 November 2021 at 04:28:05 UTC, Ali Çehreli wrote: On 11/5/21 5:43 PM, Andrey Zherikov wrote: In case others want to work, here are the modules that need to be imported: import std.algorithm; import std.range; import std.stdio; > struct A {} > struct B > { > A[] ar = [A.init]; > size_t[] idx = [0]; I don't know why but those initial values are the reason for the problem. It works without them. `get()` will return nothing in this case. But I can make them non empty in another way: ```d import std; struct A {} struct B { A[] ar; size_t[] idx; A*[] get() { return idx.map!((idx) => [idx]).array; } } auto foo() { B b; b.ar ~= A.init; b.idx ~= 0; return b.get(); } void main() { writeln(foo()); pragma(msg, foo()); } ``` Some one can complain that `foo()` returns pointers that are not available in CTFE but remember that the real code is more complex and `foo()` cam be return just length (`return b.get().length;`) having the same result. Basically I have a collection of data (`A[] ar`), different addressing through the indexes (multiple `size_t[] idx`) and I want to manipulate these objects through indexes. If there is another way to achieve the same in CFTE, I'd like to hear.
Re: How to return a reference to structs?
On Friday, 5 November 2021 at 20:13:02 UTC, Andrey Zherikov wrote: On Friday, 5 November 2021 at 19:49:50 UTC, Ali Çehreli wrote: Indexes are typed as size_t, which is ulong for 64-bit and uint for 32-bit. If idx elements were indeed indexes, it should have been typed as size_t: size_t[] idx = [1,3,4]; // <-- Here Ah, good point. Thanks! Adding a bit of CTFE: ```d struct A {} struct B { A[] ar = [A.init]; size_t[] idx = [0]; A*[] get() { return idx.map!((idx) => [idx]).array; // Error: couldn't find field `ar` of type `A[]` in `MapResult([0LU], null)` } } auto foo() { B b; return b.get(); } void main() { writeln(foo()); // This works pragma(msg, foo()); // This doesn't work } ``` How to make this work?
Re: How to return a reference to structs?
On Friday, 5 November 2021 at 19:49:50 UTC, Ali Çehreli wrote: Indexes are typed as size_t, which is ulong for 64-bit and uint for 32-bit. If idx elements were indeed indexes, it should have been typed as size_t: size_t[] idx = [1,3,4]; // <-- Here Ah, good point. Thanks!
Re: How to return a reference to structs?
On Thursday, 4 November 2021 at 13:03:54 UTC, Paul Backus wrote: On Thursday, 4 November 2021 at 11:26:30 UTC, Andrey Zherikov wrote: I have the following code example: ```d struct A{} A[5] a; ulong[] idx = [1,3,4]; auto get() { return idx.map!(_ => a[_]); } foreach(i; 0 .. a.length) write([i], " "); writeln; foreach(ref b; get()) write(, " "); writeln; ``` How can I change `get` function so it returns the references to the content in `a`? Have the lambda return by reference: ```d auto get() { return idx.map!(ref (i) => a[i]); } ``` Making this example a bit complex: I want `get` to return additional data to the reference. How should I change the lambda then? ```d auto get() { return idx.map!(ref (i) => tuple(a[i], i)); // return ref and index for simplicity } ```
Re: How do you declare manifest constants?
On Thursday, 4 November 2021 at 17:09:31 UTC, Steven Schveighoffer wrote: D doesn't have any equivalent for this. Is it possible to add this feature having `-C VERSION="1.2.3"` (`-D` is already used) to be equal to `enum VERSION="1.2.3"` in global namespace? The closest you can get is to turn on `version` identifiers. There is also a quirky `-version=123` which is IMO, a completely useless feature. I agree - this is useless. `-version myversion=123` would be much more useful. Note, there is at least one dub package which does this for you: https://code.dlang.org/packages/gen-package-version Unfortunately git/hg tags is not the only possible source of manifest constants.
How do you declare manifest constants?
I want to embed some info from build system - version info, for example. I can easily do this with C++ compiler by `-DVERSION="1.2.3"` but there is no such an option in dmd. So I'm wondering how do people workaround this? I see only one way: generate a file and add it to the build (file might be `.d` source or something included by import expression).
Re: How to return a reference to structs?
On Thursday, 4 November 2021 at 13:03:54 UTC, Paul Backus wrote: Have the lambda return by reference: ```d auto get() { return idx.map!(ref (i) => a[i]); } ``` That works, thanks!
How to return a reference to structs?
I have the following code example: ```d struct A{} A[5] a; ulong[] idx = [1,3,4]; auto get() { return idx.map!(_ => a[_]); } foreach(i; 0 .. a.length) write([i], " "); writeln; foreach(ref b; get()) write(, " "); writeln; ``` How can I change `get` function so it returns the references to the content in `a`? Is there a good documentation describing how to avoid copying of structs in the code?
Re: Does associative array change the location of values?
On Saturday, 30 October 2021 at 00:52:23 UTC, Imperatorn wrote: On Saturday, 30 October 2021 at 00:49:04 UTC, Stanislav Blinov wrote: On Friday, 29 October 2021 at 21:00:48 UTC, Steven Schveighoffer wrote: This is incorrect, the buckets are each heap allocated. Just the array of bucket pointers would change. In addition, AAs do not deallocate the key/value pairs ever. You are safe to obtain a pointer to a value and it will stay there, even if you remove the key. Who's going to document these implementation details? ;) I mean, if no one, then the above shouldn't be stated. Wouldn't you agree? Given the premise of the question at hand, it does seem useful to know these. But at least one should stress what is and isn't subject to change (even if unlikely). This should be documented for sure I did small test and it printed the same values three times so even rehash doesn't change the address of the value: ```d long[long] aa = [0:0]; writeln([0]); foreach(i; 0 .. 100_000_000) aa[i]=i; writeln([0]); aa.rehash; writeln([0]); ``` So it seems pretty safe to store a pointer to a value in AA. And I agree that this should definitely be documented.
Re: Does associative array change the location of values?
On Friday, 29 October 2021 at 17:58:24 UTC, Paul Backus wrote: No, the AA does not guarantee that the value will remain in the same location. Inserting or removing *any* keys could cause the AA to resize, which may change the locations of all of its values. However, you do not have to worry about undefined behavior, because the garbage collector will keep the "stale" copy of the value alive as long as you hold a pointer to it. Thanks a lot for clarification
Does associative array change the location of values?
I want to have a pointer to a value in an associative array. Does AA guarantee that the value will remain at the same address all the time unless I remove the corresponding key? I couldn't find any guarantees similar to C++ iterator invalidation in D Language Reference.
Re: Cannot access frame pointer of a struct with member function
On Sunday, 9 May 2021 at 17:53:07 UTC, SealabJaster wrote: On Sunday, 9 May 2021 at 17:37:40 UTC, Andrey Zherikov wrote: Is this a bug? My best guess is that, since the struct doesn't have any member functions the compiler has decided that the struct doesn't need any access to the main function's context/frame pointer, so the struct has implicitly become a `static struct`. Marking the struct `static` yourself while keeping the member function, will show that it can then compile. You can also move your `foo` function into the main function and it'll compile. Oddly the output ends up becoming: `T(1, null)` which I didn't really expect. Just a guess though. That's a point! Thanks you!
Cannot access frame pointer of a struct with member function
Compilation of this code: ```d auto foo(T)() { return T(); // Error: cannot access frame pointer of `onlineapp.main.T` } void main() { struct T { int a=1; void argsFunc(int a) {} // (1) } pragma(msg,foo!T()); } ``` fails with this error: ``` onlineapp.d(3): Error: cannot access frame pointer of `onlineapp.main.T` onlineapp.d(14): Error: template instance `onlineapp.foo!(T)` error instantiating onlineapp.d(14):while evaluating `pragma(msg, foo!(T)())` ``` But when I comment out argsFunc function on line (1), it compiles successfully meaning that there is no issue to access frame pointer. Is this a bug?