www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.learn - Foreach/opApply with nogc

reply "Stefan Frijters" <sfrijters gmail.com> writes:
Should this be possible? I admit to not being fully clear on the 
way delegates are handled, but maybe someone can shed some light? 
As an example I use a snippet Ali uses to demonstrate opApply:

struct NumberRange {
   int begin;
   int end;

   int opApply(int delegate(ref int)  nogc operations)  nogc const 
{
     int result = 0;

     for (int number = begin; number != end; ++number) {
       result = operations(number);

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

void main() {
   import std.stdio;
   foreach (element; NumberRange(3, 7)) { // line 21
     write(element, ' ');
   }
}

When I compile this with 2.066.0 I get

opapply.d(21): Error: function opapply.NumberRange.opApply (int 
delegate(ref int)  nogc operations) const is not callable using 
argument types (int delegate(ref int __applyArg0)  system)

It doesn't actually complain about anything gc, just about the 
signature, so I was wondering if there is some restriction inside 
the foreach implementation that can be lifted? Thanks in advance 
for any hints!
Aug 24 2014
parent reply ketmar via Digitalmars-d-learn <digitalmars-d-learn puremagic.com> writes:
On Sun, 24 Aug 2014 13:22:49 +0000
Stefan Frijters via Digitalmars-d-learn
<digitalmars-d-learn puremagic.com> wrote:

 nogc is a part of signature. gc-function can't call  nogc-one. the
same is with calling  system function from  safe one, for example. or
impure function from pure.

so to say, foreach() creates implicit delegate withoit ' nogc'
attribute, that's why compiler complains.

there is currenly no way to specify attributes for such implicit
delegates. this will work, but you'll not be able to call writeln():

  nogc:
  void main() {
     import std.stdio;
     foreach (element; NumberRange(3, 7)) { // line 21
       //write(element, ' '); // this will fail with=20
         //  nogc function 'z00.main.__foreachbody1' cannot call
         // non- nogc function 'std.stdio.write!(int, char).write'
    }
  }

what we need here is something like:

  foreach (element; NumberRange(3, 7)  nogc) { ... }

but alas...
Aug 24 2014
next sibling parent reply "bearophile" <bearophileHUGS lycos.com> writes:
ketmar:

 there is currenly no way to specify attributes for such implicit
 delegates.
It could be a nice language enhancement. Bye, bearophile
Aug 24 2014
parent reply ketmar via Digitalmars-d-learn <digitalmars-d-learn puremagic.com> writes:
On Sun, 24 Aug 2014 13:58:45 +0000
bearophile via Digitalmars-d-learn <digitalmars-d-learn puremagic.com>
wrote:

 there is currenly no way to specify attributes for such implicit
 delegates.
It could be a nice language enhancement.
i agree. but i tend not to fill enhancement requests without corresponding patches, and i'm not yet familiar with D frontend enough to create the patch.
Aug 24 2014
parent reply "bearophile" <bearophileHUGS lycos.com> writes:
ketmar:

 but i tend not to fill enhancement requests without
 corresponding patches,
I agree that having a patch ready is much better. But people like me file hundreds of ERs without too much damage done, and many of them get eventually implemented. If you find a D limitation, then putting this information in Bugzilla is better than letting this get forgotten. Bye, bearophile
Aug 24 2014
next sibling parent reply ketmar via Digitalmars-d-learn <digitalmars-d-learn puremagic.com> writes:
On Sun, 24 Aug 2014 14:34:02 +0000
bearophile via Digitalmars-d-learn <digitalmars-d-learn puremagic.com>
wrote:

 putting this information in Bugzilla is better than letting this=20
 get forgotten.
so it can be forgotten in Bugzilla. ;-)
Aug 24 2014
parent "bearophile" <bearophileHUGS lycos.com> writes:
ketmar:

 so it can be forgotten in Bugzilla. ;-)
And in ten, or one hundred or one thousand years the whole D language will be forgotten. There are various levels of remembering and forgetting. Putting bugs and ERs in databases is a different kind of forgetting. Bye, bearophile
Aug 24 2014
prev sibling next sibling parent "H. S. Teoh via Digitalmars-d-learn" <digitalmars-d-learn puremagic.com> writes:
On Sun, Aug 24, 2014 at 05:49:29PM +0300, ketmar via Digitalmars-d-learn wrote:
 On Sun, 24 Aug 2014 14:34:02 +0000
 bearophile via Digitalmars-d-learn <digitalmars-d-learn puremagic.com>
 wrote:
 
