February 13, 2007 Re: Super-dee-duper D features | ||||
---|---|---|---|---|
| ||||
Posted in reply to Frits van Bommel | Frits van Bommel wrote:
> Andrei Alexandrescu (See Website For Email) wrote:
>> Sean Kelly wrote:
>>> What about:
>>>
>>> foreach (i ; coll1) (j ; coll2)
>>> {
>>> if( true )
>>> continue i;
>>> }
>>>
>>> ie. allow 'continue' to accept labels to specify which collection is iterated. A 'continue' without labels would iterate both.
>>
>> I think that's a great idea, except that "continue to label" has the same syntax: http://digitalmars.com/d/statement.html#ContinueStatement
>
> Does that really matter? The compiler knows whether 'i' is a label or a loop variable (presumably it can't be both at the same time?) so it knows what to do. Note that the current "continue to label" wouldn't help here since there's only one statement for a "double" iteration. So the most natural way to specify which loop to continue would be to specify the variable.
>
>
> 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
|
February 13, 2007 Re: Super-dee-duper D features | ||||
---|---|---|---|---|
| ||||
Posted in reply to Kevin Bealer | Kevin Bealer wrote: > X Bunny wrote: >> Kevin Bealer wrote: >>> >>> 2. The syntax doesn't provide visual hints that let you read a program. > What I mean, is this (from the Computer Language Shootout): > > (defun ack (x y) > (declare (fixnum x y)) > (the fixnum > (if (zerop x) > (1+ y) > (if (zerop y) > (ack (1- x) 1) > (ack (1- x) (ack x (1- y))))))) > > as compared to this: > > int Ack(int x, int y) > { > if (x == 0) { > return y + 1; > } else if (y == 0) { > return Ack(x-1, 1); > } else { > return Ack(x-1, Ack(x, y-1)); > } > } > > These two things do the same thing in the same way, but the structure and syntax make the C example much more readable. If I want to know input and output types, I can find them. When I see the top of the if/elseif/else structure, I can find each part. It's layed out like a table, rather than like a ball of yarn. If the C was indented like this would it be as unreadable as the Lisp? int ack(int x, int y) { if(x == 0) { return y + 1; } else if(y == 0) { return ack(x-1, 1); } else { return ack(x-1, ack(x, y-1)); } } (I cant even match up all the brackets with that one!) My editor indents the Lisp like this: (defun ack (x y) (declare (fixnum x y)) (the fixnum (if (zerop x) (1+ y) (if (zerop y) (ack (1- x) 1) (ack (1- x) (ack x (1- y))))))) The structure is no less obvious to me then the C. I can see the input and output types are clearly fixnums. The branches of the ifs are obvious. > > More importantly, I can understand *parts* of this code without understanding the whole thing. Mmmm I dont what to say about that, for me with the Lisp I can do the same. Bunny |
February 13, 2007 Re: Super-dee-duper D features | ||||
---|---|---|---|---|
| ||||
Posted in reply to Dave | Dave wrote:
> Andrei Alexandrescu (See Website For Email) wrote:
>
>> Sean Kelly wrote:
>>
>>> Andrei Alexandrescu (See Website For Email) wrote:
>>>
>>>> Frits van Bommel wrote:
>>>>
>>>>> Andrei Alexandrescu (See Website For Email) wrote:
>>>>>
>>>>>> Bill Baxter wrote:
>>>>>>
>>>>>>> Yeh, I don't get it either. How would that help me implement merge() from merge sort for instance?
>>>>>>
>>>>>>
>>>>>> Merge bumps the iteration in both collections conditionally. The form above bumps the iteration in the two collections unconditionally, until one is finished; then it continues with the other until that is finished.
>>>>>
>>>>>
>>>>> In other words, it doesn't :(.
>>>>
>>>>
>>>> A need for loops iterating over multiple collections depending on arbitrary conditions will always be there. The point of extending foreach is to address the often-encountered case when you want to iterate over multiple collections simultaneously (e.g.: copy a collection to another), just like foreach itself is addressing the particular but frequent case of iterating one collection in a linear manner.
>>>
>>>
>>> What about:
>>>
>>> foreach (i ; coll1) (j ; coll2)
>>> {
>>> if( true )
>>> continue i;
>>> }
>>>
>>> ie. allow 'continue' to accept labels to specify which collection is iterated. A 'continue' without labels would iterate both.
>>
>>
>> I think that's a great idea, except that "continue to label" has the same syntax: http://digitalmars.com/d/statement.html#ContinueStatement
>>
>> Andrei
>
>
> How about using 'next' to keep it simple, so the compiler doesn't have to create / check for 'i' and 'j' as lables with the same function scope:
>
> i: while(...)
> {
> foreach (i ; coll1) (j ; coll2)
> {
> if( true )
> continue i;
> if( i < j )
> next i;
> }
> }
> ?
No offence to anyone, but the above and the other so far are *way* too complex for such an operation. They are not simple to follow at all, and could easily be the source of tricky bugs.
Perhaps it would be worthwhile waiting until we get some useful form or Iterator before adding this type of complex syntax?
(InterleavingIterator encapsulates the trickiness, such that it is trivial to use, and works every time)
- Kris
|
February 13, 2007 Re: Super-dee-duper D features | ||||
---|---|---|---|---|
| ||||
Posted in reply to Bill Baxter | 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
|
February 13, 2007 Re: Super-dee-duper D features | ||||
---|---|---|---|---|
| ||||
Posted in reply to kris | 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) ...
|
February 14, 2007 Re: Super-dee-duper D features | ||||
---|---|---|---|---|
| ||||
Posted in reply to kris | 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.
--bb
|
February 14, 2007 Re: Super-dee-duper D features | ||||
---|---|---|---|---|
| ||||
Posted in reply to Don Clugston | Don Clugston wrote:
> Walter Bright wrote:
>> 4) The more experience I have, the more it seems that the language that got a lot right is ... Lisp. But Lisp did one thing terribly, terribly wrong - the syntax. The Lisp experts who can get past that seem to be amazingly productive with Lisp. The rest of us will remain envious of what Lisp can do, but will never use it.
>>
>> 5) Lisp gets things right, according to what I've read from heavy Lisp users, by being a language that can be modified on the fly to suit the task at hand, in other words, by having a customizable language one can achieve dramatic productivity gains.
>
> I suspect: C was a great language because it doesn't try to keep you away from the machine. Lisp is great because it doesn't try to hide you from the compiler.
>
> To quote Stepanov (the link that Bill Baxter just posted):
>
> Alexander Stepanov Notes on Programming 10/3/2006
>
> Since I am strongly convinced that the purpose of the programming language is to present an abstraction of an underlying hardware C++ is my only choice. Sadly enough, most language designers seem to be interested in preventing me from getting to the raw bits and provide a “better” machine than the one inside my computer. Even C++ is in danger of being “managed” into something completely different. (p7)
>
> Sadly enough, C and C++ not only lack facilities for defining type functions but do not provide most useful type functions for extracting different type attributes that are trivially known to the compiler. It is impossible to find out how many members a type has; it is impossible to find the types of the members of a structure type; it is impossible to find out how many arguments a function takes or their types; it is impossible to know if a function is defined for a type; the list goes on and on. The language does its best to hide the things that the compiler discovers while processing a program. (pp. 43-44)
Sounds like someone needs to send Alexander Stepanov an invitation to join this discussions going on here. It sounds D's working precisely on providing him with everything he ever wanted.
--bb
|
February 14, 2007 Re: Super-dee-duper D features | ||||
---|---|---|---|---|
| ||||
Posted in reply to Don Clugston |
Don Clugston wrote:
> Sean Kelly wrote:
>> Walter Bright wrote:
>>> 8) I've never been able to create usable C++ templates. Notice that the DMD front end (in C++) doesn't use a single template. I know how they work (in intimate detail) but I still can't use them.
>>
>> I have no problem with C++ templates, but the syntax is such that I don't consider them appropriate for a lot of the uses to which they're being put. Also, in many ways, C++ templates feel like a hack. The need to sprinkle such code with "template" and "typename" qualifiers just so the compiler knows what it's parsing sends up a huge red flag that something is wrong.
>>
>>> 9) But I see what C++ templates can do. So to me, the problem is to design templates in such a way that they are as simple to write as ordinary functions. *Then*, what templates can do can be accessible and maintainable. It's like cars - they used to be very difficult to drive, but now anyone can hop in, turn the key, and go.
>>
>> Yup. It may be that the D community is more technically adept than the C++ community on average simply because of the type of people new languages tend to attract, but I've seen a lot of interesting template code around here.
>
> I'm certain that it's just easier in D. I'm a bit amused by the ninja reference to myself, since I've never done anything very sophisticated with C++ templates. Andrei on the other hand...
>
> My feeling is, that 'static if' instead of specialisation removes 60% of the mystery from template metaprogramming. Tuples remove another chunk.
> I think that if basic uses of recursion could be replaced with iteration and compile-time variables (even if they were mutable only inside foreach), it would become readable to average joe.
Yeah, a static foreach and a static while would pretty remove a lot of the remaining mystery.
|
February 14, 2007 Re: Super-dee-duper D features | ||||
---|---|---|---|---|
| ||||
Posted in reply to Bill Baxter | 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.
>
> --bb
There is no 'standard' one at this time that I know of (judging by the discussion on it a while back). However, Tango does have this beastie in the collections package. The point is, coming up with a lightweight core Iterator approach would likely provide a simpler and more dependable solution.
in the above example, x, y, and z are all iterators themselves. If D had a core notion of Iterator, that's what those would be. For instance, D iterators might map to a delegate (which is what the body of a foreach actually is).
|
February 14, 2007 Re: Super-dee-duper D features | ||||
---|---|---|---|---|
| ||||
Posted in reply to renoX | renoX wrote:
> Andrei Alexandrescu (See Website For Email) a écrit :
>> 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.
>
> At first, I really didn't like the 'continue foreach', then afterwards I got used to it, I wonder if this is really such a requested feature though, what's wrong with the good old 'for' or 'while' for the complex case?
Absolutely nothing's wrong. The same argument, however, could be formulated to render foreach redundant. We have for, don't we.
The thing is foreach is terse and elegant and has a functional flavor that gives it safety and power that for doesn't have. It's only natural to ask oneself why all of these advantages must go away in a blink just because you want to iterate two things simultaneously.
Andrei
|
Copyright © 1999-2021 by the D Language Foundation