February 13, 2007 Re: Super-dee-duper D features | ||||
---|---|---|---|---|
| ||||
Posted in reply to Frits van Bommel | On Tue, 13 Feb 2007 17:39:46 +0100, 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 :(. I imaging that the full syntax will also include this form ... foreach (int x, i ; coll1) (int y, j ; coll2) { ... use i and j ... if (somecondition) x = ... // To set the index back or forward to some // arbitary point in the array 'coll1'. } -- Derek Parnell Melbourne, Australia "Justice for David Hicks!" skype: derek.j.parnell |
February 13, 2007 Re: Super-dee-duper D features | ||||
---|---|---|---|---|
| ||||
Posted in reply to Derek Parnell | Derek Parnell wrote:
> On Tue, 13 Feb 2007 17:39:46 +0100, 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 :(.
>
> I imaging that the full syntax will also include this form ...
>
> foreach (int x, i ; coll1) (int y, j ; coll2) {
> ... use i and j ...
> if (somecondition)
> x = ... // To set the index back or forward to some
> // arbitary point in the array 'coll1'.
> }
This currently works for built-in arrays but not for user-defined types. Also, I think the fact that it works as all is the result of an implementation detail, not spec-defined behavior.
Sean
|
February 13, 2007 Re: Super-dee-duper D features | ||||
---|---|---|---|---|
| ||||
Posted in reply to Sean Kelly | Sean Kelly wrote: > Derek Parnell wrote: > >> On Tue, 13 Feb 2007 17:39:46 +0100, 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 :(. >> >> >> I imaging that the full syntax will also include this form ... >> >> foreach (int x, i ; coll1) (int y, j ; coll2) { >> ... use i and j ... >> if (somecondition) >> x = ... // To set the index back or forward to some >> // arbitary point in the array 'coll1'. >> } > > > This currently works for built-in arrays but not for user-defined types. Also, I think the fact that it works as all is the result of an implementation detail, not spec-defined behavior. > > > Sean There's no reason a user-defined type couldn't implement this. -- Kirk McDonald http://kirkmcdonald.blogspot.com Pyd: Connecting D and Python http://pyd.dsource.org |
February 13, 2007 Re: Super-dee-duper D features | ||||
---|---|---|---|---|
| ||||
Posted in reply to Lutger | Lutger a écrit : > Pragma wrote: >> One nit: I agree with Walter here. People do *not* "naturally think >> recursively". [] > I'm not sure this is true. Many simple tasks are described as 'do X to Y > until Z,' which can be expressed easily as a recursive procedure. And even more easily as a loop. > I doubt non-programmers would think of a task as iterating over a collection of > objects with mutable state either. :) Uh?? Take a bunch of potatoes, peel them. Here you are: people are very accustomed to iterate over a bunch of things, changing their state. > Sometimes I get the feeling that recursion is made out to be more difficult > than it is, for programming I mean. As an average Joe I do like to learn > more, but when you look up material on the use of recursion, the vast bulk > of it pretty much assumes you at least have a pretty good programming > knowledge and often require mathematics too. </rant> Agreed here. Recursion is not very complicated, just not 'natural'. > Recursion just has a nerdy aura around it. It probably doesn't help that > most programmers are learned to think iteratively too. And it doesn't help recursion that when you transform a recursive function to a tail recursive function so that it's not too slow, the result is ugly! Note that recursion is still a useful tool: when you learn about the way to optimize 'Conway's game of life' (couldn't find the url sorry), it really show the power of tree representation/recursion, but it also show how tricky this is. renoX |
February 13, 2007 Re: Super-dee-duper D features | ||||
---|---|---|---|---|
| ||||
Posted in reply to Andrei Alexandrescu (See Website For Email) | 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;
}
}
?
|
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; > } > } > ? Hahaha! So we're stealing things from BASIC now, are we? -- Kirk McDonald http://kirkmcdonald.blogspot.com Pyd: Connecting D and Python http://pyd.dsource.org |
February 13, 2007 Re: Super-dee-duper D features | ||||
---|---|---|---|---|
| ||||
Posted in reply to X Bunny | X Bunny wrote: > Kevin Bealer wrote: >> >> 2. The syntax doesn't provide visual hints that let you read a program. >> >> Web pages use different colors, road signs use different shapes, other languages use different punctuation, etc. I can accept that they all turn into trees on some level, but it makes it unreadable to represent that in the syntax. It's like writing all strings in hex notation. Yes, yes, I know they turn into numbers. Show me the strings anyway; and use quotes when you do it. > > I kinda follow you in the first part of this, that different punctuation makes it obvious that something important is happening at that point, ie: > > (defun foo (x y) > (+ x y)) > > is not syntactically different from: > > (deffoo frob (x y) > (+ x y)) > > and so you might miss the point that the first expression is probably > defining a function. Syntax highlighting in the editor is a simple > solution to that though. Really its no different than in another > langauge, when you see: > > Mixin!(Frob) Nuts; > > Has any of the syntax made this more obvious about what it actually > does? You know its a Mixin but so what, its not the punctuation which > matters its the actually 'stuff' the symbols. 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. More importantly, I can understand *parts* of this code without understanding the whole thing. > Lisp can be extended with extra punctuation though without having to rewrite Lisp if you think it helps. This is valid syntax which looks nothing like Lisp if you use the infix package: > > #I(if x<y<=z then f(x)=x^^2+y^^2 else f(x)=x^^2-y^^2) The fact that you can rewrite the language in this way is powerful, but I think it would be better to start at a really readable syntax. The fact is that most people will use the 'base' syntax regardless of how it looks. Otherwise, you have the problem of coordinating with the author of every piece of code that you use and somehow getting them to adopt the better syntax. They won't, so you end up working in a kind of shanty-town syntax. There is strong pressure to find one 'style' of programming and use that -- for LISP the default syntax is already established. > Regarding the second part, its worth considering at what point do you consider syntactic sugar useful and why is it part of the language? certainly inputting a string as a list of hex values would be impractical but running with that if you did have a Lisp which only internally supported strings as a list of numbers it wouldnt matter since you could make a " macro character which generated the list for you. Its even argueably more useful than a system which only understands strings because it is hardcoded to generate a list of bytes when it sees text enclosed in quotes. When you need to interact with large libraries of functionality to do things, having to know ten different syntaxes that accomplish exactly the same thing all in the same code base is going to be really annoying. >> Accountants use paper with green bars on every other line, so that your eye can *follow* it. The green bars don't do anything else, but they still help a lot with readability -- I've actually thought that other books, i.e. novels might benefit from being printed this way. Good syntax needs to consider *ergonomic* concerns, not teach an important lesson about parse trees. > > I think theres even an Emacs mode which as you nest statements colours the matching parantheses a different colour. As for green bars, just my opinion but if you have a function with so many statements that it needs green bars to delimit them then its probably too big. With Lisp or D I can break the code up and probably would. (and use comments too!) I can syntax highlight D or C++ and benefit from both kind of visual hints. >> Most importantly: If a chair hurts everyone that sits in it, but "only for the first year" its not a good chair. > > Its there a reason to sit on the chair that makes the initial discomfort seem worthwhile? Is there a more comfortable alternative chair which does everything the chair does? Is it painful because you have bad posture from sitting too long on a beanbag? :-) This seems to be a very common view in the LISP community, 'programming in other languages has made you soft'. I don't believe in the power of 'hazing' to make better programmers. My point in this paragraph (I admit it wasn't clearly made), is this: If you ask 100 people about LISP syntax, at least 90 of them will say they don't like it and find it hard to use. The benefits you mention are real, but I don't buy that they come from the syntax itself. >> 3. I'm not sure I buy that this is a myth per se. > > If you mean its true and therefore not a myth then you are wrong. > Almost all Common Lisp systems are compilers, most generate native code, some dont include an interpreter at all and compile interactively if you are programming interactively. Another misconception is that Lisp doesnt support typed variables and therefore is unable to generate fast but specific code like C or something else, again simply not true. I didn't mean the part about being interpreted. LISP code *tends* to be slower than C++, sometimes a little, sometimes a lot. For many types of code this is not too important, etc, but for some, it is crucial. http://shootout.alioth.debian.org/gp4/benchmark.php?test=all&lang=gpp&lang2=sbcl >> The rest I'll grant as probably misconceptions, especially 6. >> >> I think the real clincher is that when people describe these kinds of issues the LISP community's response seems to be something like "get used to it and you won't notice it". Other languages may catch up with some of LISP's features, but what I consider to be the problems with LISP can't be fixed because they aren't seen as problems. > > I reckon there probably is a future possibility for a language which encompasses Lisps features but which is not Lisp. To be honest I dont really see it, since Lisp can already be extended to support additional syntax, those people who need to can implement it anyways and it would still be Lisp. Its worth noting that s-expressions (the Lisp syntax everyone but Lisp programmers has a problem with) wasnt the end-all of Lisp syntax there were also m-expressions which were supposed to be more human readable and an original goal of the development, programmers genuinely prefered sexp. Interesting, I didn't know about m-expressions. > I think a nifty thing would be a D parser written in Lisp, the D parser would emit Lisp forms which would then be compiled like anyother Lisp code, additionally it could then interact with the rest of Lisp and if people felt the desire to write more off the wall stuff they could, D would remain what it is, extensions could be as D like as they wished. Probably the parser could be simpler than the complete D spec since probably the template stuff would be replaced by macros. Who knows? > > Bunny You can already go the other direction -- there is a LISP environment written in D on dsource. http://www.dsource.org/projects/dlisp Kevin |
February 13, 2007 Re: Super-dee-duper D features | ||||
---|---|---|---|---|
| ||||
Posted in reply to Andrei Alexandrescu (See Website For Email) | 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? renoX > Andrei |
February 13, 2007 Re: Super-dee-duper D features | ||||
---|---|---|---|---|
| ||||
Posted in reply to renoX | renoX wrote: > Lutger a écrit : >> Pragma wrote: >>> One nit: I agree with Walter here. People do *not* "naturally think recursively". > [] >> I'm not sure this is true. Many simple tasks are described as 'do X to Y until Z,' which can be expressed easily as a recursive procedure. > > And even more easily as a loop. > >> I doubt non-programmers would think of a task as iterating over a collection of objects with mutable state either. :) > > Uh?? Take a bunch of potatoes, peel them. > Here you are: people are very accustomed to iterate over a bunch of > things, changing their state. Grab a potato, peel. Repeat procedure until done and cook the results... This is an iterative process anyhow, but still I think recursion is a natural way to think about tasks. It's just repetition + stop-condition basically. >> Recursion just has a nerdy aura around it. It probably doesn't help that most programmers are learned to think iteratively too. > > And it doesn't help recursion that when you transform a recursive function to a tail recursive function so that it's not too slow, the result is ugly! How is that so? Could you give an example? I'm not very familiar with recursive programming actually... |
February 13, 2007 Re: Super-dee-duper D features | ||||
---|---|---|---|---|
| ||||
Posted in reply to Andrei Alexandrescu (See Website For Email) | Andrei Alexandrescu (See Website For Email) wrote:
> Bill Baxter wrote:
>> janderson 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 ...
>>>> }
>>>>
>>>> Andrei
>>>
>>> Maybe its a bit to late here however this syntax seems very special case. Can you explain why its necessary and how we would use it. How would we do this currently (without meta programming)?
>>>
>>
>> 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.
Yes, I get that. My initial impression, though, was that iterating in lock step is just one particular case, and it seems kind of special case to warrant a new syntax. It still doesn't get rid of the need for general iterators to implement more complicated things like merge sort.
But maybe it does cover the majority of cases. I guess it's basically like 'for x,y in izip(list1,list2)' in Python. But in python that's a library function, not a bit of language syntax.
--bb
|
Copyright © 1999-2021 by the D Language Foundation