Re: Giant template - changing types everywhere
On Friday, 14 July 2023 at 05:09:58 UTC, Cecil Ward wrote: On Friday, 14 July 2023 at 05:05:27 UTC, Cecil Ward wrote: On Friday, 14 July 2023 at 05:03:31 UTC, Cecil Ward wrote: On Friday, 14 July 2023 at 01:34:54 UTC, Steven Schveighoffer wrote: [...] The way I can see it going is a giant template encompassing pretty much the whole file. Does that mean that the caller who calls my one public function does so by passing the type dchar or wchar ? And then we generate the strings from that. It might be rather more natural for the caller to pass one of the string types into the template. That’s where I get rather more confused, say caller calls Transform(dstring)(dstring str) or can they just do Transform( "str"d ) and it would work out that the type is immutable dchar[] ? Perhaps I should just make up a small example file with two functions in it to see if I can get the syntax right? If I wrap the whole thing with a template declaration of the xchar type, then can I get away with no changes to the individual function definitions? I tried it, wrapped the whole thing in a template definition and it compiled, but then my test file which calls Transform( someDString ) failed to compile with errors saying it couldn’t find the definition of Transform in the other module, which is or was public. It’s as if it is no longer public because it’s now inside the template.
Re: Giant template - changing types everywhere
On Friday, 14 July 2023 at 05:05:27 UTC, Cecil Ward wrote: On Friday, 14 July 2023 at 05:03:31 UTC, Cecil Ward wrote: On Friday, 14 July 2023 at 01:34:54 UTC, Steven Schveighoffer wrote: [...] The way I can see it going is a giant template encompassing pretty much the whole file. Does that mean that the caller who calls my one public function does so by passing the type dchar or wchar ? And then we generate the strings from that. It might be rather more natural for the caller to pass one of the string types into the template. That’s where I get rather more confused, say caller calls Transform(dstring)(dstring str) or can they just do Transform( "str"d ) and it would work out that the type is immutable dchar[] ? Perhaps I should just make up a small example file with two functions in it to see if I can get the syntax right? If I wrap the whole thing with a template declaration of the xchar type, then can I get away with no changes to the individual function definitions?
Re: Giant template - changing types everywhere
On Friday, 14 July 2023 at 05:03:31 UTC, Cecil Ward wrote: On Friday, 14 July 2023 at 01:34:54 UTC, Steven Schveighoffer wrote: [...] The way I can see it going is a giant template encompassing pretty much the whole file. Does that mean that the caller who calls my one public function does so by passing the type dchar or wchar ? And then we generate the strings from that. It might be rather more natural for the caller to pass one of the string types into the template. That’s where I get rather more confused, say caller calls Transform(dstring)(dstring str) or can they just do Transform( "str"d ) and it would work out that the type is immutable dchar[] ? Perhaps I should just make up a small example file with two functions in it to see if I can get the syntax right?
Re: Giant template - changing types everywhere
On Friday, 14 July 2023 at 01:34:54 UTC, Steven Schveighoffer wrote: On 7/13/23 8:08 PM, Cecil Ward wrote: What I really want to do though is provide one single templated function with the kind of characters / strings as a parameter. I want to have something like T Transform( T )( T str) called as auto result = Transform!(dstring)( dstring str ); ```d T[] Transform(T)(T[] str) ``` Note that you don't have to specify the type when calling: ```d Transform(someDstring); // infers dchar ``` I’m quite confused as to how to proceed. This is quite a large module ~ 2k loc, and I don’t really want to go through and change every private function into a templated one. Should I just make the whole thing into a giant template containing many functions? If you have more questions, please ask. Some examples of how making a template would be painful would be helpful. -Steve The way I can see it going is a giant template encompassing pretty much the whole file. Does that mean that the caller who calls my one public function does so by passing the type dchar or wchar ? And then we generate the strings from that. It might be rather more natural for the caller to pass one of the string types into the template. That’s where I get rather more confused, say caller calls Transform(dstring)(dstring str) or can they just do Transform( "str"d ) and it would work out that the type is immutable dchar[] ?
Re: Giant template - changing types everywhere
On 7/13/23 8:08 PM, Cecil Ward wrote: What I really want to do though is provide one single templated function with the kind of characters / strings as a parameter. I want to have something like T Transform( T )( T str) called as auto result = Transform!(dstring)( dstring str ); ```d T[] Transform(T)(T[] str) ``` Note that you don't have to specify the type when calling: ```d Transform(someDstring); // infers dchar ``` I’m quite confused as to how to proceed. This is quite a large module ~ 2k loc, and I don’t really want to go through and change every private function into a templated one. Should I just make the whole thing into a giant template containing many functions? If you have more questions, please ask. Some examples of how making a template would be painful would be helpful. -Steve
Giant template - changing types everywhere
Some advice on a couple of points. I have been working on a module that works on either dchar / dstrings or wchar / wstrings with just two changes of alias definitions and a recompile. What I really want to do though is provide one single templated function with the kind of characters / strings as a parameter. I want to have something like T Transform( T )( T str) called as auto result = Transform!(dstring)( dstring str ); I only want to have one type as a parameter and derive other types from that: xstrings from xchars and I’ll need types of xchar arrays that are mutable and immutable. I’m quite confused as to how to proceed. This is quite a large module ~ 2k loc, and I don’t really want to go through and change every private function into a templated one. Should I just make the whole thing into a giant template containing many functions?
Re: On assigning const to immutable
On Thursday, 13 July 2023 at 11:55:17 UTC, Ki Rill wrote: Why does the first example `class A` work, but the second one with `class B` does not? ```D class A { immutable int a; this(in int a) { this.a = a; } } class B { immutable int[] b; this(in int[] b) { this.b = b; } } void main() { auto a = new A(1); auto b = new B([1, 2]); } ``` It implicitly converts `const` to `immutable`, but fails to do the same with an array. Is it intentional? Why? Yep: `immutable` is data that *cannot ever* change. If you could convert `int[]` to `immutable int[]`, you could do this: ``` int[] a = [2]; immutable(int)[] b = a; auto first = b[0]; a[0] = 3; auto second = b[0]; // Wait, this fails? I thought `b` was immutable. assert(first == second); ``` Use `array.idup` (immutable dup) to turn `int[]` into `immutable int[]`. And you can convert `int` to `immutable int` because it's a "value copy": you cannot mutate the immutable variable through an assignment to the original. Generally speaking, only the constness of referenced data matters for assignment. That's why you can assign `string` to `immutable string`, because `string` is `immutable(char)[]`: the referenced data is immutable in both cases.
Re: On assigning const to immutable
On Thursday, 13 July 2023 at 11:55:17 UTC, Ki Rill wrote: Why does the first example `class A` work, but the second one with `class B` does not? ```D class A { immutable int a; this(in int a) { this.a = a; } } class B { immutable int[] b; this(in int[] b) { this.b = b; } } void main() { auto a = new A(1); auto b = new B([1, 2]); } ``` It implicitly converts `const` to `immutable`, but fails to do the same with an array. Is it intentional? Why? Oh, is it because the first one is passed by value, but the second one is a reference?
On assigning const to immutable
Why does the first example `class A` work, but the second one with `class B` does not? ```D class A { immutable int a; this(in int a) { this.a = a; } } class B { immutable int[] b; this(in int[] b) { this.b = b; } } void main() { auto a = new A(1); auto b = new B([1, 2]); } ``` It implicitly converts `const` to `immutable`, but fails to do the same with an array. Is it intentional? Why?
Re: getOverloads order
On Thursday, 13 July 2023 at 11:04:40 UTC, IchorDev wrote: However, the spec doesn't specify that this is how `getOverloads` **must** work; is this guaranteed behaviour but the spec simply omits it? The order is not guaranteed. I don't know why you need a specific order, but perhaps you can sort based on `__traits(getLocation)`.
Re: getOverloads order
On Thursday, 13 July 2023 at 10:53:49 UTC, Dennis wrote: On Thursday, 13 July 2023 at 08:03:02 UTC, IchorDev wrote: I've noticed that `__traits(getOverloads)` always returns the overloads in lexical order across DMD, LDC, and GDC. Is this reliable at all? No. It depends on the order the compiler analyzes the symbols, which is often lexical order, but it can vary based on static if, mixin, forward references etc. Here's a counter example: ```D void f(int x); mixin("void f(float y);"); void f(char z); ``` Here you get overloads of `f` in the order (x, z, y) instead of (x, y, z). Well that makes sense, but also wouldn't apply to the use-case that I was considering, since all the code would be in one mixin. However, the spec doesn't specify that this is how `getOverloads` **must** work; is this guaranteed behaviour but the spec simply omits it?
Re: getOverloads order
On Thursday, 13 July 2023 at 08:03:02 UTC, IchorDev wrote: I've noticed that `__traits(getOverloads)` always returns the overloads in lexical order across DMD, LDC, and GDC. Is this reliable at all? No. It depends on the order the compiler analyzes the symbols, which is often lexical order, but it can vary based on static if, mixin, forward references etc. Here's a counter example: ```D void f(int x); mixin("void f(float y);"); void f(char z); ``` Here you get overloads of `f` in the order (x, z, y) instead of (x, y, z).
getOverloads order
I've noticed that `__traits(getOverloads)` always returns the overloads in lexical order across DMD, LDC, and GDC. Is this reliable at all?