July 29, 2004
"Juanjo Álvarez" <juanjuxNO@SPAMyahoo.es> wrote in message news:cec023$1svv$1@digitaldaemon.com...
> Juanjo Álvarez wrote:
>
> > Sean Kelly wrote:
> >
> >> In article <cebjlk$1n2q$1@digitaldaemon.com>, C. Sauls says...
> >>>
> >>>Looks promising to me... how likely would the following be, as well?
> >>>template foo(T : signed)
> >>>template foo(T : unsigned)
> >>>template foo(T : enum)
> >>>
> >>>I figure the more ways to narrow down the parameters, the better.  Maybe
> >>>templates could be further revised to have complex filters, such as:
> >>>template foo(T : struct || (signed && enum))
> >>
> >> This would be fantastic.  It would single-handedly eliminate a large bulk of meta garbage classes.
> >
> > Another strange idea, extending it to classes:
> >
> > template foo(T : ForwardIterable, BackwardIterable, Addable)
> >
> > Of couse ForwardIterable, BackwardIterable and Addable would be interfaces that the foo parameter must implement.
>
> And of course that syntax would not work because it takes the second and third interfaces as new parameters :). Anyway I've re-readed a little of the spec to find that you can do:
>
> interface ForwardIterable {  void fwiterate(); }
> interface BackwardIterable { void bwiterate(); }
> interface Addable          { /*opAdd and stuff */ }
> //Ugly
> iterface FwBwIterableAddable : ForwardIterable, BackwardIterable, Addable {}
>
> class A : FwBwIterableAddable {
>         void fwiterate() { return 0;}
>         void bwiterable() { return 0;}
> }
>
> template TFoo( T : FwBwIterableAddable ) {}
>
> main() { alias TFoo!(A)x; }
>
> But as you can see you have to declare an interface which inherits from all the interfaces and then declare the class to inherit from that interface to be allowed to limit the template parameter. Same effect, but uglier than just specifying a list of interfaces to the template parameter.
>
> Anyway I've done little D and none of that was very generic so I could be being really naive here (not that I care, that's one of my features ;).

I think we should just give Walter our requirements and expectations, and let his jogging brain come up with one of his customary neat minimalistic solutions.



July 29, 2004
In article <cebp7v$1pt7$2@digitaldaemon.com>, Matthew says...

[...]
>But one cannot do something such as
>
>    int j = accumulate(l.begin(), l.end(), 0);
>
>To do this, one has to provide the type(s), as in:
>
>    int j = accumulate!(List!(int).iterator, int)(l.begin ...)
>

Just shooting out an idea here: Could you make accumulate() a (static?) member
of List? Then you could get away with

#     int j = l.accumulate(l.begin(), l.end(), 0);

since accumulate() would then already be instantiated as (List!(int).iterator,
int).

To avoid rewriting accumulate() and all the other algorithms you would of course have to put them in a base class or use mixins or something. Also, you can't add user defined algorithms this way.

Nick


July 29, 2004
Matthew wrote:

> I think we should just give Walter our requirements and expectations, and let his jogging brain come up with one of his customary neat minimalistic solutions.

What about adding a (categorized and prioritized) wishlist page on the wiki?

July 29, 2004
"Nick" <Nick_member@pathlink.com> wrote in message news:cec125$1tem$1@digitaldaemon.com...
> In article <cebp7v$1pt7$2@digitaldaemon.com>, Matthew says...
>
> [...]
> >But one cannot do something such as
> >
> >    int j = accumulate(l.begin(), l.end(), 0);
> >
> >To do this, one has to provide the type(s), as in:
> >
> >    int j = accumulate!(List!(int).iterator, int)(l.begin ...)
> >
>
> Just shooting out an idea here: Could you make accumulate() a (static?) member
> of List? Then you could get away with
>
> #     int j = l.accumulate(l.begin(), l.end(), 0);
>
> since accumulate() would then already be instantiated as (List!(int).iterator,
> int).
>
> To avoid rewriting accumulate() and all the other algorithms you would of course have to put them in a base class or use mixins or something. Also, you can't add user defined algorithms this way.

Short answer: yes. This is exactly what I'm doing with the transformation methods in DTL.

