Re: Non-consistent implicit function template specializations

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

On 8/18/21 4:10 AM, Rekel wrote:

>>   isArray!T && (isArray!(ElementType!T))
>
> I tried looking into how isArray is defined. Like, does being able to
> index mean it's an array, or are these only static &/or dynamic arrays?

The definitions are in phobos/std/traits.d

  enum bool isArray(T) = isStaticArray!T || isDynamicArray!T;

isStaticArray uses the compiler's __traits feature:

  enum bool isStaticArray(T) = __traits(isStaticArray, T);

isDynamicArray uses the is expression but apparently has some history:

template isDynamicArray(T)
{
static if (is(T == U[], U))
enum bool isDynamicArray = true;
else static if (is(T U == enum))
// BUG: isDynamicArray / isStaticArray considers enums
// with appropriate base types as dynamic/static arrays
// Retain old behaviour for now, see
// https://github.com/dlang/phobos/pull/7574
enum bool isDynamicArray = isDynamicArray!U;
else
enum bool isDynamicArray = false;
}

Ali



Re: Non-consistent implicit function template specializations

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

On Wednesday, 18 August 2021 at 13:35:07 UTC, Paul Backus wrote:

On Wednesday, 18 August 2021 at 11:10:49 UTC, Rekel wrote:
I tried looking into how isArray is defined. Like, does being 
able to index mean it's an array, or are these only static 
&/or dynamic arrays?


Did you read the documentation?

https://phobos.dpldocs.info/std.traits.isArray.html


Ah it's specifically static & dynamic arrays, I see.


Re: Non-consistent implicit function template specializations

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

On Wednesday, 18 August 2021 at 11:10:49 UTC, Rekel wrote:
I tried looking into how isArray is defined. Like, does being 
able to index mean it's an array, or are these only static &/or 
dynamic arrays?


Did you read the documentation?

https://phobos.dpldocs.info/std.traits.isArray.html


Re: Non-consistent implicit function template specializations

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

On Tuesday, 17 August 2021 at 18:46:05 UTC, Ali Çehreli wrote:
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).


Yeah, they seem to be a bit more trustworthy to some extent.


If you want 2 dimensional arrays, then you can use

import std.range;

  isArray!T && (isArray!(ElementType!T))


I tried looking into how isArray is defined. Like, does being 
able to index mean it's an array, or are these only static &/or 
dynamic arrays? Though I couldn't understand the sourcecode.
Hence I just use(d) `is(typeof(variable[0]))` and 
`is(typeof(variable[0][0]))`.


Re: Non-consistent implicit function template specializations

2021-08-18 Thread Rekel via Digitalmars-d-learn
On Tuesday, 17 August 2021 at 18:27:21 UTC, Steven Schveighoffer 
wrote:
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.


Oh my, that's weird... Not meant to bash but given all I've seen 
of argument deduction & templates & specializations... I think 
the implementation needs some serious rework 


---

Interestingly enough my approach will not even work for 2d array 
literals. It will manage going to int[][2], but int[2][2] is one 
step too far. Which is a real bummer. :(
That is, it won't figure it out itself, but when you call `foo(T, 
uintL)(T[L][L]...` using an explicit `foo!(int, 2)` it _will_ 
work. Even though it manages T[L] just fine.
Meanwhile T[2][L] _and_ T[L][2] won't work when called with a 2x2 
array literal.


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: 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: 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: 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: 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: 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`.