 putting this information in Bugzilla is better than letting this 
 get forgotten.
so it can be forgotten in Bugzilla. ;-)
Some of us regularly comb through old bugzilla issues to find things to test & fix. It may take a long time, but we do try. :-) (And we could use a lot of help -- there are only a few of us and a ton of old bugs.) T -- Perhaps the most widespread illusion is that if we were in power we would behave very differently from those who now hold it---when, in truth, in order to get power we would have to become very much like them. -- Unknown
Aug 24 2014
prev sibling next sibling parent ketmar via Digitalmars-d-learn <digitalmars-d-learn puremagic.com> writes:
On Sun, 24 Aug 2014 08:02:40 -0700
"H. S. Teoh via Digitalmars-d-learn"
<digitalmars-d-learn puremagic.com> wrote:

 Some of us regularly comb through old bugzilla issues to find things
 to test & fix. It may take a long time, but we do try. :-)
=20
 (And we could use a lot of help -- there are only a few of us and a
 ton of old bugs.)
i understand that. it was a joke, i'm not trying to being rude or ranting about some of my "pet bugs". ;-)
Aug 24 2014
prev sibling parent "Stefan Frijters" <sfrijters gmail.com> writes:
On Sunday, 24 August 2014 at 14:34:03 UTC, bearophile wrote:
 ketmar:

 but i tend not to fill enhancement requests without
 corresponding patches,
I agree that having a patch ready is much better. But people like me file hundreds of ERs without too much damage done, and many of them get eventually implemented. If you find a D limitation, then putting this information in Bugzilla is better than letting this get forgotten. Bye, bearophile
I would also prefer to submit a patch but I do not have the skills to do it at the moment, so I filed an enhancement request: https://issues.dlang.org/show_bug.cgi?id=13370 .
Aug 24 2014
prev sibling parent reply =?UTF-8?B?QWxpIMOHZWhyZWxp?= <acehreli yahoo.com> writes:
On 08/24/2014 06:40 AM, ketmar via Digitalmars-d-learn wrote:

 On Sun, 24 Aug 2014 13:22:49 +0000
 Stefan Frijters via Digitalmars-d-learn
 <digitalmars-d-learn puremagic.com> wrote:

  nogc is a part of signature. gc-function can't call  nogc-one. the
 same is with calling  system function from  safe one, for example. or
 impure function from pure.

 so to say, foreach() creates implicit delegate withoit ' nogc'
 attribute, that's why compiler complains.

 there is currenly no way to specify attributes for such implicit
 delegates. this will work, but you'll not be able to call writeln():

    nogc:
    void main() {
       import std.stdio;
       foreach (element; NumberRange(3, 7)) { // line 21
         //write(element, ' '); // this will fail with
           //  nogc function 'z00.main.__foreachbody1' cannot call
           // non- nogc function 'std.stdio.write!(int, char).write'
      }
    }
Yeah, the only reason why the original code does not work is the write() expression in the foreach body. If I am not mistaken, the attributes are inferred for templates and delegates; the foreach body becomes nogc if it can be nogc.
 what we need here is something like:

    foreach (element; NumberRange(3, 7)  nogc) { ... }

 but alas...