But the problem in general is that there are an unbounded number of methods that one could seek to add. Whatever anyone might think about STL, its separation of containers from algorithms, communicating via iterators, is an incredibly elegant and powerful idea.

With the DTL containers, I'm restricting myself to a small set of operations, currently called:

- select() - returns a range containing elements matching a given function/delegate/functor predicate
- reject() - the opposite of select()
- collect() - returns a range containing the same number of elements, where each value in the returned collection is the
result of applying a given function/delegate/functor transformation function

and one or two others.

Wrt things like accumulate(), I'd argue that one must be content to use foreach if we don't get implicit instantiaton.



July 30, 2004
"Matthew" <admin@stlsoft.dot.dot.dot.dot.org> wrote in message news:cec0fl$1t7c$1@digitaldaemon.com...
> I'm with Sean on this one. Since D doesn't have implicit instantion, how
can an accumulate template be instantiated as
> shown above?

Can you post a complete example, and I can verify whether it is fixed or not.


July 30, 2004
In article <cebjlk$1n2q$1@digitaldaemon.com>,
 "C. Sauls" <ibisbasenji@yahoo.com> wrote:

> Walter wrote:
> > I hadn't realized that structs and classes cannot be discriminated in
> > template specialization, you're right. How does the following look:
> >     template foo(T : struct)
> > and:
> >     template foo(T : class)
> > ?
> 
> Looks promising to me... how likely would the following be, as well?
> 	template foo(T : signed)
> 	template foo(T : unsigned)
> 	template foo(T : enum)
> 
> I figure the more ways to narrow down the parameters, the better.  Maybe
> templates could be further revised to have complex filters, such as:
> 	template foo(T : struct || (signed && enum))
> 
> This would take as parameter wither a struct, or an enum that derived from a signed type (byte,short,int,long,cent..).  It would reject anything else, including an /un/signed enum (enum : ubyte,ushort,uint,ulong.ucent..).  The use of conditional operators is arbitrary, I guess anything could be used... maybe even new 'or' and 'and' keywords that are template-only.
> 
> But I'm sure a certain amount of this is dreaming on my part.  :)
> 
> -Chris S.
> -Invironz


I really like the idea of complex filters on template specialization.

Count my vote for.
July 30, 2004
"Matthew" <admin.hat@stlsoft.dot.org> escribió en el mensaje
news:ceaeid$18ir$1@digitaldaemon.com
|
| [very interesting read]
|

I have used STL only to play. Once I read TC++PL (I wanted to give C++ a try: sorry, no time). I've done even less with Java's Collections API. I've written somethings with D's foreach(). So, while I don't have a large knowledge about them, I understand they're very different approaches to the same issue, and to see you're trying to do all of that, is just way over my head.

There's a question coming: could it be possible that you're trying to achieve too much? I know it's a bit late for it, but do you think it could've been easier if you had done first this, then that, etc.? Just asking.

About your boxing module, did you know Andy wrote that some time ago? I haven't tested it, but I know it exists.

About your first litany, I agree with you. Sometimes something's working, and you add just one tiny correct thing, and the compiler gets lost. Sometimes just reorganizing modules makes everything stop working. And it's certainly impossible to reproduce it.

Besides that, I just can say don't give up. DTL looks very promising and I don't think any of us would like to lose it (and you) at this point. And release something. I'm not saying I'm going to help (I'm not saying I'm not, either), but, who knows, with luck everyone will stop what they're doing and check DTL and suggest things.

-----------------------
Carlos Santander Bernal


July 30, 2004
In article <cebp7v$1pt7$2@digitaldaemon.com>,
 "Matthew" <admin@stlsoft.dot.dot.dot.dot.org> wrote:

