opApply example isn't compliant with spec
c9bf6f2d761d5e0bf6e5f72053fde4aa5f009f1a The spec states:
If the result is nonzero, apply must cease iterating and return that value.
The other commit add some other small improvements to make the example copy-pastable with minimal friction.
The spec also says that the signature should be
int opApply(scope int delegate(ref Tree) dg);
I think ref makes little sense, since actually using that would break loop invariance.
Should we add scope? Semantically, it makes sense, but it might confuse newcomers
The scope has a specific purpose. It means that the delegate will not be stored somewhere when the opApply returns. This allows the compiler to avoid allocating a closure.
In fact, it is crucial to do this for opApply, because all foreach bodies where opApply is used are rewritten as functions. Without scope, every foreach statement becomes a GC allocation.
Why ref? D allows you to specify non-ref or ref for the parameter, but just use one opApply that accepts by ref. This goes all the way back to the D1 days. So using ref just allows more functionality.
D allows you to specify non-ref or ref for the parameter, but just use one opApply that accepts by ref.
I've made a spec update: https://github.com/dlang/dlang.org/pull/3699
Without
scope, everyforeachstatement becomes a GC allocation.
Good to know. Am I right to assume that this is (mostly) only important for libraries? I always assumed the compiler or at least the optimizer could infer stuff like this, and annotating it is mostly for documentation and making sure that safe code doesn't rely on unsupported safeness of the code, leading to future breakage.
The optimizer can easily inline an opApply call, and therefore the lambda. Most likely this happens regardless of whether the delegate is marked scope or not.
But this is all after the frontend has decided whether the function is @nogc or not.
Aaaand, dmd just lets it happen. I guess this is a really old bug, which I actually commented on...
https://issues.dlang.org/show_bug.cgi?id=16193
But I don't think it's fixed, I just tried this and got garbage.
I would still recommend using scope, because at some point this could get "fixed".
Force pushed because I accidentally merged instead of rebased upstream