I have discovered that the following works but of course it is not the same: nogc range = NumberRange(3, 7); foreach (element; range) { // write(element, ' '); } Ali
Aug 24 2014
parent reply ketmar via Digitalmars-d-learn <digitalmars-d-learn puremagic.com> writes:
On Sun, 24 Aug 2014 11:45:14 -0700
Ali =C3=87ehreli via Digitalmars-d-learn <digitalmars-d-learn puremagic.com>
wrote:

 Yeah, the only reason why the original code does not work is the
 write() expression in the foreach body.
hm. really. i forgot what is delegate body for opApply. sure, here we can't use nogc delegate. my fault.
Aug 24 2014
parent reply "Stefan Frijters" <sfrijters gmail.com> writes:
On Sunday, 24 August 2014 at 18:55:09 UTC, ketmar via 
Digitalmars-d-learn wrote:
 On Sun, 24 Aug 2014 11:45:14 -0700
 Ali Çehreli via Digitalmars-d-learn 
 <digitalmars-d-learn puremagic.com>
 wrote:

 Yeah, the only reason why the original code does not work is 
 the
 write() expression in the foreach body.
hm. really. i forgot what is delegate body for opApply. sure, here we can't use nogc delegate. my fault.
Apologies for the misunderstanding. Before I close my enhancement request I do have a followup question: is it possible somehow to have both a nogc and a normal opApply function available? My code would like to have nogc in as many places as possible, but there will be places where I cannot make the foreach body nogc (I think; maybe some more Phobos functions can be annotated as well and the problem would go away). So I basically want something like this: void bar() nogc { } void foreachBar() nogc { foreach (element; NumberRange(3, 7)) { bar(); } } void foo() { } void foreachFoo() { foreach (element; NumberRange(3, 7)) { foo(); } } void main() { foreachBar(); foreachFoo(); } Obviously if I have one opApply function one of the two functions complains opapply.d(36): Error: nogc function 'opapply.foreachBar' cannot call non- nogc function 'opapply.NumberRange.opApply' or opapply.d(44): Error: function opapply.NumberRange.opApply (int delegate(ref int) nogc operations) const is not callable using argument types (int delegate(ref int __applyArg0) system) If I add a second opApply function (one with nogc, the other without) the compiler cannot distinguish between the two: opapply.d(36): Error: NumberRange(3, 7).opApply matches more than one declaration: opapply.d(5): const nogc int(int delegate(ref int) nogc operations) and: opapply.d(18): const int(int delegate(ref int) operations) opapply.d(36): Error: cannot uniquely infer foreach argument types opapply.d(44): Error: NumberRange(3, 7).opApply matches more than one declaration: opapply.d(5): const nogc int(int delegate(ref int) nogc operations) and: opapply.d(18): const int(int delegate(ref int) operations) opapply.d(44): Error: cannot uniquely infer foreach argument types Is this maybe something that could be used as an enhancement request? Or I guess what I want is basically an 'inout' kind of thing for nogc...
Aug 24 2014
parent ketmar via Digitalmars-d-learn <digitalmars-d-learn puremagic.com> writes:
On Sun, 24 Aug 2014 19:23:01 +0000
Stefan Frijters via Digitalmars-d-learn
<digitalmars-d-learn puremagic.com> wrote:

 request I do have a followup question: is it possible somehow to=20
 have both a  nogc and a normal opApply function available?
you can use templated opApply(): import std.traits; struct NumberRange { int begin; int end; int opApply(Dg) (scope Dg dg) if (ParameterTypeTuple!Dg.length =3D=3D = 1) { int result =3D 0; for (int number =3D begin; number !=3D end; ++number) { result =3D dg(number); if (result) { break; } } return result; } } void bar() nogc { } void foreachBar() nogc { foreach (int element; NumberRange(3, 7)) { bar(); } } void foo() { } void foreachFoo() { foreach (int element; NumberRange(3, 7)) { foo(); } } void main() { foreachBar(); foreachFoo(); } this works, but you must use=20 foreach (int n; NumberRange(3, 7)) { ... } instead of foreach (n; NumberRange(3, 7)) { ... } 'cause compiler can't infer types in the last case.
Aug 24 2014