> "Sha Chancellor" <schancel@pacific.net> wrote in message news:schancel-C6DC99.10061329072004@digitalmars.com...
> > Matthew,
> >
> >    Compiler bugs aside, you forté make a few silly arguments.  Such as,
> > that you can't support iterators because you can't overload the *
> > operator.  What kind of BS is that?
> 
> I said "Neither of these preclude the creation of iterators - and I've done a little of that - ".
>
> Maybe you should have read it more thoroughly. :-(


No, but you did say : "D cannot support generic programming." Presumably, you were griping about it.  Also, you said "it means they're not really very usable."   Please elaborate.


> > Overloading operators for no apparent good reason is STLs forté.  Obj-C and Cocoa have lots of templates and it doesn't have any operator overloading what-so-ever.
> >
> > STLs and C++ use operator overloading incessantly  because somehow their designers thinks it looks cool.
> 
> Wrong. (Or half wrong anyway). They overload the operators for conformance
> with pointers. Surely you know/recognise that
> a pointer is a RandomAccess iterator?

An iterator class is still a class, not a pointer. End of story.  Don't
confuse syntax for types with needless philosophical semantics.
And a pointer is not a RandomAccess iterator, although it might be a
random access iterator....

> It's been my opinion - espoused often on the D ngs over the last year or so -
> that we don't need to directly support
> pointers as "first class" members of the enumerable club in D, since D's
> arrays (and any UDTs) are already enumerable
> via foreach().
> 
> This has been one of the motivating factors in my design toward a
> foreach-oriented library, with the consequences that
> two of the four of the enumeration "modes" / "models" in DTL are based on
> foreach.

Where are you going with this?

> 
> >   IT confuses whether or not an iterator
> > is a pointer or an object.  Why not just have a real function call:
> 
> Pointers, as explained above.

Classes, as explained above.

> 
> > Iterator.getMyFuckingInstanceNow()
> 
> 
> Yes. The iterators I've played with have taken this approach.

It makes the implementation more clear for novice programmers.

> 
> > No instead we must confuse things by going (*Iterator)
> >
> > Iterators in STL suck, plain and simple.  Most of C++'s standard template library is overly complicated and obtuse for the job.  Not to mention buggy between implementations.
> 
> At the risk of pissing off YAA, I think this is naive. (Aside: pretty much
> everyone in the world apart from fellow
> Englishmen tend to get shirty if I mention the "n" word. For my part, it's
> much less offensive to have one's opinion
> called naive, than ill-informed, or half-considered, or plain dumb. So naive
> it is.)

Which part of overly complicated, obtuse, and buggy between implementations is naive and ill-informed?  It doesn't matter if you have a special method to tie my shoes if I don't know about it, or can't remember how to use it.  Especially when I can tie my own shoes, I'll probably just go do that, rather than look up your auto-shoe-lace-tier.


> Yes, C++'s library is complex, and it's going to get a lot more so in C++-0.x.
> 
> Yes, templates are hard to understand, and template implementations are
> virtually impossible not to become dialecticised
> (?). Consider, even though I value simplicity in templates more highly than
> pretty much any other aspect, I've done some
> reasonably complex things with STLSoft, and some people have commented that
> that stuff is pretty
> advanced/over-complicated/obtuse/cool/stupid. Point being, I understand the
> complex techniques I've used in STLSoft, but
> I cannot understand the implementation of even small Boost modules, for the
> same reason that some Boosters cannot
> understand STLSoft: C++ is too complex.

Boost is too complicated too.

> But, C++ is powerful, and that's why we stick with it. To stand on the
> sidelines and just shout about how hard it is is
> plain silly, until something replaces it. I don't think I speak out of turn
> to say that Walter would like that to be D.
> To achieve that D *must* support the currently unmatched power of C++. The
> other issues are (i) whether it becomes as
> hard, and (ii) whether it engenders the confusing and disenfranchising
> dialectisation (?) of C++. I my opinion we can
> live with (i) if we must, because most developers are reasonably intelligent.
> But (ii) will kill it, because learning
> limitless dialects is incredibly irritating and a waste of effort. If D ends
> up being as big a bag of wild-woman's
> knitting as C++, then what's the motivation to move to D?

As I would like to see D become also.


> [Apologies to any wild-women who have neat knitting.]
> 
> > As for implicit instantation,  Why is this required to make an iterator?
> 
> Sigh. Either I have all the didactic talent of your average post-graduate
> tutorial host, or you've not read my post
> correctly.
> 
> What I said was that to use iterators generically, and without iterators
> sharing a common interface (e.g.
> IObjectEnumerator, or IEnumerator!(int)), we need implicit instantiation.


Explain why this would help please.


> 
> > Maybe I'm missing the boat, but what's wrong with something like this:
> >
> > class List(T) {
> >    alias ListIterator(T) iterator;
> >
> >    ...
> > }
> >
> > List!(int).iterator iter;
> > // Hell you could probably even take your existing instance and do:
> > // Foo.iterator iter;  In fact you should be able to but it seems you
> > can't  This would allow you to also do aliases for stuff like:
> >
> > iter.BaseType t; and do your generic manipulation functions. or List.BaseType; etc.  And have aliases in your class.
> 
> This kind of thing is already done. One can (or at least could - I've changed
> a lot of things since April, when I last
> built and tested with -version=UseIterators) do things such as:
> 
>     List!(int)    l = new ...
> 
>     for(List!(int).iterator b = l.begin(), e = l.end(); b != e; b.next())
>     {
>         int i = b.value();
>     }
> 
> But one cannot do something such as
> 
>     int j = accumulate(l.begin(), l.end(), 0);
> 
> To do this, one has to provide the type(s), as in:
> 
>     int j = accumulate!(List!(int).iterator, int)(l.begin ...)
> 
> [Actually, since all iterators must be classes, I've prescribed that they all
> have a standard set of member types, so
> it's possible to deduce the value type, as in:
> 
>     int j = accumulate!(List!(int).iterator)(l.begin ...)
> ]
> 
> Given that the (currently) only useful mode for iterators is where the type
> is explicit, it's my opinion (and that of
> others, I think) that there's no benefit over foreach, hence the focus on
> foreach for the container enumeration, and the
> enumeration of transformed ranges, as in:
> 
>     foreach(int i; l)
>     {
>         . . .
>     }
> 
> and
> 
>     foreach(int i; l.select(IsOdd))
>     {
>         . . .
>     }
> 
> >
> > I say we bitch at walter.
> >
> > for( iter = myList.begin();  iter != myList.end(); iter++ )
> > {
> >    printf(iter.getMyFuckingInstanceNow().toString());
> > }
> >
> > This is nearly identical to what C++ does, and i really don't see why it wouldn't work.
> 
> It can work. It does work. I've mentioned this many times on the NGs.
> 
> >  You could probably leave the instance-getter function
> > name a little shorter though.
> 
> D'ya think?
> 
> > Maybe you could expand as to why this sucks? (Besides that it's similar
> > to STL which sucks)
> 
> Again, a pointless comment that suggests ignorance, or a fondness for glib
> statements at best. STL is a mostly
> marvellous idea/technology, but the bits of it that are bad are glaringly
> bad. It does not suck, it's the current best
> effort at powerful generic programming. Just because something has bad parts
> doesn't mean it sucks. If that's the case,
> then everything sucks.
> 
> It's my hope and, I would think, that of most people in D, that DTL can be
> (nearly) as powerful as STL, but jettison
> most of the glaringly bad parts. I don't expect DTL to be without flaws, but
> it needs to be simpler, and less prone to
> spawning dialects, than STL. And it needs more power than the language
> currently provides.


