Re: How are delegate attributes in fn signature inferred?

2022-05-23 Thread wjoe via Digitalmars-d-learn

On Monday, 23 May 2022 at 13:53:02 UTC, Adam D Ruppe wrote:

On Monday, 23 May 2022 at 13:44:53 UTC, wjoe wrote:

  [...]


You can actually make this work with `construct!(int[])` rather 
than plain `construct`. This is a (really annoying) deficiency 
in dmd's implementation. (that sdc solved btw proving it can be 
done just dmd never bothered)


[...]


I see. I figured the issue was an attribute mismatch.

Thanks for the explanation. Very much appreciated!


Re: How are delegate attributes in fn signature inferred?

2022-05-23 Thread Adam D Ruppe via Digitalmars-d-learn

On Monday, 23 May 2022 at 13:44:53 UTC, wjoe wrote:

  i.construct((ulong i) {return cast(int)(i+i);}).print;


You can actually make this work with `construct!(int[])` rather 
than plain `construct`. This is a (really annoying) deficiency in 
dmd's implementation. (that sdc solved btw proving it can be done 
just dmd never bothered)



Where's **pure nothrow @nogc @safe** coming from?


That's because it is a delegate literal, so it automatically 
figured out the tightest thing that works (this is also why it 
came as `function` instead of `delegate`, since it doesn't use 
any local variables from the enclosing function, it doesn't need 
the delegate pointer either).


But all those implicitly convert away so it doesn't really 
matter. The type system allows this, just the crappy 
implementation can't handle inferring that R when it is mentioned 
both as R r *and* ElementType!R - the stupid compiler sees 
ElementType!R and bails out.


Thus why you have to help it by telling the type when 
instantiating it


  i.construct!(int[])((ulong i) {return cast(int)(i+i);}).print;




How are delegate attributes in fn signature inferred?

2022-05-23 Thread wjoe via Digitalmars-d-learn

Hello,

Consider this example:
```d
module foo;

import std.stdio;
import std.algorithm;
import std.traits;
import std.range;

void print(R)(R r) {
  static assert(isIterable!R);
  r.each!writeln;
}

auto construct(R)(R r, ElementType!R delegate(ulong i) fn) {
  static assert(isIterable!R && hasAssignableElements!R);
  ulong i = 1;
  r.each!((ref e) => e = fn(i));
  return r;
}

unittest {
  int[] i; i.length = 4;
  i.construct((ulong i) {return cast(int)(i+i);}).print;
}
```

```shell

dmd -unittest -main foo.d


Error: template 'foo.construct' cannot deduce function from 
argument types '!()(int[], int function(ulong i) pure nothrow 
@nogc @safe)', candidates are: 'construct(R)(R r, ElementType!R 
delegate(ulong i) fn)'

```

Where's **pure nothrow @nogc @safe** coming from?
Also, why is *(ulong i) {return cast(int)(i+i);}* passed as a 
function?
The error message for passing a delegate is the same except with 
*function* substituted for *delegate*.