February 15, 2007
Walter Bright wrote:
> Andrei Alexandrescu (See Website For Email) wrote:
>> Your example shows that you are able to make a list, but it gives zero
>> indication on whether you can express what a list _is_.
> 
> I just don't feel that everything that can be abstracted away, should be. Sometimes a trivial list is just a ->next, and doesn't need any more than that. Sometimes, I just want to do x*x*x rather than abstracting away a cube(T)(T x) function.
> 
> An abstraction becomes useful when it's repeated repeatedly, not when it's used once or twice.

Of course I agree with that, but I also think lists are quite a worthy-for-reuse abstraction so it's not inspired to choose it to bash needless abstraction.

Here's a more humorous take on the subject:

http://www.willamette.edu/~fruehr/haskell/evolution.html


Andrei

February 15, 2007
Andrei Alexandrescu wrote

<citing>
> "One of the things we should demand from a
> powerful programming language is the ability to build abstractions
> by assigning names to common patterns and then to work in terms of
> the abstractions directly."
</citing>

Isn't there a contradiction, when one requires to use new abstractions but forbids reinterpretations of older ones?

-manfred
February 15, 2007
Nicolai Waniek wrote:
Nicolai Waniek wrote:
> janderson wrote:
>> What about using it for files that you are going to load at runtime
>> otherwise? XML ect...?
>>
>> -Joel
> 
> Loading the file belongs to runtime. Well, if it would take 10 minutes
> to load the file instead of 1 second if it was "loaded during
> compilation", that would be an argument for something like that - but I
> guess this won't be the case in most projects.
> 
> With your example: If you define something like that for compile time,
> it won't make it possible to change this dynamically, e.g. with a
> configuration file. If you write a super-D-duper library that loads file
> xyz and converts it to zyx, you won't want to sell the code (if it's not
> open source) so this possibility won't even fit to your business...
> 
> So, if "a" stands for "easy to learn, easy to use, fixed language" and
> "b" for "hard to learn because of dynamic language extension" you might
> get something like this for "not using mixins and that kind of stuff":
> 
> a [---|-----------] b
> 
> and the following, if you use them:
> 
> a [----------|----] b
> 
> Well I have to admit that there are some real good and well thought-out
> examples on how to reasonably use the new language features, but there
> will be more examples on how to _not_ use them. and the latter ones will
> be the ones with which we will have to struggle - and I don't want to
> struggle when programming, it usually is a joy! (and that's why I don't
> want to code in C++).

> janderson wrote:
>> What about using it for files that you are going to load at runtime
>> otherwise? XML ect...?
>>
>> -Joel
> 
> Loading the file belongs to runtime. Well, if it would take 10 minutes
> to load the file instead of 1 second if it was "loaded during
> compilation", that would be an argument for something like that - but I
> guess this won't be the case in most projects.
> 
> With your example: If you define something like that for compile time,
> it won't make it possible to change this dynamically, e.g. with a
> configuration file. If you write a super-D-duper library that loads file
> xyz and converts it to zyx, you won't want to sell the code (if it's not
> open source) so this possibility won't even fit to your business...
> 
> So, if "a" stands for "easy to learn, easy to use, fixed language" and
> "b" for "hard to learn because of dynamic language extension" you might
> get something like this for "not using mixins and that kind of stuff":
> 
> a [---|-----------] b
> 
> and the following, if you use them:
> 
> a [----------|----] b
> 
> Well I have to admit that there are some real good and well thought-out
> examples on how to reasonably use the new language features, but there
> will be more examples on how to _not_ use them. and the latter ones will
> be the ones with which we will have to struggle - and I don't want to
> struggle when programming, it usually is a joy! (and that's why I don't
> want to code in C++).

My point is that you shouldn't have to fight if its made as simple as run-time.

-Joel
February 15, 2007
Bill Baxter wrote:
> Nicolai Waniek wrote:
>> janderson wrote:
>>> What about using it for files that you are going to load at runtime
>>> otherwise? XML ect...?
>>>
>>> -Joel
>>
> On the other hand, that doesn't mean you need import to do it.  You can always write an external tool too 'stringify' a data file.  In fact that's exactly what I did: http://www.dsource.org/projects/luigi/browser/trunk/luigi/wrapres.d
> 
> The new import makes much (but not all) of the functionality of that converter unnecessary.
> 
> --bb

Stringify won't work for scripting or network mapping.  The number of libraries that I've seen that compile down to C++ to get around its limitations illustrate how useful this feature will be.  If its not provided you've got more problems when dealing with these libraries. Admittedly I probably see more examples because of the industry I work in.