STL is more overloaded and bulky than most things need.


> > And as for your template example:
> >
> >
> > #    template dump(T) {
> > #    void dump(IContainer!(T) c)
> > #    {
> > #        for(IEnumerator e = c.enumerate(); e.hasMoreElements; )
> > #        {
> > #
> > #        }
> > #    }
> > #    }
> > #
> > #    List!(int, IContainer!(int))           l = new ...;
> > #
> > #    dump(l);
> >
> > For one, making those aliases all over is just as ugly and hard to remember as just specifying it.  Second:
> >
> > You're passing in l of type List!(int, IContainer!(int)), and then
> > proceed to do this with it:
> >
> > IContainer!(List!(int, IContainer!(int))) c.
> >
> > Is that really what you were intending to do?
> 
> I'm afraid I can't follow the last section. Can you rephrase?

Never mind, the way you used templates there is a bit odd.  Let me see if I've got this correct:

Since you've got a function with the same name as the template some magic happens here presumably.

dump( List!(int, IContainer!(int)) );

Would be equivalent to:

dump!(int).dump( List!(int, IContainer!(int)) );

in this case? And List!(int, IContainer!(int)) would be seen as a IContainer!(int) due to the specified interface?


> > It seems like templates should support something along these lines:
> >
> > #   template dump( T : IContainer!(T) ) {
> > #      void dump( IContainer!(t) ) {
> > #      }
> > #   }
> >
> > Although I seriously doubt that works as it is.
> 
> What's "t"? If you mean "T", then I presume the different you're providing is
> the constraint on T to be "in" an
> IContainer!(T)?? Doesn't the function signature already do that? Please
> elucidate.

