Re: @nogc with opApply

2018-08-12 Thread Alex via Digitalmars-d-learn

On Sunday, 12 August 2018 at 01:39:21 UTC, ag0aep6g wrote:

On 08/11/2018 12:00 PM, Alex wrote:

[...]

[...]

[...]

[...]

 [...]

[...]

[...]


You can provide to overloads: one with @nogc, one without it. 
To keep it somewhat DRY, you can let them forward to a template 
implementation:


int opApply(scope int delegate(ref uint) operations)
{
return opApplyImpl(operations);
}
int opApply(scope int delegate(ref uint) @nogc operations) 
@nogc

{
return opApplyImpl(operations);
}
int opApplyImpl(O)(O operations)
{
/* ... implementation here ... */
}


Ah... that's nice...
Thanks!


Re: @nogc with opApply

2018-08-11 Thread ag0aep6g via Digitalmars-d-learn

On 08/11/2018 12:00 PM, Alex wrote:

´´´
import std.experimental.all;

static assert(isIterable!S);


[...]


struct S
{

[...]

     int opApply(scope int delegate(ref uint) /*@nogc*/ operations) //@nogc
     {

[...]

     }
}
´´´

Everything works fine, before I try to use the opApply function inside a 
@nogc function.


If I do, compiler complains, that opApply is not marked as @nogc. Ok.
If I try to mark opApply @nogc, I would have to mark operations delegate 
also as @nogc, but I can't do this, as I do not know a priori, how it 
will be used.


Now, as I learned at some point, a possibility would be, to templatify 
the function, as the compiler can then derive, if @nogc apply or not.

But if I write
´´´
int opApply()(...){...}
´´´
Then the static assert from above refuses to compile.

So... how to solve this case?


You can provide to overloads: one with @nogc, one without it. To keep it 
somewhat DRY, you can let them forward to a template implementation:


int opApply(scope int delegate(ref uint) operations)
{
return opApplyImpl(operations);
}
int opApply(scope int delegate(ref uint) @nogc operations) @nogc
{
return opApplyImpl(operations);
}
int opApplyImpl(O)(O operations)
{
/* ... implementation here ... */
}


Re: @nogc with opApply

2018-08-11 Thread tide via Digitalmars-d-learn

On Saturday, 11 August 2018 at 10:00:34 UTC, Alex wrote:

Hi all,
maybe I misunderstand something but having this:

´´´
import std.experimental.all;

static assert(isIterable!S);

void main()
{
S s;
s.each!(el => el.writeln);
}

struct S
{
private Nullable!uint member = 0;
Nullable!uint front() @nogc { return member; }
//void popFront(){} // not implementable.
//bool empty(){} // not implementable
Nullable!uint successor(uint current) @nogc { return 
Nullable!uint.init; }


/**
the opApply method grants the correct foreach behavior
*/
int opApply(scope int delegate(ref uint) /*@nogc*/ 
operations) //@nogc

{
int result;

for(auto leading = front; !leading.isNull; leading = 
successor(leading.get))

{
result = operations(leading.get);

if(result)
{
break;
}
}
return result;
}
}
´´´

Everything works fine, before I try to use the opApply function 
inside a @nogc function.


If I do, compiler complains, that opApply is not marked as 
@nogc. Ok.
If I try to mark opApply @nogc, I would have to mark operations 
delegate also as @nogc, but I can't do this, as I do not know a 
priori, how it will be used.


Now, as I learned at some point, a possibility would be, to 
templatify the function, as the compiler can then derive, if 
@nogc apply or not.

But if I write
´´´
int opApply()(...){...}
´´´
Then the static assert from above refuses to compile.

So... how to solve this case?


There's no way to solve it, just don't use @nogc is the easiest 
workaround. It wasn't thought out when it was added and these are 
one of the cases where it doesn't work. Having functions 
automatically declare themselves @nogc if they don't use the gc 
would solve part of the problem. Which is how templates work.


https://dlang.org/library/std/traits/is_iterable.html

If you see how isIterable is defined you'll see that it requires 
opApply be able to provide the element type automatically. That 
is "foreach" doesn't define a type and it is automatically 
deduced. The compiler can't deduce the argument type because the 
function is a template.



foreach(t ; S.init) // Error: cannot infer type for `foreach` 
variable `t`, perhaps set it explicitly

{

}