-Joel
February 15, 2007
Manfred Nowak wrote:
> Andrei Alexandrescu wrote
> 
> <citing>
>> "One of the things we should demand from a
>> powerful programming language is the ability to build abstractions
>> by assigning names to common patterns and then to work in terms of
>> the abstractions directly." 
> </citing>
> 
> Isn't there a contradiction, when one requires to use new abstractions but forbids reinterpretations of older ones?

It's not new vs. old nor about reinterpretation. It's higher-level vs. lower-level.

Andrei
February 15, 2007
Andrei Alexandrescu (See Website For Email) wrote:
> James Dennett wrote:
>> C++, of course, has std::for_each(e.begin(), e.end(), do_x);
>> in its library (though that's weaker than it could be because
>> of lack of support for convenient anonymous functions/lambdas).
>>
>> C++0x is very likely to have for(v: e).  It's implemented
>> in ConceptGCC already. Java already has essentially that,
>> as does C#.  This really doesn't set D apart (but at least
>> D isn't falling behind here).
> 
> BTW, D might soon have simultaneous iteration that will blow away all conventional languages:
> 
> foreach (i ; coll1) (j ; coll2)
> {
>   ... use i and j ...
> }
> continue foreach (i)
> {
>   ... coll2 finished; use i ...
> }
> continue foreach (j)
> {
>   ... coll1 finished; use j ...
> }
> 
> Best languages out there are at best ho-hum when it comes about iterating through simultaneous streams. Most lose their elegant iteration statement entirely and come with something that looks like an old hooker early in the morning.
> 
> 
> Andrei

Just a random thought.  It would be a good idea to post these sort of things as a new post.  It been very hard to follow with all these mega threads of late.

-Joel
February 15, 2007
Andrei Alexandrescu (See Website For Email) wrote:
> Bill Baxter wrote:
>> kris wrote:
>>> kris wrote:
>>>> Bill Baxter wrote:
>>>>
>>>>> Frits van Bommel wrote:
>>>>>
>>>>>> By the way, would the new loop syntax allow more than two collections to be simultaneously iterated?
>>>>>
>>>>>
>>>>>
>>>>> Whoa!  I certainly hope so.  It hadn't even occurred to me that Andrei might mean this syntax can only be used for just two collections.  If that's the case then ... ick.
>>>>>
>>>>> --bb
>>>>
>>>>
>>>> InterleavedIterator does multiple collections via using multiple instances of InterleavedIterator. It's simple to use, and only needs to be written once. Would be better to implement some basic iterator needs than to introduce some tricky new syntax?
>>>>
>>>> - Kris
>>>
>>>
>>> Should have given an example. Simple case with 2 entities:
>>>
>>> auto two = InterleavedInterator (x, y);
>>> foreach (x; two) ...
>>>
>>> more than 2:
>>>
>>> auto three = InterleavedInterator (two, z);
>>> foreach (x; three) ...
>>
>> Should have also mentioned where one can find this mythical InterleavedIterator.
> 
> The issue with such a multi-iterator is that it makes it easier to make errors, and harder to write efficient and correct code that's statically verifiable.
> 
> I'm not sure when the interleaved iterator stops iterating, but there are two possibilities, none of which is satisfactory:
> 
> 1. Stop after the shortest of the two collections is done. Then user code must query the state of the iterator after the loop to figure what extra work is to be done:
> 
> auto two = InterleavedInterator (x, y);
> foreach (x; two) { ... }
> if (two.MoreData(0)) {
>   auto back2one = two.Project(0); // fetch the first iterator
>   foreach (x ; back2one) { ... }
> } else if (two.moreData(1)) {
>   ... same (or)deal ...
> }
> 
> This is way more work than there should.
> 

How about just simply:

  auto two = InterleavedInterator (x, y);
  foreach (x; two) { ... }
  foreach (a; two.Project(0)) { ... } // fetch the first iterator
  foreach (b; two.Project(1)) { ... } // fetch the second iterator

One of the two last foreach's won't execute a cicle because there is no data.

> 2. Stop after the longest of the two collections is done. Then user code must ensure _at each step_ that both iterators have meaningful data:
> 
> auto two = InterleavedInterator (x, y);
> foreach (x; two) {
>   if (two.HasData(0)) { ... }
>   else { ... only the second iter has data ... }
> }
> 
> This is unclear, verbose, and probably suboptimal.
> 

Maybe, but how does your multi foreach proposal helps at all? (see below)

