When to opCall instead of opIndex and opSlice?

Jonathan M Davis newsgroup.d at jmdavisprog.com
Mon Oct 2 19:19:14 UTC 2017


On Monday, October 02, 2017 18:31:23 Per Nordlöw via Digitalmars-d-learn 
wrote:
> On Monday, 2 October 2017 at 18:14:24 UTC, Jacob Carlborg wrote:
> > On 2017-10-02 17:57, Nordlöw wrote:
> >> Is implementing opCall(size_t) for structures such as array
> >> containers that already define opIndex and opSlice deprecated?
> >>
> >> I can't find any documentation on the subject on when opCall
> >> should be defined to enable foreach (isIterable).
> >
> > opCall is not related to foreach. It's used to overload the
> > call operator, i.e. ().
> >
> > struct Foo
> > {
> >
> >     void opCall() {};
> >
> > }
> >
> > Foo foo;
> > foo();
> >
> > Are you thinking of opApply [1]?
> >
> > [1]
> > https://dlang.org/spec/statement.html#foreach_over_struct_and_classes
>
> Ahh, yes of course.
>
> It seems like defining opIndex anf opSlice is enough in the array
> container case. Why do we have opApply as well? Non-random access?

opApply was the original way to implement the ability to use foreach with
user defined types. Later, when ranges were added to the language, foreach
was made to try slicing the type, and if that resulted in a range, then that
was used with foreach. So, opSlice made it possible to use foreach (but only
if the result was a range), and later opIndex was altered to also do what
opSlice does.

opApply is kept around in part to avoid breaking any code and in part
because there are cases where implementing foreach that way rather than with
a range is more efficient. IMHO, it also makes more sense in cases where
you're dealing with a transitive front - e.g. if std.stdio's byLine were
implemented via opApply and you _had_ to use byLineCopy when you wanted a
range, then we'd have avoided a lot of problems with byLine - though at
least we do now have byLineCopy instead of just byLine, even if byLine still
returns a range.

Random access has nothing to do with foreach in any of those cases, because
random access isn't ever used with foreach and user-defined types. The
closest you get is when you use index with foreach, and that works with
arrays (but not ranges) and with opApply. So, it's probably using random
access on arrays when iterating over them, but it doesn't with ranges in
general, and it doesn't with opApply unless the underlying implementation
happens to use random access inside of opApply; opApply itself isn't
designed to use random access any more than front and popFront are.

- Jonathan M Davis




More information about the Digitalmars-d-learn mailing list