Thread overview | |||||||||||||||||||||||||||||||||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
July 18, 2004 Why D needs implicit instantion or an autotype keyword | ||||
---|---|---|---|---|
| ||||
Ok, some of you may have followed a recent post describing composition of filtering operations on DTL containers, e.g. foreach(X x; cont.select!(SomePredicate).collect(SomeTxFunction).select(SomeDelegate)) { . . . } Although the compiler currently eats my machine when trying to compile this, I'm pretty confident that it can be achieved soon without much hassles. This all works reasonably neatly because all <range> objects (those returned by transformations on containers or other <ranges>) support foreach. So far so good. There'll also be support for getting a specific item out of container/range, via methods like max(), min_if(), find_first(), as in: Person m = cont.select!(SomePredicate).collect(SomeTxFunction).max(SomeDelegate) That's also quite straightforward. However, here's the rub. If you want to get hold of a range and save it for later processing, you need to know its type. The problem is that its type can be something incredibly complex. Consider the following fictional case, where we're filtering the contents of a List of Person container: List!(Person) results of select() (with delegate IsMan): MatchedNotionalRange!(_ListUtil!(Person).ListRange, DelegatePredicate!(bool delegate(in Person value), Person)) Now that's just the one level. Imagine what it looks like when we're composing another filter on top of the results of select()! In C++ one can obviate such things by writing working template functions. Since C++ supports implicit instantiation, the worker function can deduce such horrendous mouthfuls for us. Of course, this is not always appropriate, but it does help a lot. Since D is not going to have implicit instantiation, I suggest that we *must* have the autotype keyword, which will be akin to the semantics proposed for auto in C++ 0.x. That is to say, the type is deduced, at compile time - it's no variant type! - from the initialising expression, so: bool IsOdd(Number n); Number Square(Number n); autotype r = cont.select!(IsOdd).collect(Square) . . . for(; r.open; r.advance()) { writeln("Number: ", r.current); } AFAIUI, there's no major conceptual difficulty in doing this, since the compiler already knows the type of the initialising expression. The only area of uncertainty is that we might lose the polymorphic nature of the type, but I'd say that if you know what type it should be, then you don't need autotype. Kind of axiomatic, but maybe I've missed something Thoughts, everyone? Walter?!? |
July 18, 2004 Re: Why D needs implicit instantion or an autotype keyword | ||||
---|---|---|---|---|
| ||||
Posted in reply to Matthew | "Matthew" <admin@stlsoft.dot.dot.dot.dot.org> wrote in message news:cddhd8$275p$2@digitaldaemon.com... > Ok, some of you may have followed a recent post describing composition of filtering operations on DTL containers, e.g. > > > foreach(X x; > cont.select!(SomePredicate).collect(SomeTxFunction).select(SomeDelegate)) > { > . . . > } > > Although the compiler currently eats my machine when trying to compile this, I'm > pretty confident that it can be achieved soon without much hassles. This all > works reasonably neatly because all <range> objects (those returned by transformations on containers or other <ranges>) support foreach. So far so good. > > There'll also be support for getting a specific item out of container/range, via > methods like max(), min_if(), find_first(), as in: > > Person m = > cont.select!(SomePredicate).collect(SomeTxFunction).max(SomeDelegate) > > That's also quite straightforward. > > However, here's the rub. If you want to get hold of a range and save it for later > processing, you need to know its type. The problem is that its type can be something incredibly complex. > > Consider the following fictional case, where we're filtering the contents of a > List of Person > > container: List!(Person) > results of select() (with delegate IsMan): > MatchedNotionalRange!(_ListUtil!(Person).ListRange, DelegatePredicate!(bool > delegate(in Person value), Person)) > > Now that's just the one level. Imagine what it looks like when we're composing > another filter on top of the results of select()! > > In C++ one can obviate such things by writing working template functions. Since > C++ supports implicit instantiation, the worker function can deduce such horrendous mouthfuls for us. Of course, this is not always appropriate, but it > does help a lot. > > Since D is not going to have implicit instantiation, I suggest that we *must* > have the autotype keyword, which will be akin to the semantics proposed for auto > in C++ 0.x. That is to say, the type is deduced, at compile time - it's no variant type! - from the initialising expression, so: > > bool IsOdd(Number n); > Number Square(Number n); > > autotype r = cont.select!(IsOdd).collect(Square) > > . . . > > for(; r.open; r.advance()) > { > writeln("Number: ", r.current); > } > > AFAIUI, there's no major conceptual difficulty in doing this, since the compiler > already knows the type of the initialising expression. The only area of uncertainty is that we might lose the polymorphic nature of the type, but I'd say > that if you know what type it should be, then you don't need autotype. Kind of > axiomatic, but maybe I've missed something > > Thoughts, everyone? Walter?!? I like it! I also liked that proposal for C++, so why not for D? :) |
July 18, 2004 Re: Why D needs implicit instantion or an autotype keyword | ||||
---|---|---|---|---|
| ||||
Posted in reply to Matthew | >Thoughts, everyone? Walter?!?
Well, I proposed this some time ago, got only good response, but Walter didn't answer.
If you look at Walters style you can understand this. He declares all variables on top of his functions, like Pascal coders do or C programmers before 1999.
Anyway, I don't like the name autotype. In C++0x auto is used so they don't have to introduce a new keyword. But auto is already used in D (well it is in C++, too, but with another meaning, that can't conflict in the situations, where you need the new auto).
Other languages use let, var or val for this. Why don't we use one of these words?
-- Matthias Becker
|
July 18, 2004 Re: Why D needs implicit instantion or an autotype keyword | ||||
---|---|---|---|---|
| ||||
Posted in reply to Matthias Becker | "Matthias Becker" <Matthias_member@pathlink.com> wrote in message news:cddv6v$2bi8$1@digitaldaemon.com... > >Thoughts, everyone? Walter?!? > > Well, I proposed this some time ago, got only good response, but Walter didn't > answer. > > If you look at Walters style you can understand this. He declares all variables > on top of his functions, like Pascal coders do or C programmers before 1999. > > Anyway, I don't like the name autotype. In C++0x auto is used so they don't have > to introduce a new keyword. But auto is already used in D (well it is in C++, > too, but with another meaning, that can't conflict in the situations, where you > need the new auto). > > Other languages use let, var or val for this. Why don't we use one of these > words? I don't really care about the name, although I don't like let and val, and I assume var will be reserved for a built-in variant type in the future. |
July 18, 2004 Re: Why D needs implicit instantion or an autotype keyword | ||||
---|---|---|---|---|
| ||||
Posted in reply to Matthew | You are talking about two connected but distinct issues here: implicit instantiation and automatic type deduction for local variables.
The first is dearly needed for template metaprogramming, and especially for expression templates. It is far more than just a convenience issue. A nested expression of moderate complexity, will usually have a type of nested templates of the same depth. Furthermore: the exact type of the expression may not even be easy to deduct, but it may follow from some lengthy compile-time computation.
With types of local variables, the situation is similar. Of course, you could in principle always deduct them and give them explicitly, but for a non-trivial meta-program, this deduction may be arbitrarily complicated. The compiler, of course, can always deduct it (that's why it is called compile-time-computation).
B.t.w: autotypes for local variables have proven rather convenient in Sather as well. There is no meta-programming possibility, so it really is just a matter of convenience, but still, you quickly get addicted to it...
Matthew wrote:
> Ok, some of you may have followed a recent post describing composition of filtering operations on DTL containers, e.g.
>
>
> foreach(X x;
> cont.select!(SomePredicate).collect(SomeTxFunction).select(SomeDelegate))
> {
> . . .
> }
>
> Although the compiler currently eats my machine when trying to compile this, I'm pretty confident that it can be achieved soon without much hassles. This all works reasonably neatly because all <range> objects (those returned by transformations on containers or other <ranges>) support foreach. So far so good.
>
> There'll also be support for getting a specific item out of
> container/range, via methods like max(), min_if(), find_first(), as in:
>
> Person m =
> cont.select!(SomePredicate).collect(SomeTxFunction).max(SomeDelegate)
>
> That's also quite straightforward.
>
> However, here's the rub. If you want to get hold of a range and save it for later processing, you need to know its type. The problem is that its type can be something incredibly complex.
>
> Consider the following fictional case, where we're filtering the contents of a List of Person
>
> container: List!(Person)
> results of select() (with delegate IsMan):
> MatchedNotionalRange!(_ListUtil!(Person).ListRange,
> DelegatePredicate!(bool delegate(in Person value), Person))
>
> Now that's just the one level. Imagine what it looks like when we're composing another filter on top of the results of select()!
>
> In C++ one can obviate such things by writing working template functions. Since C++ supports implicit instantiation, the worker function can deduce such horrendous mouthfuls for us. Of course, this is not always appropriate, but it does help a lot.
>
> Since D is not going to have implicit instantiation, I suggest that we *must* have the autotype keyword, which will be akin to the semantics proposed for auto in C++ 0.x. That is to say, the type is deduced, at compile time - it's no variant type! - from the initialising expression, so:
>
> bool IsOdd(Number n);
> Number Square(Number n);
>
> autotype r = cont.select!(IsOdd).collect(Square)
>
> . . .
>
> for(; r.open; r.advance())
> {
> writeln("Number: ", r.current);
> }
>
> AFAIUI, there's no major conceptual difficulty in doing this, since the compiler already knows the type of the initialising expression. The only area of uncertainty is that we might lose the polymorphic nature of the type, but I'd say that if you know what type it should be, then you don't need autotype. Kind of axiomatic, but maybe I've missed something
>
> Thoughts, everyone? Walter?!?
|
July 18, 2004 Re: Why D needs implicit instantion or an autotype keyword | ||||
---|---|---|---|---|
| ||||
Posted in reply to Matthew | Matthew wrote:
> Since D is not going to have implicit instantiation, I suggest that we *must*
> have the autotype keyword, which will be akin to the semantics proposed for auto
> in C++ 0.x. That is to say, the type is deduced, at compile time - it's no
> variant type! - from the initialising expression, so:
>
> Thoughts, everyone? Walter?!?
It even looks (to my feeble brain, at least) easy to implement:
autotype r = expr;
// equivalent to:
typeof(expr) r = expr;
-- andy
|
July 18, 2004 Re: Why D needs implicit instantion or an autotype keyword | ||||
---|---|---|---|---|
| ||||
Posted in reply to Matthew Wilson | > I don't really care about the name, although I don't like let and val, and I > assume var will be reserved for a built-in variant type in the future. I like "val", it reminds me of ML. |
July 18, 2004 Re: Why D needs implicit instantion or an autotype keyword | ||||
---|---|---|---|---|
| ||||
Posted in reply to Norbert Nemec | > B.t.w: autotypes for local variables have proven rather convenient in Sather > as well. There is no meta-programming possibility, so it really is just a matter of convenience, but still, you quickly get addicted to it... It sure would be sweet to have both in 2.0. I like it even before I've tried it. :-) val t, i; ... t = s[5 .. 25]; i = index(s,"abc"); begone bloat |
July 19, 2004 Re: Why D needs implicit instantion or an autotype keyword | ||||
---|---|---|---|---|
| ||||
Posted in reply to Andy Friesen | "Andy Friesen" <andy@ikagames.com> escribió en el mensaje news:cde51k$2dpc$1@digitaldaemon.com | Matthew wrote: || Since D is not going to have implicit instantiation, I suggest that we *must* || have the autotype keyword, which will be akin to the semantics proposed for auto || in C++ 0.x. That is to say, the type is deduced, at compile time - it's no || variant type! - from the initialising expression, so: || || Thoughts, everyone? Walter?!? | I don't really care about the name, but I do like the idea. | It even looks (to my feeble brain, at least) easy to implement: | | autotype r = expr; | // equivalent to: | typeof(expr) r = expr; | | -- andy What if "expr" is really complex (like that really long expression that Matthew posted before) and the compiler can't directly determine what it's type is? Wouldn't it mean evaluating it twice? Of course, if it just can't happen, then just tell me so, I just wanna be sure. ----------------------- Carlos Santander Bernal |
July 19, 2004 Re: Why D needs implicit instantion or an autotype keyword | ||||
---|---|---|---|---|
| ||||
Posted in reply to Carlos Santander B. | > What if "expr" is really complex (like that really long expression that Matthew posted before) and the compiler can't directly determine what it's type is? Wouldn't it mean evaluating it twice? Of course, if it just can't happen, then just tell me so, I just wanna be sure.
I can't imagine. To test this write
type value = expr;
where typeof(expr) is incompatible with type, and expr is an arbitrarily
complex expression.
It should be clear that since the compiler can catch type mismatches between the type of value and the type of expr, it must know the type of expr and hence be able to deduce the type of a val/autotype.
I can imagine implicit template instantiation complex to implement though. But then either it can deduce the types or it can't, in which case compilation fails.
|
Copyright © 1999-2021 by the D Language Foundation