> The scoping of foreach links the scope of the variables with their validity range, which rules out a class of possible errors entirely:
> 
> foreach (x ; c1) (y ; c2) (z ; c3) {
>   ... x, y, z syntactically accessible _and_ valid ...
> }
> continue foreach (x, z) {
>   ... x is both invalid _and_ syntactically inaccessible ...
> }
> 

I din't understand the above. Did you mean 'y' instead of one of those 'x' ?

-- 
Bruno Medeiros - MSc in CS/E student
http://www.prowiki.org/wiki4d/wiki.cgi?BrunoMedeiros#D
February 15, 2007
Andrei Alexandrescu (See Website For Email) wrote:
> James Dennett wrote:
>> C++, of course, has std::for_each(e.begin(), e.end(), do_x);
>> in its library (though that's weaker than it could be because
>> of lack of support for convenient anonymous functions/lambdas).
>>
>> C++0x is very likely to have for(v: e).  It's implemented
>> in ConceptGCC already. Java already has essentially that,
>> as does C#.  This really doesn't set D apart (but at least
>> D isn't falling behind here).
> 
> BTW, D might soon have simultaneous iteration that will blow away all conventional languages:
> 
> foreach (i ; coll1) (j ; coll2)
> {
>   ... use i and j ...
> }
> continue foreach (i)
> {
>   ... coll2 finished; use i ...
> }
> continue foreach (j)
> {
>   ... coll1 finished; use j ...
> }
> 
> Best languages out there are at best ho-hum when it comes about iterating through simultaneous streams. Most lose their elegant iteration statement entirely and come with something that looks like an old hooker early in the morning.
> 
> 
> Andrei

Hum. Correct me if I'm wrong, but that proposal would also require adding an iterator concept to iterable types, since the current opApply() mechanism can't suport such simultaneous iteration.

-- 
Bruno Medeiros - MSc in CS/E student
http://www.prowiki.org/wiki4d/wiki.cgi?BrunoMedeiros#D
February 15, 2007
Bruno Medeiros wrote:
> Andrei Alexandrescu (See Website For Email) wrote:
>> James Dennett wrote:
>>> C++, of course, has std::for_each(e.begin(), e.end(), do_x);
>>> in its library (though that's weaker than it could be because
>>> of lack of support for convenient anonymous functions/lambdas).
>>>
>>> C++0x is very likely to have for(v: e).  It's implemented
>>> in ConceptGCC already. Java already has essentially that,
>>> as does C#.  This really doesn't set D apart (but at least
>>> D isn't falling behind here).
>>
>> BTW, D might soon have simultaneous iteration that will blow away all conventional languages:
>>
>> foreach (i ; coll1) (j ; coll2)
>> {
>>   ... use i and j ...
>> }
>> continue foreach (i)
>> {
>>   ... coll2 finished; use i ...
>> }
>> continue foreach (j)
>> {
>>   ... coll1 finished; use j ...
>> }
>>
>> Best languages out there are at best ho-hum when it comes about iterating through simultaneous streams. Most lose their elegant iteration statement entirely and come with something that looks like an old hooker early in the morning.
>>
>>
>> Andrei
> 
> Hum. Correct me if I'm wrong, but that proposal would also require adding an iterator concept to iterable types, since the current opApply() mechanism can't suport such simultaneous iteration.

Correct.

Andrei
February 16, 2007
Andrei Alexandrescu (See Website For Email) wrote:
> Bill Baxter wrote:
>>
>> You're of course welcome to your opinion, but multiple assignment exists in many languages.  So you're saying they're all wrong to have such a feature?
> 
> No. It's good to have multiple assignments; it's annoying that Perl prevents the option of grouping initializers with the data if I so wanted:
> 
> my $a = e1, $b = e2, $c = e3;
> 
> I was just opining that
> 
> foreach (a ; e1) (a2 ; e2) {}
> 
> is clearer than:
> 
> foreach (a ; b) (e1 ; e2) {}
> 
> 
> Andrei
> 

Ah, but then would you agree that your simultaneous foreach proposal
would only serve the purpose of grouping variables next to their data?
I.e., it wouldn't help in terms of simplifying code complexity (as it
might happen in other languages, like Perl which you mentioned in
another post), since D can currently do this:

  foreach (x,y ; transpose_view(reverse_view(foo),bar)
    //then why not this too?!

And your proposal would only serve to simplify the above to this:

  foreach (x ; reverse_view(foo)) (y ; bar)
    //probably I could!

which IMO is negligible, and not worthy of adding such new syntax.


-- 
Bruno Medeiros - MSc in CS/E student
http://www.prowiki.org/wiki4d/wiki.cgi?BrunoMedeiros#D