I'm sorry, I made a capitalization error.

Yes I would be constraining it to be in an IContainer, But also you would then deduce the template's type via template specialization.  Then you could use the base type.  But yes, it looks like your example already does that, I overlooked it.
July 30, 2004
"Carlos Santander B." <carlos8294@msn.com> wrote in message news:cec3is$1ug7$1@digitaldaemon.com...
> "Matthew" <admin.hat@stlsoft.dot.org> escribió en el mensaje
> news:ceaeid$18ir$1@digitaldaemon.com
> |
> | [very interesting read]
> |
>
> I have used STL only to play. Once I read TC++PL (I wanted to give C++ a try: sorry, no time). I've done even less with Java's Collections API. I've written somethings with D's foreach(). So, while I don't have a large knowledge about them, I understand they're very different approaches to the same issue, and to see you're trying to do all of that, is just way over my head.
>
> There's a question coming: could it be possible that you're trying to achieve too much?

It's certainly likely that I've tried to achieve too much in the first instance.

But, no, I do not believe the DTL "vision" is overblown. In fact, I think it's really neat, easily explained, and self-contained. (But then I would think that, I suppose)

> I know it's a bit late for it, but do you think it could've been easier if you had done first this, then that, etc.? Just asking.

Most certainly.

> About your boxing module, did you know Andy wrote that some time ago? I haven't tested it, but I know it exists.

No. Where is it? How to I get it? I'd like to get a look at that.

btw, do you mean Andy Friesen? Andy, want to knock heads together on this?

Mine was just a stab to get me what I needed, and was not intended to be the all-things-for-all-men (or women!) approach. However, I thought it might serve as a base for that.

> About your first litany, I agree with you. Sometimes something's working, and you add just one tiny correct thing, and the compiler gets lost. Sometimes just reorganizing modules makes everything stop working. And it's certainly impossible to reproduce it.

Hurrah! So it's not just me, then.

> Besides that, I just can say don't give up. DTL looks very promising and I don't think any of us would like to lose it (and you) at this point.

Thanks. I confess I've been skirting the throwing-the-towel-in point over the last couple of weeks. Thankfully, the gritty Yorkshireman in me jumped out and gave me a kick up the arse. :)


> And release
> something. I'm not saying I'm going to help (I'm not saying I'm not, either),
> but, who knows, with luck everyone will stop what they're doing and check DTL
> and suggest things.

Ok, arm-twisters all. I shall release 0.1 this weekend. It will only have type 1 ("foreach") enumeration capabilities for each container, although some of the other enumeration types will be available for some of the containers. Then we can take it from there.

(btw, the actual "containment" implementations were all done in a couple of days in March, so they may not be optimal. That doesn't matter of course, but I just don't want anyone to think that any aspects of the lib are production-ready yet.)



July 30, 2004
In article <cebp7v$1pt7$2@digitaldaemon.com>, Matthew says...

>[Actually, since all iterators must be classes, I've prescribed that they all have a standard set of member types, so it's possible to deduce the value type, as in:
>
>    int j = accumulate!(List!(int).iterator)(l.begin ...)
>]

Actually, you could do it this way even with pointers:

# template accumulate(T: T*) { /* pointer iterators go here */ }
# template accumulate(T: IteratorBase) { /* class iterators here */ }

but it would mean you'd have to implement everything twice, which isn't exactly optimal :)

>Given that the (currently) only useful mode for iterators is where the type
> is explicit, it's my opinion (and that of others, I think) that there's no benefit over foreach, hence the focus on foreach for the container enumeration,

I hope this doesn't mean you want to drop algorithms from DTL altogether? I think replacing sort() with a foreach will be a tad difficult.

Nick