Re: simple (I think) eponymous template question ... what is proper idimatic way ?
On Wednesday, 18 August 2021 at 05:33:13 UTC, james.p.leblanc wrote: On Tuesday, 17 August 2021 at 20:28:20 UTC, Alexandru Ermicioi wrote: On Tuesday, 17 August 2021 at 19:53:52 UTC, james.p.leblanc wrote: Wow! That is absolutely beautiful ... I had never seen (or even imagined) a recursive template! This expands my mind in a good way ... and is going into my toolbox immediately. Best Regards, James Just don't over rely on it. It can cause compilation slowdowns, so avoid it if you can. I've been happily trying to absorb all the helpful concepts posted. A final related question in the quest for simplicity and robustness. If I wanted to ensure that a function accepts only arguments of byte, int, uint, long, etc. (i.e. integer-like types). Is the accepted way to do this like so?: **auto foo( T : long )(T a, T b){ ... }** I really wish I could find a good explanation of the ":" (colon) used in templates. I am sure one exists ...but haven't come upon it just yet. (I thought "isIntegral" in traits module would be helpful...but I failed in my experiments.) Thanks for patience with this question! Best Regards, James A template specialization is basically a template overload. For example: ```d void func(int a){ writeln("argument is integer"); } void func(long a){ writeln("argument is long"); } void main(){ int a; long b; func(a); func(b); } ``` The above does what you expect. Now the template specialization way: ```d void funcTemplate(T:int)(T a){ writeln("argument is int"); } void funcTemplate(T : long)(T a){ writeln("argument is long"); } void main(){ int c; long d; funcTemplate(c); funcTemplate(d); } ``` The above will also do what you expect. Template specialization is basically overloading for templates, nothing more. Below is a complete working copy-paste example combining both: ```d import std; void func(int a){ writeln("argument is integer"); } void func(long a){ writeln("argument is long"); } void funcTemplate(T:int)(T a){ writeln("argument is int"); } void funcTemplate(T : long)(T a){ writeln("argument is long integer"); } void main(){ int a; long b; func(a); func(b); funcTemplate(a); funcTemplate(b); } ```
Re: simple (I think) eponymous template question ... what is proper idimatic way ?
On Wednesday, 18 August 2021 at 05:33:13 UTC, james.p.leblanc wrote: If I wanted to ensure that a function accepts only arguments of byte, int, uint, long, etc. (i.e. integer-like types). Is the accepted way to do this like so?: **auto foo( T : long )(T a, T b){ ... }** I very much prefer the ususal constraint syntax **auto foo(T)(T a, T b) if(isIntegral!T) { ... }**
Re: simple (I think) eponymous template question ... what is proper idimatic way ?
On Tuesday, 17 August 2021 at 20:28:20 UTC, Alexandru Ermicioi wrote: On Tuesday, 17 August 2021 at 19:53:52 UTC, james.p.leblanc wrote: Wow! That is absolutely beautiful ... I had never seen (or even imagined) a recursive template! This expands my mind in a good way ... and is going into my toolbox immediately. Best Regards, James Just don't over rely on it. It can cause compilation slowdowns, so avoid it if you can. I've been happily trying to absorb all the helpful concepts posted. A final related question in the quest for simplicity and robustness. If I wanted to ensure that a function accepts only arguments of byte, int, uint, long, etc. (i.e. integer-like types). Is the accepted way to do this like so?: **auto foo( T : long )(T a, T b){ ... }** I really wish I could find a good explanation of the ":" (colon) used in templates. I am sure one exists ...but haven't come upon it just yet. (I thought "isIntegral" in traits module would be helpful...but I failed in my experiments.) Thanks for patience with this question! Best Regards, James
Re: Concurrency message passing
On 8/17/21 2:36 PM, JG wrote: Thanks for the suggestions and explanations. I am not sure what to do in my case though. The situation is as follows. I have a struct that is populated via user input not necessarily at single instance (so that seems to rule out immutable). On the other hand while it is being populate it is only accessible from one thread so that makes using shared messy. After being populated it should be passed to the other thread and no references are kept. You are allowed to cast to immutable if no other mutable references are used. I recommend using `assumeUnique`. What I am doing currently is populating the struct and casting to shared when I push into a synchronized queue (no references to its data are kept in the first thread). Is what I am doing wrong and can it be achieved using message passing? Yeah, build it like Ali says, and then cast in order to pass it. -Steve
Re: simple (I think) eponymous template question ... what is proper idimatic way ?
On Tuesday, 17 August 2021 at 20:29:51 UTC, james.p.leblanc wrote: So, below is my code: import std.stdio; import std.meta : AliasSeq; template isAmong(T, S...) { static if (S.length == 0) enum isAmong = false; else enum isAmong = is(T == S) || isAmong(T, S[1..$]); } alias MyTypes = AliasSeq!(int, float); auto myFunc(T)(T a, T b) if (isAmong!(T, MyTypes)) { writeln(" in myFunc "); return; } void main(){ writeln("started ..."); auto a = 1; auto b = 2; myFunc!(int)(a, b); return; } And, here are the error message: (master) Notes > dmd recursive_template.d recursive_template.d(9): Error: circular reference to variable `recursive_template.isAmong!(int, int, float).isAmong` recursive_template.d(17): Error: template instance `recursive_template.isAmong!(int, int, float)` error instantiating recursive_template.d(29):while looking for match for `myFunc!int` Can anyone see what is going on? Best Regards, James https://run.dlang.io/is/m5svQ2 The error was in line 8. T (Teoh) forgot to take the first of `S` in `is(T == S[0])`. The error message improves after adding the `!` in `isAmong!(T, S[1..$])`, which, surprisingly, is optional! — Bastiaan.
Re: simple (I think) eponymous template question ... what is proper idimatic way ?
On Tue, Aug 17, 2021 at 07:53:52PM +, james.p.leblanc via Digitalmars-d-learn wrote: > On Tuesday, 17 August 2021 at 19:44:29 UTC, H. S. Teoh wrote: > > You could use a helper template and an AliasSeq for this: > > > > template isAmong(T, S...) { > > static if (S.length == 0) > > enum isAmong = false; > > else > > enum isAmong = is(T == S) || > > isAmong(T, S[1..$]); > > } > > > > import std.meta : AliasSeq; > > alias MyTypes = AliasSeq!(int, float, MySpecialStruct); > > > > auto myFunc(T)(T a, T b) if (isAmong!(T, MyTypes)) { ... } [...] > Dear H.S. Teoh, > > Wow! That is absolutely beautiful ... I had never seen (or even > imagined) a recursive template! This expands my mind in a good > way ... and is going into my toolbox immediately. [...] I didn't want to spoil your joy of discovery, but since others have already done that -- beware of recursive templates, because if used too often they can become a source of big slowdowns to your compilation times (as well as the compiler consuming ridiculous amounts of memory). Simple, linearly-recursive templates like this one are probably harmless (unless you artificially generate pathologically-long lists of types). But if the recursion gets too deep or grows superlinearly, you probably want to consider alternative implementations instead. ;-) --T
Re: simple (I think) eponymous template question ... what is proper idimatic way ?
On Tuesday, 17 August 2021 at 20:13:59 UTC, Paul Backus wrote: FYI: in this particular case, you can use std.meta.staticIndexOf instead of writing the recursion out yourself: import std.meta: staticIndexOf; enum isAmong(T, S...) = staticIndexOf!(T, S) >= 0; Docs: https://phobos.dpldocs.info/std.meta.staticIndexOf.html All, Thanks again ... Paul, I will try this staticIndexOf as you mention. I had been receiving "circular reference to variable" error messages from the "isAmong" suggestion. (But, I very likely had misunderstood how to use this.) I would still be interested to learn what I have done wrong. So, below is my code: import std.stdio; import std.meta : AliasSeq; template isAmong(T, S...) { static if (S.length == 0) enum isAmong = false; else enum isAmong = is(T == S) || isAmong(T, S[1..$]); } alias MyTypes = AliasSeq!(int, float); auto myFunc(T)(T a, T b) if (isAmong!(T, MyTypes)) { writeln(" in myFunc "); return; } void main(){ writeln("started ..."); auto a = 1; auto b = 2; myFunc!(int)(a, b); return; } And, here are the error message: (master) Notes > dmd recursive_template.d recursive_template.d(9): Error: circular reference to variable `recursive_template.isAmong!(int, int, float).isAmong` recursive_template.d(17): Error: template instance `recursive_template.isAmong!(int, int, float)` error instantiating recursive_template.d(29):while looking for match for `myFunc!int` Can anyone see what is going on? Best Regards, James
Re: simple (I think) eponymous template question ... what is proper idimatic way ?
On Tuesday, 17 August 2021 at 19:53:52 UTC, james.p.leblanc wrote: Wow! That is absolutely beautiful ... I had never seen (or even imagined) a recursive template! This expands my mind in a good way ... and is going into my toolbox immediately. Best Regards, James Just don't over rely on it. It can cause compilation slowdowns, so avoid it if you can.
Re: simple (I think) eponymous template question ... what is proper idimatic way ?
On Tuesday, 17 August 2021 at 19:53:52 UTC, james.p.leblanc wrote: On Tuesday, 17 August 2021 at 19:44:29 UTC, H. S. Teoh wrote: You could use a helper template and an AliasSeq for this: template isAmong(T, S...) { static if (S.length == 0) enum isAmong = false; else enum isAmong = is(T == S) || isAmong(T, S[1..$]); } import std.meta : AliasSeq; alias MyTypes = AliasSeq!(int, float, MySpecialStruct); auto myFunc(T)(T a, T b) if (isAmong!(T, MyTypes)) { ... } T Dear H.S. Teoh, Wow! That is absolutely beautiful ... I had never seen (or even imagined) a recursive template! This expands my mind in a good way ... and is going into my toolbox immediately. Best Regards, James FYI: in this particular case, you can use std.meta.staticIndexOf instead of writing the recursion out yourself: import std.meta: staticIndexOf; enum isAmong(T, S...) = staticIndexOf!(T, S) >= 0; Docs: https://phobos.dpldocs.info/std.meta.staticIndexOf.html
Re: simple (I think) eponymous template question ... what is proper idimatic way ?
On Tuesday, 17 August 2021 at 19:44:29 UTC, H. S. Teoh wrote: You could use a helper template and an AliasSeq for this: template isAmong(T, S...) { static if (S.length == 0) enum isAmong = false; else enum isAmong = is(T == S) || isAmong(T, S[1..$]); } import std.meta : AliasSeq; alias MyTypes = AliasSeq!(int, float, MySpecialStruct); auto myFunc(T)(T a, T b) if (isAmong!(T, MyTypes)) { ... } T Dear H.S. Teoh, Wow! That is absolutely beautiful ... I had never seen (or even imagined) a recursive template! This expands my mind in a good way ... and is going into my toolbox immediately. Best Regards, James
Re: simple (I think) eponymous template question ... what is proper idimatic way ?
On Tue, Aug 17, 2021 at 07:22:54PM +, james.p.leblanc via Digitalmars-d-learn wrote: [...] > auto moo(T : (int || float || mySpecialStruct )(T myMoo) {•••} > > When re-using any such sets, it would be nice to define the set as > follows: > > S = (int || float || mySpecialStruct) > > and then define "moo" more concisely as: > > auto moo(T < S)(T myMoo) {•••} > > ( where I have used "<" to mean "T is a member of S"). [...] You could use a helper template and an AliasSeq for this: template isAmong(T, S...) { static if (S.length == 0) enum isAmong = false; else enum isAmong = is(T == S) || isAmong(T, S[1..$]); } import std.meta : AliasSeq; alias MyTypes = AliasSeq!(int, float, MySpecialStruct); auto myFunc(T)(T a, T b) if (isAmong!(T, MyTypes)) { ... } T -- I am a consultant. My job is to make your job redundant. -- Mr Tom
Re: simple (I think) eponymous template question ... what is proper idimatic way ?
On Tuesday, 17 August 2021 at 18:28:53 UTC, Steven Schveighoffer wrote: On 8/17/21 2:11 PM, james.p.leblanc wrote: Evening All, [Template constraints](https://dlang.org/spec/template.html#template_constraints). -Steve Dear All, Thanks! I was aware of, and have used template constraints in simple ways. But, I should express my question a bit better: "... is there a more elegant way to expression these constraints?" Perhaps by extending Alexandru's "moo" concepts, with a list of allowed types: auto moo(T : (int || float || mySpecialStruct )(T myMoo) {•••} When re-using any such sets, it would be nice to define the set as follows: S = (int || float || mySpecialStruct) and then define "moo" more concisely as: auto moo(T < S)(T myMoo) {•••} ( where I have used "<" to mean "T is a member of S"). Possible? Best Regards, James
Re: Concurrency message passing
On 8/17/21 11:36 AM, JG wrote: >>> Maybe message parsing isn't the >>> correct solution? I use message passing in many of my programs. > After being populated it should be passed to > the other thread and no references are kept. Then you simply cast to-and-from 'shared' and be happy with it. :) I explain what I do here: https://www.youtube.com/watch?v=dRORNQIB2wA&t=1735s Ali
Re: Non-consistent implicit function template specializations
On 8/17/21 2:59 AM, Rekel wrote: > template TFoo(T){ void foo(){writeln("1");} } // #1 > template TFoo(T : T[]) { void foo(){writeln("2");} } // #2 I don't have such problems because I am not smart enough to understand that syntax so I don't use it. :) I use template constraints (which have other problems). import std.traits; import std.stdio; template TFoo(T) if (!isArray!T) { void foo(){ writeln("not array"); } } template TFoo(T) if (isArray!T) { void foo(){ writeln("array"); } } void main() { TFoo!(int).foo(); TFoo!(int[]).foo(); } If you want 2 dimensional arrays, then you can use import std.range; isArray!T && (isArray!(ElementType!T)) Ali
Re: Concurrency message passing
On Tuesday, 17 August 2021 at 12:24:14 UTC, Steven Schveighoffer wrote: On 8/17/21 7:05 AM, JG wrote: Hi I have a program with two threads. One thread produces data that is put in a queue and then consumed by the other thread. I initially built a custom queue to do this, but thought this should have some standard solution in D? I looked at std.concurrency and thought that message passing could be used. However, the problem is that I get the following error. Error: static assert: "Aliases to mutable thread-local data not allowed." I am not sure how to solve this. Maybe message parsing isn't the correct solution? Is there some standard solution to this in D? Data with references needs to be marked either immutable or shared in order to be passed using std.concurrency. D is strict about not sharing thread-local data, because then you can use the type system to prove lock-free code is valid. However, data that has no references (aliases) should be passable regardless of mutability, because you are passing a copy. -Steve Thanks for the suggestions and explanations. I am not sure what to do in my case though. The situation is as follows. I have a struct that is populated via user input not necessarily at single instance (so that seems to rule out immutable). On the other hand while it is being populate it is only accessible from one thread so that makes using shared messy. After being populated it should be passed to the other thread and no references are kept. What I am doing currently is populating the struct and casting to shared when I push into a synchronized queue (no references to its data are kept in the first thread). Is what I am doing wrong and can it be achieved using message passing?
Re: simple (I think) eponymous template question ... what is proper idimatic way ?
On 8/17/21 2:11 PM, james.p.leblanc wrote: Evening All, Eponymous templates allow a nice calling syntax. For example, "foo" here can be called without needing the exclamation mark (!) at calling sites. We see that foo is restricting a, and b to be of the same type ... so far, so good. auto foo(T)(T a, T b) { ... } Now, suppose I need to restrict "T" only certain subsets of variable types. I can imagine putting in some "static if" statements in my function body, is one solution. (Also a bit ugly as the allowed types might grow). Is there a more elegant way, to do this? [Template constraints](https://dlang.org/spec/template.html#template_constraints). -Steve
Re: simple (I think) eponymous template question ... what is proper idimatic way ?
On 8/17/21 11:11 AM, james.p.leblanc wrote: > auto foo(T)(T a, T b) { ... } > > Now, suppose I need to restrict "T" only certain subsets of variable types. There are template constraints: import std.traits; auto foo(T)(T a, T b) if (isArray!T) { // ... } auto foo(T)(T a, T b) if (isFloatingPoint!T) { // ... } void main() { foo(1.5, 2.5); } See __traits as well and of course you can use any compile-time check in the template constraint. > I can imagine putting in some "static if" statements in my function body, That method can display an intelligible error message if there is only one template implementation. Template constraints on the other hand, are not errors; they just determine what template implementations are available for instantiation for the used parameters. And of course, 'static if' has more uses other than just error reporting; which might be performed better with 'static assert'. Ali
Re: Non-consistent implicit function template specializations
On 8/17/21 2:07 PM, Rekel wrote: On Tuesday, 17 August 2021 at 16:24:38 UTC, Steven Schveighoffer wrote: All these are calling with array literals, which default to dynamic arrays, not static arrays. I realise that is their default, though in this scenario they should (I believe) be used as static arrays. (This works for me in any case) According to my tests, it prefers the `T` version over the static array version. Which leads me to believe that it prefers a dynamic array over a static one. In fact, if I comment out the `T` version, it doesn't compile. It literally will not pick that specialization, even if it can interpret the literal that way. which is really bizarre, since if you do it without specializations, but just spelling out all the template components (as in your alternative workaround), it WILL pick that one over a dynamic array one. -Steve
Re: simple (I think) eponymous template question ... what is proper idimatic way ?
On Tue, Aug 17, 2021 at 06:11:56PM +, james.p.leblanc via Digitalmars-d-learn wrote: > Evening All, > > Eponymous templates allow a nice calling syntax. For example, "foo" > here can be called without needing the exclamation mark (!) at calling > sites. We see that foo is restricting a, and b to be of the same type > ... so far, so good. > > auto foo(T)(T a, T b) { ... } > > Now, suppose I need to restrict "T" only certain subsets of variable > types. This is exactly what "signature constraints" are for. For example: auto foo(T)(T a, T b) if (is(T == string)) // <--- this is a signature constraint { ... // deal with strings here } auto foo(T)(T a, T b) if (is(T == int)) // you can overload on signature constraints { ... // deal with ints here } auto foo(T)(T a, T b) if (is(T == float) || is(T == double)) // you can use complex conditions { ... // deal with floats or doubles here } Be aware that a signature constraint failure is not an error: the compiler simply skips that overload of the function. So if you make a mistake in a sig constraint, it may *always* fail, and the compiler may try instead to instantiate a completely unintended overload and generate an error that may have nothing to do with the actual problem. T -- Give a man a fish, and he eats once. Teach a man to fish, and he will sit forever.
Re: simple (I think) eponymous template question ... what is proper idimatic way ?
On Tuesday, 17 August 2021 at 18:11:56 UTC, james.p.leblanc wrote: Is there a more elegant way, to do this? Regards, James PS Any violations should be caught at compile time. That is template specialization: ``` auto moo(T : YourSpecialClassOrDType)(T myMoo) {•••} ``` You can also declare other overloads of the method, just make sure they don't overlap in the constraints, otherwise you'd get ambiguous call exception. Regards, Alexandru.
simple (I think) eponymous template question ... what is proper idimatic way ?
Evening All, Eponymous templates allow a nice calling syntax. For example, "foo" here can be called without needing the exclamation mark (!) at calling sites. We see that foo is restricting a, and b to be of the same type ... so far, so good. auto foo(T)(T a, T b) { ... } Now, suppose I need to restrict "T" only certain subsets of variable types. I can imagine putting in some "static if" statements in my function body, is one solution. (Also a bit ugly as the allowed types might grow). Is there a more elegant way, to do this? Regards, James PS Any violations should be caught at compile time.
Re: Non-consistent implicit function template specializations
On Tuesday, 17 August 2021 at 16:24:38 UTC, Steven Schveighoffer wrote: void foo(T:U[L], uint L)(T a){...} This is an invalid specification, what is U? Did you mean: Yes, sorry typo in the forum. void foo(T: U[L], U, uint L)(T a) {...} void foo(T:U[L][L], uint L)(T a){...} // Never matched Apart from another missing U, this is only a SQUARE 2d-array (both dimensions the same), your example below only calls with a 1x2 array. Again, sorry a typo, calling with `[[1,2],[3,4]]`. void foo(T:U[L], U:V[L], V uint L)(T a){...} // Never matched (alternatively) I don't think you need this, and I had to comment it out, or the compiler wouldn't build. That is correct, it's equivalent thus causes 2 matches. All these are calling with array literals, which default to dynamic arrays, not static arrays. I realise that is their default, though in this scenario they should (I believe) be used as static arrays. (This works for me in any case)
Re: Non-consistent implicit function template specializations
On 8/17/21 10:20 AM, Rekel wrote: As my post was not the actual cause of my issue (my apology for the mistake), I think I have found the actual reason I'm currently having problems. This seems to be related to a (seeming, I might be wrong) inability to specialize over both 1d and 2d arrays separately. (If constraining the length to values.) This brings me to 2 questions. 1. How does one specialize a template for both 1d and 2d arrays at the same time? 2. Are there any plans to rework templates? like: - Making `template TFoo(T : T[])` illegal. This makes little sense to me however I look at it, and as several people have advised against it it's confusing it's in the docs. (21.4.1) - Changing the way priorities are set using specializations in general, to make them less pitfall-y. - Allow for 2+d length specification. At the moment `T[][L]` works while `T[L][L]` does not seem to. You should try out things individually to see if they at least work. ```d void foo(T)(T a){...} void foo(T:U[L], uint L)(T a){...} This is an invalid specification, what is U? Did you mean: void foo(T: U[L], U, uint L)(T a) {...} void foo(T:U[L][L], uint L)(T a){...} // Never matched Apart from another missing U, this is only a SQUARE 2d-array (both dimensions the same), your example below only calls with a 1x2 array. void foo(T:U[L], U:V[L], V uint L)(T a){...} // Never matched (alternatively) I don't think you need this, and I had to comment it out, or the compiler wouldn't build. // Should work with void main(string[] args) { foo([[1],[2]]); foo([1,2]); foo(1); } ``` All these are calling with array literals, which default to dynamic arrays, not static arrays. -Steve
Re: Anyway to achieve the following
On Saturday, 14 August 2021 at 20:50:47 UTC, Carl Sturtivant wrote: ``` struct S { int x = 1234; } void main() { import std.stdio; S s; //construction of a using &(s.x) auto a = Ref!(int)(&s.x); writeln(a); //displays 1234 s.x += 1; writeln(a); //displays 1235 a += 1; writeln(s.x); //displays 1236 } struct Ref(T) { T* ptr; this(T* p) { ptr = p; } string toString() { import std.conv; return to!string(*ptr); } ref T var() { return *ptr; } alias var this; } ``` Wow you can alias this a function? TIL!
Re: How to get element type of a slice?
On Tuesday, 17 August 2021 at 13:14:44 UTC, Steven Schveighoffer wrote: On 8/17/21 8:21 AM, Ferhat Kurtulmuş wrote: Hello folks, Hope everyone is doing fine. Considering the following code, in the first condition, I am extracting the type Point from the slice Point[]. I searched in the std.traits, and could not find a neater solution something like ElementTypeOf!T. Is there any neater solution for it? Thanks in advance. ```d static if (isArray!VecPoint){ VecPoint dummy; alias Point = typeof(dummy[0]); } else static if (isRandomAccessRange!VecPoint){ alias ASeq2 = TemplateArgsOf!VecPoint; alias Point = ASeq2[0]; } else static assert(0, typeof(VecPoint).stringof ~ " type is not supported"); ``` If you want the element type of a range (i.e. the thing returned by `range.front`), you can use `ElementType!T` (from std.range.primitives). This returns the element type of the range, which for every array *except* character arrays, gives you the element type of the array. If you want always the element type of the array, even for auto-decoded ranges, use `ElementEncodingType!T`. If you know it's an array, you can just use Paul's solution. Your `isRandomAccessRange` branch seems very suspect. -Steve Very informative, thanks. My code is lying here[1]. I want my struct to accept 2d static arrays, random access ranges, and "std.container.Array". I could achieve it with its present form, and I will probably slightly modify it based on your comments. [1]: https://github.com/aferust/earcut-d/blob/master/source/earcutd.d#L34
Re: How to get element type of a slice?
On Tuesday, 17 August 2021 at 12:49:02 UTC, drug wrote: 17.08.2021 15:21, Ferhat Kurtulmuş пишет: [...] https://dlang.org/library/std/range/primitives/element_type.html Yes, that is neat. Thank you.
Re: Non-consistent implicit function template specializations
As my post was not the actual cause of my issue (my apology for the mistake), I think I have found the actual reason I'm currently having problems. This seems to be related to a (seeming, I might be wrong) inability to specialize over both 1d and 2d arrays separately. (If constraining the length to values.) This brings me to 2 questions. 1. How does one specialize a template for both 1d and 2d arrays at the same time? 2. Are there any plans to rework templates? like: - Making `template TFoo(T : T[])` illegal. This makes little sense to me however I look at it, and as several people have advised against it it's confusing it's in the docs. (21.4.1) - Changing the way priorities are set using specializations in general, to make them less pitfall-y. - Allow for 2+d length specification. At the moment `T[][L]` works while `T[L][L]` does not seem to. ```d void foo(T)(T a){...} void foo(T:U[L], uint L)(T a){...} void foo(T:U[L][L], uint L)(T a){...} // Never matched void foo(T:U[L], U:V[L], V uint L)(T a){...} // Never matched (alternatively) // Alternative workaround, very cluttery but with more control. void foo(T)(T a) if(!is(typeof(a[0]))&&!is(typeof(a[0][0]))) {...} void foo(T, uint L)(T[L] a) if(!is(typeof(a[0]))){...} void foo(T, uint L)(T[L][L] a) {...} // Still does not work. void foo(T, unit L(T[][L] a) {static foreach(i;0..L) assert(a[i].length==L); ...} // Will (generally) work but may include runtime checking & is generally much less preferrable. // Should work with void main(string[] args) { foo([[1],[2]]); foo([1,2]); foo(1); } ``` - Supporting specializations such as the following (from https://forum.dlang.org/post/kdgfwlydkgmwvzrie...@forum.dlang.org): ```d void foo(L, T, uint S)(L l, T[S] r){ writeln("foo"); } void bar(L, R:T[S], T, uint S)(L l, R r){ writeln("bar"); } void main(string[] args) { foo(1, [1,2,3,4]); // "foo" bar(1, [1,2,3,4]); // "cannot deduce function" } ``` I'm actually still not sure why this shouldn't work, but changing bar to foo isn't too difficult. (though it's more preferrable to work regardless, it currently feels like a pitfall) --- Not sure if I'm asking the right questions, hope it's not of nuisance. - Rekel
Re: Union member positions?
On Tuesday, 17 August 2021 at 13:46:22 UTC, z wrote: Is it possible to set a "position" on a union member? You can use anonymous `struct` and `union` blocks. ```D union UnionExample{ uint EAX; struct { //upper union { ushort EAHX; struct { ubyte EAHH; ubyte EAHL; } } //lower union { ushort EALX; struct { ubyte EALH; ubyte EALL; } } } } ```
Re: Union member positions?
On 17.08.21 15:46, z wrote: Is it possible to set a "position" on a union member? or is there is a language-integrated equivalent? For example, to get access to each byte in an unsigned integer while still supporting the original type. ```D ///a single uint that would be accessed as two ushort, or four separate ubyte union UnionExample{ uint EAX; //upper ushort EAHX; ubyte EAHH; ubyte EAHL; //lower ushort EALX; ubyte EALH; ubyte EALL; } ``` Thanks. union UnionExample { uint EAX; struct { union // upper { ushort EAHX; struct { ubyte EAHH; ubyte EAHL; } } union // lower { ushort EALX; struct { ubyte EALH; ubyte EALL; } } } }
Union member positions?
Is it possible to set a "position" on a union member? or is there is a language-integrated equivalent? For example, to get access to each byte in an unsigned integer while still supporting the original type. ```D ///a single uint that would be accessed as two ushort, or four separate ubyte union UnionExample{ uint EAX; //upper ushort EAHX; ubyte EAHH; ubyte EAHL; //lower ushort EALX; ubyte EALH; ubyte EALL; } ``` Thanks.
Re: How to get element type of a slice?
On 8/17/21 8:21 AM, Ferhat Kurtulmuş wrote: Hello folks, Hope everyone is doing fine. Considering the following code, in the first condition, I am extracting the type Point from the slice Point[]. I searched in the std.traits, and could not find a neater solution something like ElementTypeOf!T. Is there any neater solution for it? Thanks in advance. ```d static if (isArray!VecPoint){ VecPoint dummy; alias Point = typeof(dummy[0]); } else static if (isRandomAccessRange!VecPoint){ alias ASeq2 = TemplateArgsOf!VecPoint; alias Point = ASeq2[0]; } else static assert(0, typeof(VecPoint).stringof ~ " type is not supported"); ``` If you want the element type of a range (i.e. the thing returned by `range.front`), you can use `ElementType!T` (from std.range.primitives). This returns the element type of the range, which for every array *except* character arrays, gives you the element type of the array. If you want always the element type of the array, even for auto-decoded ranges, use `ElementEncodingType!T`. If you know it's an array, you can just use Paul's solution. Your `isRandomAccessRange` branch seems very suspect. -Steve
Re: How to get element type of a slice?
17.08.2021 15:21, Ferhat Kurtulmuş пишет: Hello folks, Hope everyone is doing fine. Considering the following code, in the first condition, I am extracting the type Point from the slice Point[]. I searched in the std.traits, and could not find a neater solution something like ElementTypeOf!T. Is there any neater solution for it? Thanks in advance. ```d static if (isArray!VecPoint){ VecPoint dummy; alias Point = typeof(dummy[0]); } else static if (isRandomAccessRange!VecPoint){ alias ASeq2 = TemplateArgsOf!VecPoint; alias Point = ASeq2[0]; } else static assert(0, typeof(VecPoint).stringof ~ " type is not supported"); ``` Ferhat https://dlang.org/library/std/range/primitives/element_type.html
Re: How to get element type of a slice?
On Tuesday, 17 August 2021 at 12:32:45 UTC, Paul Backus wrote: On Tuesday, 17 August 2021 at 12:21:31 UTC, Ferhat Kurtulmuş wrote: Hello folks, Hope everyone is doing fine. Considering the following code, in the first condition, I am extracting the type Point from the slice Point[]. I searched in the std.traits, and could not find a neater solution something like ElementTypeOf!T. Is there any neater solution for it? Thanks in advance. `typeof(T.init[0])` Note that `std.range.ElementType` will probably not give the result you expect for character arrays (such as `char[]` and `wchar[]`), due to autodecoding. Thank you. This one looks better.
Re: How to get element type of a slice?
On Tuesday, 17 August 2021 at 12:26:36 UTC, jfondren wrote: On Tuesday, 17 August 2021 at 12:21:31 UTC, Ferhat Kurtulmuş wrote: [...] This one's not in std.traits: ```d import std.range : ElementType; struct Point { int x, y; } unittest { Point[] points; assert(is(ElementType!(typeof(points)) == Point)); } ``` Hey, thank you again but, I don't want an instance of Point[] I need: alias T = Point[]; alias ElementOfPointSlice = // element type of T
Re: How to get element type of a slice?
On Tuesday, 17 August 2021 at 12:21:31 UTC, Ferhat Kurtulmuş wrote: Hello folks, Hope everyone is doing fine. Considering the following code, in the first condition, I am extracting the type Point from the slice Point[]. I searched in the std.traits, and could not find a neater solution something like ElementTypeOf!T. Is there any neater solution for it? Thanks in advance. `typeof(T.init[0])` Note that `std.range.ElementType` will probably not give the result you expect for character arrays (such as `char[]` and `wchar[]`), due to autodecoding.
Re: How to get element type of a slice?
On Tuesday, 17 August 2021 at 12:26:36 UTC, jfondren wrote: On Tuesday, 17 August 2021 at 12:21:31 UTC, Ferhat Kurtulmuş wrote: [...] This one's not in std.traits: ```d import std.range : ElementType; struct Point { int x, y; } unittest { Point[] points; assert(is(ElementType!(typeof(points)) == Point)); } ``` Awesome! Have a great day.
Re: How to get element type of a slice?
On Tuesday, 17 August 2021 at 12:21:31 UTC, Ferhat Kurtulmuş wrote: Hello folks, Hope everyone is doing fine. Considering the following code, in the first condition, I am extracting the type Point from the slice Point[]. I searched in the std.traits, and could not find a neater solution something like ElementTypeOf!T. Is there any neater solution for it? Thanks in advance. ```d static if (isArray!VecPoint){ VecPoint dummy; alias Point = typeof(dummy[0]); } else static if (isRandomAccessRange!VecPoint){ alias ASeq2 = TemplateArgsOf!VecPoint; alias Point = ASeq2[0]; } else static assert(0, typeof(VecPoint).stringof ~ " type is not supported"); ``` Ferhat This one's not in std.traits: ```d import std.range : ElementType; struct Point { int x, y; } unittest { Point[] points; assert(is(ElementType!(typeof(points)) == Point)); } ```
How to get element type of a slice?
Hello folks, Hope everyone is doing fine. Considering the following code, in the first condition, I am extracting the type Point from the slice Point[]. I searched in the std.traits, and could not find a neater solution something like ElementTypeOf!T. Is there any neater solution for it? Thanks in advance. ```d static if (isArray!VecPoint){ VecPoint dummy; alias Point = typeof(dummy[0]); } else static if (isRandomAccessRange!VecPoint){ alias ASeq2 = TemplateArgsOf!VecPoint; alias Point = ASeq2[0]; } else static assert(0, typeof(VecPoint).stringof ~ " type is not supported"); ``` Ferhat
Re: Concurrency message passing
On 8/17/21 7:05 AM, JG wrote: Hi I have a program with two threads. One thread produces data that is put in a queue and then consumed by the other thread. I initially built a custom queue to do this, but thought this should have some standard solution in D? I looked at std.concurrency and thought that message passing could be used. However, the problem is that I get the following error. Error: static assert: "Aliases to mutable thread-local data not allowed." I am not sure how to solve this. Maybe message parsing isn't the correct solution? Is there some standard solution to this in D? Data with references needs to be marked either immutable or shared in order to be passed using std.concurrency. D is strict about not sharing thread-local data, because then you can use the type system to prove lock-free code is valid. However, data that has no references (aliases) should be passable regardless of mutability, because you are passing a copy. -Steve
Re: Concurrency message passing
On Tuesday, 17 August 2021 at 11:05:09 UTC, JG wrote: Hi I have a program with two threads. One thread produces data that is put in a queue and then consumed by the other thread. I initially built a custom queue to do this, but thought this should have some standard solution in D? I looked at std.concurrency and thought that message passing could be used. However, the problem is that I get the following error. Error: static assert: "Aliases to mutable thread-local data not allowed." I am not sure how to solve this. The error tells you what you can't do. You can do anything other than that. What you *should* do depends on what exactly you're trying to do. Here are some examples: Sending shared mutable data: ```d import std.concurrency, std.stdio, core.atomic; void incr() { auto counts = receiveOnly!(shared(int)[]); foreach (ref n; counts) atomicOp!"+="(n, 1); // shared(int) can't just be +='d ownerTid.send(true); } void main() { shared(int)[] counts = [0, 0, 0]; // no issues passing this spawn(&incr).send(counts); receiveOnly!bool; writeln(counts); } ``` Sending immutable data: ```d import std.concurrency, std.stdio, std.typecons; void greeter() { auto who = receiveOnly!(string); writeln("Hello, ", who); } void main() { char[] who = "John".dup; // mutable&thread-local, can't be sent spawn(&greeter).send(who.idup); // create immutable copy to send } ``` Sending scalar data: ```d import std.concurrency, std.stdio; __gshared int[3] counts; void incr() { auto indexes = receiveOnly!(int, int); foreach (ref n; counts[indexes[0] .. indexes[1]]) n++; ownerTid.send(true); } void main() { spawn(&incr).send(1, 2); receiveOnly!bool; writeln(counts); } ```
Concurrency message passing
Hi I have a program with two threads. One thread produces data that is put in a queue and then consumed by the other thread. I initially built a custom queue to do this, but thought this should have some standard solution in D? I looked at std.concurrency and thought that message passing could be used. However, the problem is that I get the following error. Error: static assert: "Aliases to mutable thread-local data not allowed." I am not sure how to solve this. Maybe message parsing isn't the correct solution? Is there some standard solution to this in D?
Re: Non-consistent implicit function template specializations
On Tuesday, 17 August 2021 at 10:21:39 UTC, Mike Parker wrote: We do have a paid Issue/Pull-Request manager now (Razvan Nitu), and he's prioritizing issues for strike teams composed of volunteers willing to fix them. If you find a specific bug that is a blocker or a major headache, make a post about it here in the forums. Sometimes, the reason a bug hasn't been fixed is simply that it hasn't caught the attention of the right person. With Razvan in place, it's more likely such issues will be resolved, or at least moved up on the priority list, if you let him know about them. A forum post is an easy way to do that while also bringing it to the attention of others who may be looking for something to work on. That's great to hear :), I'll keep it in mind.
Re: Non-consistent implicit function template specializations
On Tuesday, 17 August 2021 at 10:14:07 UTC, Mike Parker wrote: The error is in your code. Both of your `foo` templates are implemented to print `"1"`. Change the second one to print "2" and you will see the desired output. I keep managing to disappoint myself greatly... this is absurd, so sorry.
Re: Anyway to achieve the following
On Monday, 16 August 2021 at 19:30:19 UTC, JG wrote: On Sunday, 15 August 2021 at 21:53:14 UTC, Carl Sturtivant wrote: On Sunday, 15 August 2021 at 07:10:17 UTC, JG wrote: [...] What you are asking for are reference variables. C++ has them: the example here illustrates the behavior you want. https://www.geeksforgeeks.org/references-in-c/ [...] Thanks for the links and code. Looking at the assembly as suggested by others it seems that after optimization this not too bad. The problem is not optimization. The semantics of the code are different when you use the `Ref!int` solution versus simply `int`. You'll see this in template instantiations, as in the `writeln` example. `writeln` is a template and `writeln!int` is something different from `writeln!(Ref!int)`. When you force the template instantiation to `writeln!int` -- e.g. with an explicit cast, https://d.godbolt.org/z/6fKbMh731 -- the `Ref!int` output is the same as with `int`. Regardless, I haven't seen a performance measurement, and it is most likely completely irrelevant for the performance of your program. -Johan
Re: Non-consistent implicit function template specializations
On Tuesday, 17 August 2021 at 09:59:53 UTC, Rekel wrote: time in the future. Even bugs don't seem to get fixed in any timely manner (Not meant as an insult, just being realistic :/). We do have a paid Issue/Pull-Request manager now (Razvan Nitu), and he's prioritizing issues for strike teams composed of volunteers willing to fix them. If you find a specific bug that is a blocker or a major headache, make a post about it here in the forums. Sometimes, the reason a bug hasn't been fixed is simply that it hasn't caught the attention of the right person. With Razvan in place, it's more likely such issues will be resolved, or at least moved up on the priority list, if you let him know about them. A forum post is an easy way to do that while also bringing it to the attention of others who may be looking for something to work on.
Re: Non-consistent implicit function template specializations
On Tuesday, 17 August 2021 at 09:59:53 UTC, Rekel wrote: When using implicit function templates, identical specialization yield different results. Example: ```d template TFoo(T){ void foo(){writeln("1");} } // #1 template TFoo(T : T[]) { void foo(){writeln("2");} } // #2 void foo(T)(){ writeln("1"); } void foo(T : T[])(){ writeln("1"); } void main(string[] args) { // Works TFoo!(int).foo();// "1" TFoo!(double[]).foo(); // "2" foo!(int)();// "1" foo!(double[])(); // "1" ! } ``` I'm fairly certain the last call _should_ yield "2", yet it does not. The error is in your code. Both of your `foo` templates are implemented to print `"1"`. Change the second one to print "2" and you will see the desired output. At any rate, to specialize on arrays you should generally be using something like `T : U[], U`. Ditto for pointers: `T : U*, U`.
Non-consistent implicit function template specializations
When using implicit function templates, identical specialization yield different results. Example: ```d template TFoo(T){ void foo(){writeln("1");} } // #1 template TFoo(T : T[]) { void foo(){writeln("2");} } // #2 void foo(T)(){ writeln("1"); } void foo(T : T[])(){ writeln("1"); } void main(string[] args) { // Works TFoo!(int).foo();// "1" TFoo!(double[]).foo(); // "2" foo!(int)();// "1" foo!(double[])(); // "1" ! } ``` I'm fairly certain the last call _should_ yield "2", yet it does not. Should I submit a bugreport? And will that even help? There's even 'NEW' bugs from 2016 :'c --- Interestingly enough, it seems I've made a previous thread about this in January (https://forum.dlang.org/post/zudtiruaxdfdwcjen...@forum.dlang.org), though in it I state `TFoo!(uint[]) yields the array version`, which as can be seen from the example above, is not or no longer true. Sadly I'm having issues with template arguments more often (https://forum.dlang.org/post/xkgpheuhohbffzgdb...@forum.dlang.org) And I sadly don't see any improvement to this happening any time in the future. Even bugs don't seem to get fixed in any timely manner (Not meant as an insult, just being realistic :/).
Re: Nondeterministic unittest debugging problem.
On Monday, 16 August 2021 at 22:01:21 UTC, russhy wrote: remove the .dub folder and try again, as stated in other reply, might be a cache issue, or something that picks an outdated file in the cache Thanks, I'll try that, sadly clear didn't seem to fix it.