Lars Ivar Igesund wrote:
Andrei Alexandrescu wrote:
Lars Ivar Igesund wrote:
Andrei Alexandrescu wrote:
Lars Ivar Igesund wrote:
Andrei Alexandrescu wrote:
For example, I'm not sure how code in std.algorithm could
help containers or streams in Tango (as it should), or how
to reconcile std.algorithm with std.core.array.
If the language (D2++) will have a new way of iteration and
ranges known and enforced by the compiler, then I expect
Tango to support those at some point, and std.algorithm would
presumably just work. However, if it is based on some
interface, ad hoc (these methods must be present) or properly
via an interface Range { }, I would expect Tango developers
to be involved in the process of defining those interfaces
(if Tango is meant to use/know about them). Since I have seen
neither, it is somewhat difficult to make a well informed
comment on the subject.
It's been there for a while now (since 25 Nov 2008).
http://www.digitalmars.com/d/2.0/statement.html#ForeachStatement
Scroll down to "Foreach over Structs and Classes with Ranges".
The changelog reflects that too:
http://www.digitalmars.com/d/2.0/changelog.html
Version 2.021 mentions "Added range support to foreach
statement."
Ah, thanks :)
However, replacing the "single" opApply with 5 properties seems
somewhat excessive? At least it becomes even more obvious that a
form of (runtime queryable) struct interfaces will be necessary -
the one and only feature I really really want in D2.
opApply was very inefficient and defining an abstraction that
allows efficient iteration was a key goal of range design and
foreach overhaul. Using duck typing and implicit interfaces was a
tried and true technique. On top of this framework it is easy to
define and use explicit interfaces. Using classic interfaces would
have hamstrung efficiency of iteration from day one.
I'd be curious to find out more about a runtime queryable struct
interface. How would it work? What idioms would it enable?
The point is that with classes and interfaces, you can query the
class (at runtime) for whether it contains a certain set of
functionality.
I think there are a number of confusions and misunderstandings at work
here on top of one another, so allow me to try and clarify a couple.
"Five properties versus one opApply seems excessive. Therefore, a
form of runtime-queryable interface for struct is necessary."
The latter doesn't follow from the former. If five properties in an
implicit interface seems too many, then what you might be asking for is
explicit interfaces, not dynamic-polymorphic interfaces. Something along
the lines of:
interface InputRange(T)
{
void next();
bool empty();
T head();
}
struct RandomGenerator : InputRange!(int) { ... }
class IntStream : InputRange!(int) { ... }
The two would follow different implementation strategies. For structs
the interface would be statically checked. In all likelihood, this
feature will be part of D2 because it allows for easy concept checking.
Now, I know that the virtuality of doing so isn't the most efficient
in most cases, but that is besides the point - if there is an
efficient way of doing this with structs, then that should work with
classes too.
This I don't understand at all. Yes, implicit interfaces do work with
structs and classes and equally well.
When you have functionality (at runtime) that relies only on a
container to have a specific set of functions/properties/methods,
then it seems unfair to restrict that to classes. In practice I see
this as something that operates via additional type info.
I confess I read this one more than a few times and couldn't understand
it. So let me read it back in my own words: "You want to implement
runtime functionality (?) by relying on the existence of a specific set
of functions/properties/methods. It is unfair to restrict that to
classes, so I'd like that to work for structs too. The way I see this
working is by adding extra type info to structs." This doesn't do
anything in terms of clarifying things for me, so I'd appreciate more info.
Andrei