Re: simple (I think) eponymous template question ... what is proper idimatic way ?

2021-08-17 Thread Tejas via Digitalmars-d-learn
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 ?

2021-08-17 Thread Dominikus Dittes Scherkl via Digitalmars-d-learn
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 ?

2021-08-17 Thread james.p.leblanc via Digitalmars-d-learn
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

2021-08-17 Thread Steven Schveighoffer via Digitalmars-d-learn

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 ?

2021-08-17 Thread Bastiaan Veelo via Digitalmars-d-learn

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 ?

2021-08-17 Thread H. S. Teoh via Digitalmars-d-learn
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 ?

2021-08-17 Thread james.p.leblanc via Digitalmars-d-learn

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 ?

2021-08-17 Thread Alexandru Ermicioi via Digitalmars-d-learn

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 ?

2021-08-17 Thread Paul Backus via Digitalmars-d-learn

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 ?

2021-08-17 Thread james.p.leblanc via Digitalmars-d-learn

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 ?

2021-08-17 Thread H. S. Teoh via Digitalmars-d-learn
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 ?

2021-08-17 Thread james.p.leblanc via Digitalmars-d-learn
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

2021-08-17 Thread Ali Çehreli via Digitalmars-d-learn

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

2021-08-17 Thread Ali Çehreli via Digitalmars-d-learn

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

2021-08-17 Thread JG via Digitalmars-d-learn
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 ?

2021-08-17 Thread Steven Schveighoffer via Digitalmars-d-learn

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 ?

2021-08-17 Thread Ali Çehreli via Digitalmars-d-learn

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

2021-08-17 Thread Steven Schveighoffer via Digitalmars-d-learn

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 ?

2021-08-17 Thread H. S. Teoh via Digitalmars-d-learn
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 ?

2021-08-17 Thread Alexandru Ermicioi via Digitalmars-d-learn

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 ?

2021-08-17 Thread james.p.leblanc via Digitalmars-d-learn

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

2021-08-17 Thread Rekel via Digitalmars-d-learn
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

2021-08-17 Thread Steven Schveighoffer via Digitalmars-d-learn

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

2021-08-17 Thread Rekel via Digitalmars-d-learn
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?

2021-08-17 Thread Ferhat Kurtulmuş via Digitalmars-d-learn
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?

2021-08-17 Thread Ferhat Kurtulmuş via Digitalmars-d-learn

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

2021-08-17 Thread Rekel via Digitalmars-d-learn
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?

2021-08-17 Thread Dennis via Digitalmars-d-learn

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?

2021-08-17 Thread ag0aep6g via Digitalmars-d-learn

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?

2021-08-17 Thread z via Digitalmars-d-learn
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?

2021-08-17 Thread Steven Schveighoffer via Digitalmars-d-learn

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?

2021-08-17 Thread drug via Digitalmars-d-learn

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?

2021-08-17 Thread Ferhat Kurtulmuş via Digitalmars-d-learn

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?

2021-08-17 Thread Ferhat Kurtulmuş via Digitalmars-d-learn

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?

2021-08-17 Thread Paul Backus via Digitalmars-d-learn
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?

2021-08-17 Thread Ferhat Kurtulmuş via Digitalmars-d-learn

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?

2021-08-17 Thread jfondren via Digitalmars-d-learn
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?

2021-08-17 Thread Ferhat Kurtulmuş via Digitalmars-d-learn

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

2021-08-17 Thread Steven Schveighoffer via Digitalmars-d-learn

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

2021-08-17 Thread jfondren via Digitalmars-d-learn

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

2021-08-17 Thread JG via Digitalmars-d-learn

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

2021-08-17 Thread Rekel via Digitalmars-d-learn

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

2021-08-17 Thread Rekel via Digitalmars-d-learn

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

2021-08-17 Thread Johan via Digitalmars-d-learn

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

2021-08-17 Thread Mike Parker via Digitalmars-d-learn

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

2021-08-17 Thread Mike Parker via Digitalmars-d-learn

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

2021-08-17 Thread Rekel via Digitalmars-d-learn
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.

2021-08-17 Thread Rekel via Digitalmars-d-learn

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.