User defined type and foreach
Jonathan M Davis
newsgroup.d at jmdavisprog.com
Sat Nov 18 07:15:48 UTC 2017
On Saturday, November 18, 2017 05:24:30 Tony via Digitalmars-d-learn wrote:
> On Friday, 17 November 2017 at 17:55:30 UTC, Jonathan M Davis
> > So, in the general case, if you want to use a range in foreach
> > without consuming the range, it needs to be a forward range,
> > and you need to call save. e.g.
> >
> > foreach(e; range.save)
>
> Seems like you can make class-based ranges to work on multiple
> foreach calls without having to do save, although maybe it falls
> apart in other usage.
A range that was a class would just be completely consumed by foreach unless
you used break to exit the loop early. But my point is that in generic code,
you can't copy a range and then use it any more after copying it without
assigning it a new range, because the behavior is unspecified, and different
ranges will act differently. Similarly, in generic code, you must call save
when you want to get another copy of the range that can then be iterated
independently. In non-generic code, you can choose to depend on the
behavior of the specific range that you're using, but for the same code to
work with all types of ranges, you're a bit more restricted.
> It also doesn't appear that the compiler
> requires an @property annotation as specified in the interface :
@property does almost nothing in general. All it really does is affect how
some stuff like typeof works. So, code introspection can be affected by
@property, but whether you put @property on something like empty or front
really doesn't matter. A lot of us do it out of habit and/or to make it
clear that it's intended to be used as a property function, but any function
which returns a value but has no parameters can be used as a getter property
regardless of whether @property is used. And what the range API really cares
about is that the code in isInputRange, isForwardRange, etc. compiles, not
that anything is marked with @property. It's not even sure that everything
involved is a function - e.g. infinite ranges are ranges where empty is
known to be false at compile time, and that's usually done by defining empty
as an enum, in which case it's not a function at all. However, it can be
called the same way, so the same code work with a range that defines empty
as a function and a range that defines it as an enum or variable, since the
range API expects empty to be called without parens.
Originally, @property was supposed to do more with optional parens going
away, but it never really happened (optional parens became too popular once
UFCS was added to the language). The main problem that it may yet be made to
solve is property functions which return callables. Right now, if you use ()
on a property function (whether it has @property on it or not), they're the
optional parens of the function call, whereas if the property were a
variable, the parens would either trigger opCall or call a delegate
(depending on the type of the variable). So, you can't currently turn a
public variable that's a callable into a property function and have it work
as a property function. @property could be made to indicate that in that
case, the single set of parens should be called on the return value rather
than the function itself, in which case, you could have a property that's a
callable, but while that has been discussed, it's never happened. So, for
now at least, @property really doesn't do much.
- Jonathan M Davis
More information about the Digitalmars-d-learn
mailing list