Skip to content

opDispatch and opApply parts should be split, plus incorrect example of opApply #799

@baryluk

Description

@baryluk

https://tour.dlang.org/tour/en/gems/opdispatch-opapply

has few issues

  • It bunches together two very different things - opDispatch and opApply
  • It does not link to opApply documentation, only opDispatch. This is because opApply is not really operator overloading. opApply is documented in statements and foreach and foreach_reverse - https://dlang.org/spec/statement.html#foreach_over_struct_and_classes
  • There is no runnable example for opApply
  • In-line example is buggy

It is:

class Tree {
    Tree lhs;
    Tree rhs;
    int opApply(int delegate(Tree) dg) {
        if (lhs && lhs.opApply(dg)) return 1;
        if (dg(this)) return 1;
        if (rhs && rhs.opApply(dg)) return 1;
        return 0;
    }
}
Tree tree = new Tree;
foreach (node; tree) {
    ...
}

but doing blind return 0 is not correct, especially when doing nested loops, with return statements in the body of the loops, or labeled continue/break (on outer loop), or with goto to label that is outside of the inner most loop.

This is documented in subsections 5 and 6 of the opApply documentation.

Proper way, is to return from opApply same value that dg returned:

class Tree {
    Tree lhs;
    Tree rhs;
    int opApply(int delegate(Tree) dg) {
        if (lhs) if (auto ret = lhs.opApply(dg)) return ret;
        if (auto ret = dg(this)) return ret;
        if (rhs) if (auto ret = rhs.opApply(dg)) return ret;
        return 0;
    }
}
Tree tree = new Tree;
foreach(node; tree) {
    ...
}

Or something similar.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions