www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.announce - Steve Yegge's rant on The Next Big Language

reply Deewiant <deewiant.doesnotlike.spam gmail.com> writes:
Mentions D, and is an interesting article overall.

http://steve-yegge.blogspot.com/2007/02/next-big-language.html

-- 
Remove ".doesnotlike.spam" from the mail address.
Feb 11 2007
next sibling parent reply Manfred Nowak <svv1999 hotmail.com> writes:
Deewiant wrote

 Mentions D, and is an interesting article overall.
Seems pretty clear, that NBL == D. -manfred
Feb 11 2007
parent reply "Jarrett Billingsley" <kb3ctd2 yahoo.com> writes:
"Manfred Nowak" <svv1999 hotmail.com> wrote in message 
news:eqoukm$17se$1 digitalmars.com...
 Deewiant wrote

 Mentions D, and is an interesting article overall.
Seems pretty clear, that NBL == D. -manfred
Except for the typing system (though it could certainly get there), the absolute lack of tools, and missing about half of the Kitchen Sink points ;) Admit it, we all look at the programming language world through D-colored glasses. Though this article seems more oriented at the next big _apps_ language. I could really see D taking over C/C++'s slot as the systems language, and maybe a little of the apps as well.
Feb 11 2007
next sibling parent reply Chad J <gamerChad _spamIsBad_gmail.com> writes:
Jarrett Billingsley wrote:
 "Manfred Nowak" <svv1999 hotmail.com> wrote in message 
 news:eqoukm$17se$1 digitalmars.com...
 
Deewiant wrote


Mentions D, and is an interesting article overall.
Seems pretty clear, that NBL == D. -manfred
Except for the typing system (though it could certainly get there), the absolute lack of tools, and missing about half of the Kitchen Sink points ;) Admit it, we all look at the programming language world through D-colored glasses. Though this article seems more oriented at the next big _apps_ language. I could really see D taking over C/C++'s slot as the systems language, and maybe a little of the apps as well.
Yeah, I'd bet that, at least in Steve's eyes, D != NBL. After all, D was mentioned under the "NBL does not replace C++" section, and he said D was a contender to replace C++. Hey, we can always shoot for The Big Language After The Next Big Language, or TBLATNBL!
Feb 11 2007
next sibling parent "Jarrett Billingsley" <kb3ctd2 yahoo.com> writes:
"Chad J" <gamerChad _spamIsBad_gmail.com> wrote in message 
news:eqovmi$1952$1 digitalmars.com...

 Yeah, I'd bet that, at least in Steve's eyes, D != NBL.  After all, D was 
 mentioned under the "NBL does not replace C++" section, and he said D was 
 a contender to replace C++.  Hey, we can always shoot for The Big Language 
 After The Next Big Language, or TBLATNBL!
I'd like "The Language that The Next Big Language is Written In" ;)
Feb 11 2007
prev sibling parent Kevin Bealer <kevinbealer gmail.com> writes:
Chad J wrote:
 Jarrett Billingsley wrote:
 "Manfred Nowak" <svv1999 hotmail.com> wrote in message 
 news:eqoukm$17se$1 digitalmars.com...

 Deewiant wrote


 Mentions D, and is an interesting article overall.
Seems pretty clear, that NBL == D. -manfred
Except for the typing system (though it could certainly get there), the absolute lack of tools, and missing about half of the Kitchen Sink points ;) Admit it, we all look at the programming language world through D-colored glasses. Though this article seems more oriented at the next big _apps_ language. I could really see D taking over C/C++'s slot as the systems language, and maybe a little of the apps as well.
Yeah, I'd bet that, at least in Steve's eyes, D != NBL. After all, D was mentioned under the "NBL does not replace C++" section, and he said D was a contender to replace C++. Hey, we can always shoot for The Big Language After The Next Big Language, or TBLATNBL!
He seems to exclude D from the NBL for categorical reasons, i.e. the replaces C++ thing. But it's pretty impressive that in this long negative article about how all languages suck, and every language is criticized for rampant inadequacies, but the little section on D reads like he is in love with D nevertheless. Kevin
Feb 11 2007
prev sibling parent reply BCS <BCS pathlink.com> writes:
Jarrett Billingsley wrote:
 
 
 Except for the typing system (though it could certainly get there), the 
 absolute lack of tools, and missing about half of the Kitchen Sink points ;) 
Half?, more like one or two hard misses and a few more close calls. I can kill one close calls:
4 Destructuring bind (e.g. x, y = returnTwoValues())
If I'm reading it right this does that, and nicely: struct SetT(V...) { V args_m; static SetT go(inout V args) { SetT ret; foreach (i, arg; args) ret.args_m[i] = arg; return ret; } void opCall(inout V args) { foreach (i, arg; args_m) args[i] = arg; } } SetT!(int,int) bar(int i, int j) { return SetT!(int,int).go(i,j); } void main() { int i=1,j=2,k=0,l=0; bar(i,j)(k,l); writef("[k,l]=[%d,%d]\n", k,l); }
Feb 12 2007
next sibling parent reply Bill Baxter <dnewsgroup billbaxter.com> writes:
BCS wrote:
 Jarrett Billingsley wrote:
 Except for the typing system (though it could certainly get there), 
 the absolute lack of tools, and missing about half of the Kitchen Sink 
 points ;) 
Half?, more like one or two hard misses and a few more close calls. I can kill one close calls: >4 Destructuring bind (e.g. x, y = returnTwoValues()) If I'm reading it right this does that, and nicely:
Uh... no. Sort of does it, yes. Nicely? no.
     bar(i,j)(k,l);
The winning solution should use the syntax i,j = bar(k,l); And should also work in situations like // swap i and j i,j = j,i; And should at least allow bar to be implemented like: SetT!(int,int) bar(int i, int j) { return SetT(i,j); } With a little tweaking of the way Tuples are handled, I think tuples could be made to satisfy this Kitchen Sink requirement. Tuple!(int,int) bar(int i, int j) { return Tuple!(i,j); } You can make a tuple from a struct with tupleof. So value tuples are in a way just anonymous structs. You can return a struct from a function. So why not a value tuple? Given that, plus a new rule that lets you assign a value tuple to a comma separated list (or alias tuple?), you'd be there. These sorts of things seem like the direction Tuples are headed, taken to their logical conclusions. If that happens I think maybe it's time for Tuple! to get a first class syntax. Something on par with [a,b,c] for lists. (a,b,c) would be great if that could be made to work. If not, maybe !(a,b,c). This would be nice to be able to write: (int,int) bar(int i, int j) { return (i,j); } x,y = bar(1,2); --bb
Feb 12 2007
next sibling parent BCS <BCS pathlink.com> writes:
Bill Baxter wrote:
 BCS wrote:
 
 Jarrett Billingsley wrote:


 If I'm reading it right this does that, and nicely:
Uh... no. Sort of does it, yes. Nicely? no.
Ok, maybe I overstated my case: It does it without making me want to puke.
 
 And should at least allow bar to be implemented like:
 
 SetT!(int,int) bar(int i, int j)
 {
    return SetT(i,j);
 }
 
I tried that by using static opCall but you can't overload both static and non static opCall. I assume that if you could than a little implicit instancing would get rid of the rest. If you use a class it might look better, sort of. But then you get an alloc.
Feb 12 2007
prev sibling parent BCS <ao pathlink.com> writes:
Reply to Bill,

 And should at least allow bar to be implemented like:
 
 SetT!(int,int) bar(int i, int j)
 {
 return SetT(i,j);
 }
struct SetT(V...) { V args_m; void opCall(inout V args) { foreach (i, arg; args_m) args[i] = arg; } } SetT!(V) Set(V...)(V args) { SetT!(V) ret; foreach (i, arg; args) ret.args_m[i] = arg; return ret; } SetT!(int,int) bar(int i, int j) { return Set(i,j); } It still has that odd left to right assignment.
Feb 12 2007
prev sibling parent reply "Jarrett Billingsley" <kb3ctd2 yahoo.com> writes:
"BCS" <BCS pathlink.com> wrote in message 
news:eqq7nq$2tut$1 digitalmars.com...

 Half?, more like one or two hard misses and a few more close calls.
Well let's see: 1. Object-literal syntax for arrays and hashes Arrays? Yes. Hashes? no. 2. Array slicing and other intelligent collection operators Yes. 3. Perl 5 compatible regular expression literals No. It did in a way at one point, but no one liked that. 4. Destructuring bind (e.g. x, y = returnTwoValues()) No. 5. Function literals and first-class, non-broken closures Function literals, yes; non-broken closures, no. How many posts have we had in the past month that had to do with people returning nested functions? :S 6. Standard OOP with classes, instances, interfaces, polymorphism, etc. Yes. 7. Visibility quantifiers (public/private/protected) Yes. 8. Iterators and generators Not in the way I think he means. There's opApply, but.. 9. List comprehensions No. 10. Namespaces and packages Package namespaces... yes. ;) 11. Cross-platform GUI No! 12. Operator overloading Yes. 13. Keyword and rest parameters No, but what does he mean by "rest"? Vararg? That's a yes, but.. 14. First-class parser and AST support If he means "code modifying other code" then no, certainly not first-class. 15. Static typing and duck typing Yes. (Unless some duck typing expert wants to correct me, I _think_ D has it) 16. Type expressions and statically checkable semantics I won't lie, I don't know what this means. But it doesn't sound like D has them since I've never heard of them. 17. Solid string and collection libraries _Libraries_? Noooo. 18. Strings and streams act like collections Yes, if by "collection" you mean "you can iterate over them." So counting the ones that are partially yes as 0.5, and the yeses as 1.0, I get 9. 9/18 = 0.5
Feb 12 2007
next sibling parent reply "Jarrett Billingsley" <kb3ctd2 yahoo.com> writes:
"Jarrett Billingsley" <kb3ctd2 yahoo.com> wrote in message 
news:eqr5o5$16us$1 digitalmars.com...
 "BCS" <BCS pathlink.com> wrote in message 
 news:eqq7nq$2tut$1 digitalmars.com...

 Half?, more like one or two hard misses and a few more close calls.
Well let's see:
And I just wanted to add that this is considering _language features_, not things that can be done with libraries (excluding those points which explicitly mention libraries). So yes, you can do Perl-like regexps, multiple return values, iterators, generators, and list comprehensions with libraries. I think it's awesome that D can pretty much provide these without much trouble, but these are not language features.
Feb 12 2007
parent reply BCS <ao pathlink.com> writes:
Reply to Jarrett,

 "Jarrett Billingsley" <kb3ctd2 yahoo.com> wrote in message
 news:eqr5o5$16us$1 digitalmars.com...
 
 "BCS" <BCS pathlink.com> wrote in message
 news:eqq7nq$2tut$1 digitalmars.com...
 
 Half?, more like one or two hard misses and a few more close calls.
 
Well let's see:
And I just wanted to add that this is considering _language features_, not things that can be done with libraries (excluding those points which explicitly mention libraries). So yes, you can do Perl-like regexps, multiple return values, iterators, generators, and list comprehensions with libraries. I think it's awesome that D can pretty much provide these without much trouble, but these are not language features.
To pick at a few: Does any language do interators for user type as language features? You have to write them your self in every language I know of. In D, all the types you can get without a lib can be iterated over without a lib. And I'll admit that the mult return is a bit of a stretch. But *I* don't care if things come from a lib or from a feature, just how well they get the job done. And I would never use a language that doesn't need libs. It would be WAY to big. But that's all just my opinion. Really my point is that for the most part D, in one form or another, has most of the things mentioned .
Feb 12 2007
next sibling parent reply "Jarrett Billingsley" <kb3ctd2 yahoo.com> writes:
"BCS" <ao pathlink.com> wrote in message 
news:ce0a334373d08c91d138f82c904 news.digitalmars.com...
 To pick at a few:
 Does any language do interators for user type as language features? You 
 have to write them your self in every language I know of.
...well if you don't write the iterator for your user type, how is the language going to know how to iterate over it? When Steve said "iterators and generators" as a 'thing to have', I think he meant that they are first-class primitives in the language. Having to write a custom iterator for a class wouldn't change that fact.
 But *I* don't care if things come from a lib or from a feature, just how 
 well they get the job done.
I don't either. But then you have languages like C++, where you are practically crippled without a library. It's nice to have a basic set of powerful functionality without having to resort to the standard library to do the most common tasks. D does that very well right now, but that doesn't mean it's perfect.
Feb 13 2007
parent reply BCS <BCS pathlink.com> writes:
Jarrett Billingsley wrote:
 "BCS" <ao pathlink.com> wrote in message 
 news:ce0a334373d08c91d138f82c904 news.digitalmars.com...
 
To pick at a few:
Does any language do interators for user type as language features? You 
have to write them your self in every language I know of.
....well if you don't write the iterator for your user type, how is the language going to know how to iterate over it? When Steve said "iterators and generators" as a 'thing to have', I think he meant that they are first-class primitives in the language. Having to write a custom iterator for a class wouldn't change that fact.
Strait up question: how does D fail in this regard? opApply and delegate based foreach cover a /lot/ of ground.
Feb 13 2007
parent reply "Jarrett Billingsley" <kb3ctd2 yahoo.com> writes:
"BCS" <BCS pathlink.com> wrote in message 
news:eqst6m$29s$2 digitalmars.com...
 ....well if you don't write the iterator for your user type, how is the 
 language going to know how to iterate over it?  When Steve said 
 "iterators and generators" as a 'thing to have', I think he meant that 
 they are first-class primitives in the language.  Having to write a 
 custom iterator for a class wouldn't change that fact.
Strait up question: how does D fail in this regard? opApply and delegate based foreach cover a /lot/ of ground.
I guess it doesn't really miss much functionality, though the way D handles iteration certainly makes it harder to do parallel iteration. I have *no* idea how Walter/Andrei plan to implement the "foreach(i;a)(j;b){}" syntax that Andrei has been talking about. On the other hand, many general case iterators are far easier to write using the D callback style than with iterator style. Generators, on the other hand, are just plain cool. I think they can be done using something like StackThreads.
Feb 13 2007
parent reply BCS <ao pathlink.com> writes:
Reply to Jarrett,

 I guess it doesn't really miss much functionality, though the way D
 handles iteration certainly makes it harder to do parallel iteration.
 I have *no* idea how Walter/Andrei plan to implement the
 "foreach(i;a)(j;b){}" syntax that Andrei has been talking about.
It might take this approch (interate over the intersect of to AA's) int delegate(int delegate (inout U, SetT!(T, T)) dg) Intersect(T, U)(T[U] first, T[U] sec) returns this delegate |{ | foreach(k, v1; first) | { | if(v2 = (k in sec)) | { | if(ret = dg (k, Set(v1, *v2)) | return ret | } | } |}
 
 Generators, on the other hand, are just plain cool.  I think they can
 be done using something like StackThreads.
 
I'm missing somthing here: what is a generator?
Feb 13 2007
parent reply Frits van Bommel <fvbommel REMwOVExCAPSs.nl> writes:
BCS wrote:
 Reply to Jarrett,
 
 Generators, on the other hand, are just plain cool.  I think they can
 be done using something like StackThreads.
I'm missing somthing here: what is a generator?
A generator is like a function, but after it "returns" it can be "called" again and it will resume where it left off. Local variables are preserved, and execution resumes after the statement that caused the return. They're basically an automated method for creating an iterator object out of an opApply-like function. In Python, you create them by using 'yield' instead of return. Python tutorial section on generators: http://docs.python.org/tut/node11.html#SECTION00111000000000000000000
Feb 13 2007
parent reply BCS <ao pathlink.com> writes:
Reply to Frits,

 BCS wrote:
 
 Reply to Jarrett,
 
 Generators, on the other hand, are just plain cool.  I think they
 can be done using something like StackThreads.
 
I'm missing somthing here: what is a generator?
A generator is like a function, but after it "returns" it can be "called" again and it will resume where it left off. Local variables are preserved, and execution resumes after the statement that caused the return. They're basically an automated method for creating an iterator object out of an opApply-like function. In Python, you create them by using 'yield' instead of return. Python tutorial section on generators: http://docs.python.org/tut/node11.html#SECTION00111000000000000000000
I should be burned at the stake for this... | struct | { | // all needed variables | int at=0; | | int go() // fn with no local variables | { | switch(at) | { | case -1: | assert(false); | | case 0: | | //stuff | | at=1; return value; case 1: | | // more stuff | | at=2; return value; case 2: | | // more stuff | | } | at = -1; | return value; | } | }
Feb 13 2007
parent reply Charles D Hixson <charleshixsn earthlink.net> writes:
BCS wrote:
 Reply to Frits,
 
 BCS wrote:

 Reply to Jarrett,

 Generators, on the other hand, are just plain cool.  I think they
 can be done using something like StackThreads.
I'm missing somthing here: what is a generator?
A generator is like a function, but after it "returns" it can be "called" again and it will resume where it left off. Local variables are preserved, and execution resumes after the statement that caused the return. They're basically an automated method for creating an iterator object out of an opApply-like function. In Python, you create them by using 'yield' instead of return. Python tutorial section on generators: http://docs.python.org/tut/node11.html#SECTION00111000000000000000000
I should be burned at the stake for this... | struct | { | // all needed variables | int at=0; | | int go() // fn with no local variables | { | switch(at) | { | case -1: | assert(false); | | case 0: | | //stuff | | at=1; return value; case 1: | | // more stuff | | at=2; return value; case 2: | | // more stuff | | } | at = -1; | return value; | } | }
Which kind of proves what I've been seeing as the point, i.e., D is a complete language, and it's POSSIBLE to do anything computable in it. That doesn't mean it's easy, or worth doing, if you have to do it within the D syntax. The things that people have been saying are all things that are POSSIBLE to do in D...but frequently the techniques for doing them are so cumbersome or error prone that the only reasonable choice is to avoid them. If one believes that a particular technique is desirable, then one wishes to have it reasonably easy to use. Thus, because MANY people have thought that templates are a good idea (esp. Walter), lots of work and improvement has been done on them. Much less work has been done on advanced run-time features, which aren't typically used in, at a guess, embedded systems. (Well, those don't even like garbage collectors, so it's some other purpose that's at the center of focus for D. It doesn't seem to involve graphics or databases. Those are "available", but only in rudimentary form, and largely as a side effect of having C routines be callable. N.B.: I'm not asserting that everyone is interested in some one particular thing, but merely that the "center of gravity" of interest is in an area with certain characteristics. Presumably as it becomes "well developed" more out-lying areas will experience more development. But just contrast D's approach with that of Python. Python has long boasted "Batteries Included!". I don't know if it's still on the home web page, but it was for many years. Or Perl's proclaiming of CPAN. I've never used it, but I'm still well aware of claims that programs don't need to check that libraries are available locally. As long as there's a net connection, they'll be downloaded automatically. (That may be overselling...but that's the way I've heard it advertised.) D, OTOH, is more like Ruby. Libraries aren't available by default, and lots of the ones that are in the repositories aren't maintained any more and have suffered from bit-rot. As a result Ruby has Rails programmers, and Python has Python programmers, and Perl has Perl programmers. (OK. That statement's a bit too strong. But that's the tendency.) D is starting from the language model of C and C++. In many ways this is good, but I'm not sure to what extent... N.B.: In the commentary about languages I left out Java, because that was driven by large corporations. Still, it's worth noting that much of Java's success was due to the large libraries it has of routines that can be counted upon to work. Phobos is more analogous to the libraries that came with the Fortran compilers around 1970. (Well, less extensive, but more tuned to the basic tasks.) P.S.: Partially this note is due to my current frustration due to the release of Tango, which won't work with Phobos, and therefore means that I can't depend on any particular library being installed with a D compiler...with the libraries being so different that the same code can't be used with both.
Feb 13 2007
parent reply Lutger <lutger.blijdestijn gmail.com> writes:
Charles D Hixson wrote:

 Which kind of proves what I've been seeing as the point, i.e.,
 D is a complete language, and it's POSSIBLE to do anything
 computable in it.  That doesn't mean it's easy, or worth
 doing, if you have to do it within the D syntax.
 
 The things that people have been saying are all things that
 are POSSIBLE to do in D...but frequently the techniques for
 doing them are so cumbersome or error prone that the only
 reasonable choice is to avoid them.
The things that been been mentioned are also (not) coincidentally the things that are well supported by either the core language or library. Numerous other techniques are well supported and not cumbersome or error-prone.
 If one believes that a particular technique is desirable, then
 one wishes to have it reasonably easy to use.  Thus, because
 MANY people have thought that templates are a good idea (esp.
 Walter), lots of work and improvement has been done on them.
 Much less work has been done on advanced run-time features,
 which aren't typically used in, at a guess, embedded systems.
Correct me if I'm wrong, but aren't these complimentory? I mean that the effort that is going into things like templates is meant to make it easier to support these 'advanced run-time features'?
 But just contrast D's approach with that of Python.  Python
 has long boasted "Batteries Included!".  I don't know if it's
 still on the home web page, but it was for many years.  Or
 Perl's proclaiming of CPAN.  I've never used it, but I'm still
 well aware of claims that programs don't need to check that
 libraries are available locally.  As long as there's a net
 connection, they'll be downloaded automatically.  (That may be
 overselling...but that's the way I've heard it advertised.)
 D, OTOH, is more like Ruby.  Libraries aren't available by
 default, and lots of the ones that are in the repositories
 aren't maintained any more and have suffered from bit-rot.  As
 a result Ruby has Rails programmers, and Python has Python
 programmers, and Perl has Perl programmers.  (OK.  That
 statement's a bit too strong.  But that's the tendency.)
Python is around much longer. It's apples and oranges in another way too, for Python does not have (nor aims to have) the performance of D. DSSS is supposed to be like CPAN, it is still young but pretty sweet (if adopted by community).
 P.S.:  Partially this note is due to my current frustration
 due to the release of Tango, which won't work with Phobos, and
 therefore means that I can't depend on any particular library
 being installed with a D compiler...with the libraries being
 so different that the same code can't be used with both.
I agree. In some other thread someone remarked upon how easy it was to write Java code because it is so very standardized, that makes it easy to understand and use existing code. In a way D improves on C++ in that a lot of stuff is not implementation specific, but on the library side at the moment the situation is different. This is not really a fair critique though since this (I would hope) is a transient state of affairs, Tango is just out.
Feb 14 2007
parent Lutger <lutger.blijdestijn gmail.com> writes:
Lutger wrote:

 The things that been been mentioned are also (not) coincidentally the
 things that are well supported by either the core language or library.
I meant to write 'are *not*' well supported of course.
Feb 14 2007
prev sibling parent reply =?ISO-8859-1?Q?Julio_C=E9sar_Carrascal_Urquijo?= writes:
BCS wrote:
 To pick at a few:
 Does any language do interators for user type as language features? You 
 have to write them your self in every language I know of. In D, all the 
 types you can get without a lib can be iterated over without a lib.
class List { IEnumerator getEnumerator() { for (int i = 0; i < 100; ++i) yield return InnerList[i]; } }
 And I'll admit that the mult return is a bit of a stretch.
Actually, tuples are one of my favorite language features on both Python and Erlang.
 But *I* don't care if things come from a lib or from a feature, just how 
 well they get the job done. And I would never use a language that 
 doesn't need libs. It would be WAY to big.
Agree
 But that's all just my opinion. Really my point is that for the most 
 part D, in one form or another, has most of the things mentioned .
Agree, but I think that Steve Yegge was actually referring to a future version of ECMAScript.
Feb 14 2007
parent reply Bill Baxter <dnewsgroup billbaxter.com> writes:
Julio César Carrascal Urquijo wrote:
 BCS wrote:
 To pick at a few:
 Does any language do interators for user type as language features? 
 You have to write them your self in every language I know of. In D, 
 all the types you can get without a lib can be iterated over without a 
 lib.
class List { IEnumerator getEnumerator() { for (int i = 0; i < 100; ++i) yield return InnerList[i]; } }
 And I'll admit that the mult return is a bit of a stretch.
Actually, tuples are one of my favorite language features on both Python and Erlang.
 But *I* don't care if things come from a lib or from a feature, just 
 how well they get the job done. And I would never use a language that 
 doesn't need libs. It would be WAY to big.
Agree
 But that's all just my opinion. Really my point is that for the most 
 part D, in one form or another, has most of the things mentioned .
Agree, but I think that Steve Yegge was actually referring to a future version of ECMAScript.
Right -- so it's DMDScript and not D he was talking about. :-) --bb
Feb 14 2007
parent Paul Findlay <r.lph50+d gmail.com> writes:
 Right -- so it's DMDScript and not D he was talking about.  :-)
I hope so too :) - Paul
Feb 15 2007
prev sibling next sibling parent reply BCS <ao pathlink.com> writes:
Reply to Jarrett,

 "BCS" <BCS pathlink.com> wrote in message
 news:eqq7nq$2tut$1 digitalmars.com...
 
 Half?, more like one or two hard misses and a few more close calls.
 
Well let's see: 1. Object-literal syntax for arrays and hashes Arrays? Yes. Hashes? no.
Hashes can be done +(1 + .5)/2
 2. Array slicing and other intelligent collection operators
 
 Yes.
+1
 
 3. Perl 5 compatible regular expression literals
 
 No.  It did in a way at one point, but no one liked that.
 
Regex is there but not as a native type. IIRC however these is a project to do compile time regex compilation. +.5
 4. Destructuring bind (e.g. x, y = returnTwoValues())
 
 No.
Not as part of the language but, again it can be done: Slightly better syntax than before: struct SetT(V...) { V args_m; void opCall(inout V args) { foreach (i, arg; args_m) args[i] = arg; } } SetT!(V) Set(V...)(V args) { SetT!(V) ret; foreach (i, arg; args) ret.args_m[i] = arg; return ret; } SetT!(int,int) bar(int i, int j){ return Set(i,j); } void main() { int i=1,j=2,k=0,l=0; bar(i,j)(k,l); writef("[k,l]=[%d,%d]\n", k,l); } +.5
 
 5. Function literals and first-class, non-broken closures
 
 Function literals, yes; non-broken closures, no.  How many posts have
 we had in the past month that had to do with people returning nested
 functions?  :S
 
that's broken usage, not a broken feature, they work if you do them right, just as pointers do. +1
 6. Standard OOP with classes, instances, interfaces, polymorphism,
 etc.
 
 Yes.
 
+1
 7. Visibility quantifiers (public/private/protected)
 
 Yes.
+1
 8. Iterators and generators
 
 Not in the way I think he means.  There's opApply, but..
 
foreach will take delegate, and with only a little work the delegate can carry context from one foreach to the next auto it = WalkList("hello world"); foreach(char c; it) if(c == ' ') break; else writef(c); writef(\n); foreach(char c; it) writef(c); other options include: Nested iteration foreach(rec; DB.WithName("bob").ageOver(65).Male.iter) Joined iteration of AA's int[char[]] foo, bar; foreach(char[] k, int v; Inter(foo, bar)) I could be wrong but I don't see what that doesn't cover. +1
 9. List comprehensions
 
 No.
Ok, I'll bite, What is it? +??
 
 10. Namespaces and packages
 
 Package namespaces... yes.  ;)
 
+1
 11. Cross-platform GUI
 
 No!
 
Hard miss. +0
 12. Operator overloading
 
 Yes.
+1
 
 13. Keyword and rest parameters
 
 No, but what does he mean by "rest"?  Vararg?  That's a yes, but..
 
I'm not sure what this is +??
 14. First-class parser and AST support
 
 If he means "code modifying other code" then no, certainly not
 first-class.
 
Hard miss. Unless you count mixin or template code +0
 15. Static typing and duck typing
 
 Yes.  (Unless some duck typing expert wants to correct me, I _think_ D
 has it)
+1
 
 16. Type expressions and statically checkable semantics
 
 I won't lie, I don't know what this means.  But it doesn't sound like
 D has them since I've never heard of them.
 
I'd count template's that construct types under this, as well as the ability to statically check operator restrictions somewhere Oskar Linde has a Unit checking template that at compile time checks for errors like adding meters to Newtons +1
 17. Solid string and collection libraries
 
 _Libraries_?  Noooo.
 
We don't need them, D's AA's and dynamic arrays cover most of it and IIRC there are about a dozen libs for playing with them when you need more, clean them up a little and you've got it. +1
 18. Strings and streams act like collections
 
 Yes, if by "collection" you mean "you can iterate over them."
 
+1
 So counting the ones that are partially yes as 0.5, and the yeses as
 1.0, I get 9.  9/18 = 0.5
 
I get 12.75 of 18 with only 2 hard misses and two that I don't known what they are. However that's just my counting, based on my assumptions: enough)
Feb 12 2007
parent reply "Jarrett Billingsley" <kb3ctd2 yahoo.com> writes:
"BCS" <ao pathlink.com> wrote in message 
news:ce0a334373a38c91d108e764264 news.digitalmars.com...
 5. Function literals and first-class, non-broken closures
that's broken usage, not a broken feature, they work if you do them right, just as pointers do.
I'd consider the current incarnation of closures "broken." Are they useful as they are now? Hell yes. But can you do everything with them that you can in languages that have true closures? No. Functions are *almost* first class types in D ;) Being able to return closures without having to manually create the context would be.. amazing.
 9. List comprehensions
Ok, I'll bite, What is it?
Basically it's a way of really easily applying functions and such over a list. They're kind of like array operations (a[] = b[] + c[]), which D doesn't have yet, but more flexible. You can do stuff like (using very python-like syntax): int[] numbers = [1, 2, 3, 4, 5, 6, 7, 8]; // This loops through numbers, seeing if the condition holds true, // and if it does, adds it to a new list, which is eventually assigned // to evens. int[] evens = [x for x in numbers if !(x & 1)]; // Square the list int[] squares = [x * x for x in numbers];
 13. Keyword and rest parameters
I'm not sure what this is
Keyword parameters are another thing found in python. They allow you to call functions with named parameters: foo(x = 5, y = 10); In python, the keyword parameters are interpreted as a hashtable, but since D is statically typed, it could probably just map the parameters right to the parameters defined in the function. I'd really like to see this.
 16. Type expressions and statically checkable semantics
I'd count template's that construct types under this, as well as the ability to statically check operator restrictions somewhere Oskar Linde has a Unit checking template that at compile time checks for errors like adding meters to Newtons
Oh, alright then. That's cool.
 17. Solid string and collection libraries

 _Libraries_?  Noooo.
We don't need them, D's AA's and dynamic arrays cover most of it and IIRC there are about a dozen libs for playing with them when you need more, clean them up a little and you've got it.
I'll agree with you mostly for collections (I haven't missed STL a bit), but std.string is kind of an embarassment. It only really has support for char[] (major shortfall in a language that supposedly handles UTF-16 and UTF-32) and doesn't provide any in-place functions (which would be great when you're writing a program that doesn't want to make any heap allocations).
Feb 13 2007
next sibling parent reply BCS <BCS pathlink.com> writes:
Jarrett Billingsley wrote:
 "BCS" <ao pathlink.com> wrote in message 
 news:ce0a334373a38c91d108e764264 news.digitalmars.com...
 
5. Function literals and first-class, non-broken closures
that's broken usage, not a broken feature, they work if you do them right, just as pointers do.
I'd consider the current incarnation of closures "broken." Are they useful as they are now? Hell yes. But can you do everything with them that you can in languages that have true closures? No. Functions are *almost* first class types in D ;) Being able to return closures without having to manually create the context would be.. amazing.
Yes that would be nice, but it is one hell of a can of worms. It has more corner cases than general cases. About the only things that would be safe and reasonably understandable would be to put the whole stack frame on the heap. If someone can figure out how to fix all the problems in a reasonably understandable manner, I'd love to see it. Until then, I think Explicit scoping (using structs) is the way to go. Again, just my opinion.
9. List comprehensions
Ok, I'll bite, What is it?
Basically it's a way of really easily applying functions and such over a list. They're kind of like array operations (a[] = b[] + c[]), which D doesn't have yet, but more flexible. You can do stuff like (using very python-like syntax): int[] numbers = [1, 2, 3, 4, 5, 6, 7, 8]; // This loops through numbers, seeing if the condition holds true, // and if it does, adds it to a new list, which is eventually assigned // to evens. int[] evens = [x for x in numbers if !(x & 1)]; // Square the list int[] squares = [x * x for x in numbers];
Cool, LISPisums. Again, it would be a lib but I think it is possible, it would look something like this: int[] squares = mapOver(numbers, (int x){return x*x;}); int[] evens = Filter(numbers, (int x){return !(x & 1);}); A smart compiler would try real hard to inline these so you'd even get most of the performance.
 
13. Keyword and rest parameters
I'm not sure what this is
Keyword parameters are another thing found in python. They allow you to call functions with named parameters: foo(x = 5, y = 10); In python, the keyword parameters are interpreted as a hashtable, but since D is statically typed, it could probably just map the parameters right to the parameters defined in the function. I'd really like to see this.
Would this count? struct foo{int x=1; int y=1;} void fn(foo f){...} fn({x:0}); fn({y:0}); not as nice, but with a little tweaking we could have this: void fn(struct {int x=1; int y=1;}){...} use an anon struct as the arguments.
17. Solid string and collection libraries

_Libraries_?  Noooo.
We don't need them, D's AA's and dynamic arrays cover most of it and IIRC there are about a dozen libs for playing with them when you need more, clean them up a little and you've got it.
I'll agree with you mostly for collections (I haven't missed STL a bit), but std.string is kind of an embarassment. It only really has support for char[] (major shortfall in a language that supposedly handles UTF-16 and UTF-32) and doesn't provide any in-place functions (which would be great when you're writing a program that doesn't want to make any heap allocations).
Ah... UTF, Oh, yeah. Forgot about that.
Feb 13 2007
parent "Jarrett Billingsley" <kb3ctd2 yahoo.com> writes:
"BCS" <BCS pathlink.com> wrote in message 
news:eqst20$29s$1 digitalmars.com...
 Yes that would be nice, but it is one hell of a can of worms. It has more 
 corner cases than general cases. About the only things that would be safe 
 and reasonably understandable would be to put the whole stack frame on the 
 heap.

 If someone can figure out how to fix all the problems in a reasonably 
 understandable manner, I'd love to see it. Until then, I think Explicit 
 scoping (using structs) is the way to go.

 Again, just my opinion.
That's why it's Walter's job ;)
 Would this count?

 struct foo{int x=1; int y=1;}

 void fn(foo f){...}

 fn({x:0});
 fn({y:0});

 not as nice, but with a little tweaking we could have this:

 void fn(struct {int x=1; int y=1;}){...}

 use an anon struct as the arguments.
Someone actually suggested this. Basically the idea was that if your function took a struct as a parameter, you could replace the struct with a list of struct member initializers and D would implicitly create the struct. struct foo { int x = 1; int y = 1; } void fn(foo f) { ... } fn(x:0, y:5); basically the same as your suggestion but without the curly braces at the call site. I'd like to see something, anything, for named parameters. I still think the compiler should be able to map directly to the function's named arguments without any extra trickery like using a struct.
Feb 13 2007
prev sibling next sibling parent renoX <renosky free.fr> writes:
Jarrett Billingsley a écrit :
 "BCS" <ao pathlink.com> wrote in message 
 13. Keyword and rest parameters
I'm not sure what this is
Keyword parameters are another thing found in python. They allow you to call functions with named parameters: foo(x = 5, y = 10); In python, the keyword parameters are interpreted as a hashtable, but since D is statically typed, it could probably just map the parameters right to the parameters defined in the function. I'd really like to see this.
+1 When you think about it, the current function call where parameter passing is done by position is quite broken as shown nicely by memset: developers make so many mistake calling it, that some compilers integrated warnings when they see that the parameters are likely wrong.. IMHO when a function has two parameters with 'compatible' type, it should be called by 'keyword' to avoid hard to find errors. Plus, this really improves readability, if a bit verbose. renoX
Feb 13 2007
prev sibling parent reply janderson <askme me.com> writes:
Jarrett Billingsley wrote:
 
 Basically it's a way of really easily applying functions and such over a 
 list.  They're kind of like array operations (a[] = b[] + c[]), which D 
 doesn't have yet, but more flexible.  You can do stuff like (using very 
 python-like syntax):
 
 int[] numbers = [1, 2, 3, 4, 5, 6, 7, 8];
 
 // This loops through numbers, seeing if the condition holds true,
 // and if it does, adds it to a new list, which is eventually assigned
 // to evens.
 int[] evens = [x for x in numbers if !(x & 1)];
 
 // Square the list
 int[] squares = [x * x for x in numbers];
I'm not sure about these. The syntax is not much better then a foreach loop.
Mar 11 2007
next sibling parent reply Johan Granberg <lijat.meREM OVE.gmail.com> writes:
janderson wrote:

 Jarrett Billingsley wrote:
 
 Basically it's a way of really easily applying functions and such over a
 list.  They're kind of like array operations (a[] = b[] + c[]), which D
 doesn't have yet, but more flexible.  You can do stuff like (using very
 python-like syntax):
 
 int[] numbers = [1, 2, 3, 4, 5, 6, 7, 8];
 
 // This loops through numbers, seeing if the condition holds true,
 // and if it does, adds it to a new list, which is eventually assigned
 // to evens.
 int[] evens = [x for x in numbers if !(x & 1)];
 
 // Square the list
 int[] squares = [x * x for x in numbers];
I'm not sure about these. The syntax is not much better then a foreach loop.
But they are expressions instead of statements which can be important in some situations, and they are probably more limited (no defined ordering) something that could be used in optimizations.
Mar 11 2007
parent janderson <askme me.com> writes:
Johan Granberg wrote:
 janderson wrote:
 
 Jarrett Billingsley wrote:
 Basically it's a way of really easily applying functions and such over a
 list.  They're kind of like array operations (a[] = b[] + c[]), which D
 doesn't have yet, but more flexible.  You can do stuff like (using very
 python-like syntax):

 int[] numbers = [1, 2, 3, 4, 5, 6, 7, 8];

 // This loops through numbers, seeing if the condition holds true,
 // and if it does, adds it to a new list, which is eventually assigned
 // to evens.
 int[] evens = [x for x in numbers if !(x & 1)];

 // Square the list
 int[] squares = [x * x for x in numbers];
I'm not sure about these. The syntax is not much better then a foreach loop.
But they are expressions instead of statements which can be important in some situations, and they are probably more limited (no defined ordering) something that could be used in optimizations.
About the optimisation part. I think it would be better to be able to specify that a loop's contents are order-independent. -Joel
Mar 11 2007
prev sibling parent reply Foo <foo bar.zoo> writes:
janderson Wrote:

 Jarrett Billingsley wrote:
 
 Basically it's a way of really easily applying functions and such over a 
 list.  They're kind of like array operations (a[] = b[] + c[]), which D 
 doesn't have yet, but more flexible.  You can do stuff like (using very 
 python-like syntax):
 
 int[] numbers = [1, 2, 3, 4, 5, 6, 7, 8];
 
 // This loops through numbers, seeing if the condition holds true,
 // and if it does, adds it to a new list, which is eventually assigned
 // to evens.
 int[] evens = [x for x in numbers if !(x & 1)];
 
 // Square the list
 int[] squares = [x * x for x in numbers];
I'm not sure about these. The syntax is not much better then a foreach loop.
We can use "Array operations": R[] map(T,R)(T[] arr, R delegate(T) dg){ R[] result = new R[arr.length]; foreach(i, item; arr) result[i] = dg(item); return result; } void main(){ int[] numbers = [1, 2, 3, 4, 5, 6, 7, 8]; int[] squares = numbers.map( delegate int(int x){return x * x;} ); } I think the syntax of delegate literal should be simplified, like this: int[] squares = numbers.map( int(int x){return x * x;} ); or ruby-like syntax: int[] squares = numbers.map( {int|int x| x * x} );
Mar 12 2007
next sibling parent reply Frits van Bommel <fvbommel REMwOVExCAPSs.nl> writes:
Foo wrote:
 I think the syntax of delegate literal should be simplified, like this:
 int[] squares = numbers.map( int(int x){return x * x;} );
 
 or ruby-like syntax:
 int[] squares = numbers.map( {int|int x| x * x} );
*ahem* You just didn't simplify _enough_ ;): --- $ cat test.d import std.stdio; R[] map(T,R)(T[] arr, R delegate(T) dg){ R[] result = new R[arr.length]; foreach(i, item; arr) result[i] = dg(item); return result; } void main(){ int[] numbers = [1, 2, 3, 4, 5, 6, 7, 8]; int[] squares = numbers.map( (int x){return x * x;} ); writefln(squares); } $ dmd -run test.d [1,4,9,16,25,36,49,64] --- As you can see, your first example works if you also leave out the return type :). (See http://www.digitalmars.com/d/expression.html#FunctionLiteral) I'm not quite sure why you're not allowed to explicitly specify the return type without also specifying "function" or "delegate" first, but it could be there's some syntactic ambiguity that would create which I can't think of right now. Or it could just be that Walter overlooked it, thought it too hard to implement, or simply not worth it for some reason... [a bit later] I just thought of a semi-ambiguity. If the return type and the types of any parameters are user-defined, and all parameters (if any) are anonymous and implicitly 'in', the first part looks just like a function call: "foo(bar)" can then be either a call to a function 'foo' with parameter 'bar', or the start of a delegate returning a value of type 'foo' taking an anonymous parameter of type 'bar'. But since IIRC D already requires an infinite-lookahead parser, the next character (either a '{' or not) should disambiguate, which is why I only called this a semi-ambiguity. Can anyone think of an actual ambiguity, or think of another reason this is not allowed? Barring fault, oversight or laziness (or perhaps just busy-ness) on Walter's part, of course :P.
Mar 12 2007
parent reply Sean Kelly <sean f4.ca> writes:
Frits van Bommel wrote:
 I just thought of a semi-ambiguity. If the return type and the types of 
 any parameters are user-defined, and all parameters (if any) are 
 anonymous and implicitly 'in', the first part looks just like a function 
 call: "foo(bar)" can then be either a call to a function 'foo' with 
 parameter 'bar', or the start of a delegate returning a value of type 
 'foo' taking an anonymous parameter of type 'bar'.
It could also look like an object instantiation via static opCall followed by a nested block of code. Excluding the separating semicolon, of course.
 But since IIRC D already requires an infinite-lookahead parser, the next 
 character (either a '{' or not) should disambiguate, which is why I only 
 called this a semi-ambiguity.
Yup.
 Can anyone think of an actual ambiguity, or think of another reason this 
 is not allowed? Barring fault, oversight or laziness (or perhaps just 
 busy-ness) on Walter's part, of course :P.
I think the presence or lack of a semicolon keeps this from being a true ambiguity.
Mar 12 2007
parent reply Frits van Bommel <fvbommel REMwOVExCAPSs.nl> writes:
Sean Kelly wrote:
 Frits van Bommel wrote:
 I just thought of a semi-ambiguity. If the return type and the types 
 of any parameters are user-defined, and all parameters (if any) are 
 anonymous and implicitly 'in', the first part looks just like a 
 function call: "foo(bar)" can then be either a call to a function 
 'foo' with parameter 'bar', or the start of a delegate returning a 
 value of type 'foo' taking an anonymous parameter of type 'bar'.
It could also look like an object instantiation via static opCall followed by a nested block of code. Excluding the separating semicolon, of course.
A static opCall is also a regular function as far as the syntax is concerned, just one that happens to have the same name as an aggregate type. AFAIK the compiler doesn't even generate different code for this (except for the actual function address concerned, of course). A non-static opCall is slightly different here, but should AFAIK generate code equivalent to a that of a delegate call, except the function is a constant instead of stored in memory. See below regarding the semicolon.
 But since IIRC D already requires an infinite-lookahead parser, the 
 next character (either a '{' or not) should disambiguate, which is why 
 I only called this a semi-ambiguity.
Yup.
 Can anyone think of an actual ambiguity, or think of another reason 
 this is not allowed? Barring fault, oversight or laziness (or perhaps 
 just busy-ness) on Walter's part, of course :P.
I think the presence or lack of a semicolon keeps this from being a true ambiguity.
No, I think it's the presence of an opening brace, not a semicolon; for instance, it's still a function call if the next token is some sort of binary operator ('+', '*', '/', '.', whatever): in the expression "foo(bar) + 5" the "foo(bar)" must be a function or delegate call of some sort. (Perhaps you failed to consider that functions are allowed to return values? :) ) So the absence of a semicolon doesn't mean it's not a function call, whereas the absence of an opening brace does mean it's not a delegate literal. So the opening brace would be the superior discriminating token, since its presence also unambiguously (AFAICT) indicates a delegate literal. But as I immediately indicated, I agree that this isn't a real ambiguity (and that it was just the closest thing to one I could come up with :) ). Which I consider to be a good thing, as I'm hoping there isn't any ambiguity and this syntax can therefore be allowed in a future D version.
Mar 12 2007
parent Sean Kelly <sean f4.ca> writes:
Frits van Bommel wrote:
 Sean Kelly wrote:
 Frits van Bommel wrote:
 I just thought of a semi-ambiguity. If the return type and the types 
 of any parameters are user-defined, and all parameters (if any) are 
 anonymous and implicitly 'in', the first part looks just like a 
 function call: "foo(bar)" can then be either a call to a function 
 'foo' with parameter 'bar', or the start of a delegate returning a 
 value of type 'foo' taking an anonymous parameter of type 'bar'.
It could also look like an object instantiation via static opCall followed by a nested block of code. Excluding the separating semicolon, of course.
A static opCall is also a regular function as far as the syntax is concerned, just one that happens to have the same name as an aggregate type. AFAIK the compiler doesn't even generate different code for this (except for the actual function address concerned, of course). A non-static opCall is slightly different here, but should AFAIK generate code equivalent to a that of a delegate call, except the function is a constant instead of stored in memory. See below regarding the semicolon.
 But since IIRC D already requires an infinite-lookahead parser, the 
 next character (either a '{' or not) should disambiguate, which is 
 why I only called this a semi-ambiguity.
Yup.
 Can anyone think of an actual ambiguity, or think of another reason 
 this is not allowed? Barring fault, oversight or laziness (or perhaps 
 just busy-ness) on Walter's part, of course :P.
I think the presence or lack of a semicolon keeps this from being a true ambiguity.
No, I think it's the presence of an opening brace, not a semicolon; for instance, it's still a function call if the next token is some sort of binary operator ('+', '*', '/', '.', whatever): in the expression "foo(bar) + 5" the "foo(bar)" must be a function or delegate call of some sort. (Perhaps you failed to consider that functions are allowed to return values? :) )
No, I was merely thinking of the syntax in general rather than specifically in a function call. For example, I believe this is legal: (int x) {printf("%d\n", x); }( 2 );
 So the absence of a semicolon doesn't mean it's not a function call, 
 whereas the absence of an opening brace does mean it's not a delegate 
 literal.
In the context of a function call, I agree.
 But as I immediately indicated, I agree that this isn't a real ambiguity 
 (and that it was just the closest thing to one I could come up with :) 
 ). Which I consider to be a good thing, as I'm hoping there isn't any 
 ambiguity and this syntax can therefore be allowed in a future D version.
Yup :-) Sean
Mar 12 2007
prev sibling parent reply Max Samukha <samukha voliacable.com> writes:
On Mon, 12 Mar 2007 09:34:39 -0400, Foo <foo bar.zoo> wrote:

I think the syntax of delegate literal should be simplified, like this:
int[] squares = numbers.map( int(int x){return x * x;} );

or ruby-like syntax:
int[] squares = numbers.map( {int|int x| x * x} );
This works: int[] squares = numbers.map((int x){return x * x;} ); The return value of the delegate literal is inferred from the return expression type.
Mar 12 2007
parent reply Max Samukha <samukha voliacable.com> writes:
On Mon, 12 Mar 2007 16:14:09 +0200, Max Samukha
<samukha voliacable.com> wrote:

The return value of the delegate literal is inferred from the return
expression type.
Not return value, return type, of course. Frits was faster, anyway.
Mar 12 2007
parent reply Vassily Gavrilyak <gavrilyak gmail.com> writes:
Argument(s) type could be inferred too, as it is currently with foreach.
So

auto res = [1,2,3].map((x){return x+x;}).filter((x, i){return i<2;});

Almost array comprehension.


auto res = [1,2,3].map(x=> x+x).filter(_, i => i<2).sort(a,b => a>b);
Such syntax is consistent with current lazy arguments.


Max Samukha Wrote:

 On Mon, 12 Mar 2007 16:14:09 +0200, Max Samukha
 <samukha voliacable.com> wrote:
 
The return value of the delegate literal is inferred from the return
expression type.
Not return value, return type, of course. Frits was faster, anyway.
Mar 12 2007
parent reply Daniel Keep <daniel.keep.lists gmail.com> writes:
Vassily Gavrilyak wrote:
 Argument(s) type could be inferred too, as it is currently with foreach.
 So
 
 auto res = [1,2,3].map((x){return x+x;}).filter((x, i){return i<2;});
I wouldn't want to be the one to write the type inference code for that :3 [1,2,3].map(f) works because it's rewritten as map([1,2,3], f), and the type of [1,2,3] and f is known. But if the type of f is inferred from the call to map, and the call to map needs to know the type of f in order to know its' own type... *groans* My brain hurts just trying to think about it >_< Not saying I wouldn't *love* to have this, just that I wouldn't be at all upset if it never happened :P
 Almost array comprehension.

 
 auto res = [1,2,3].map(x=> x+x).filter(_, i => i<2).sort(a,b => a>b);
 Such syntax is consistent with current lazy arguments.
Whoa, now *that* is nasty. Quick: is foo(a,b=>a>b) a delegate of two arguments or one? What if a is declared outside the scope; which is it then? Hell, I couldn't even work out what the "_" was for until I realised it was allowing multiple arguments :P
 
 Max Samukha Wrote:
 
 On Mon, 12 Mar 2007 16:14:09 +0200, Max Samukha
 <samukha voliacable.com> wrote:

 The return value of the delegate literal is inferred from the return
 expression type.
Not return value, return type, of course. Frits was faster, anyway.
Frits is a forum-post ninja; beware his stealthy and sudden posts! -- Daniel -- Unlike Knuth, I have neither proven or tried the above; it may not even make sense. v2sw5+8Yhw5ln4+5pr6OFPma8u6+7Lw4Tm6+7l6+7D i28a2Xs3MSr2e4/6+7t4TNSMb6HTOp5en5g6RAHCP http://hackerkey.com/
Mar 12 2007
parent reply Vassily Gavrilyak <gavrilyak gmail.com> writes:
Strange, for me inferring RETURN type is much more difficult then argument
type, 
and D already do exactly this.  
Arguments types are already declared, in declaration of map
R[] map(T[] arr, R delegate(T) fun);

From here it is clear that there is one argument, and its type is T for array
of T's.
But probably some D features will disallow such simple kind of inference.
Inferring type R from above example seems much more complicated - 
you need to look at the delegate code and find the return type.

 Whoa, now *that* is nasty.  Quick: is foo(a,b=>a>b) a delegate of two
 arguments or one?  What if a is declared outside the scope; which is it
Hmm, for me it looks simple :-) It's a shortcut for delegate (int a, int b){return a>b;} It's the same as lazy 3+2 is just a shortcut for (void){return 3+2;}, but with parameters. From expanded version it is clear that a and b are local arguments and normal D rules of name resolution is applied. (well, I do not know the exact rules, but it seems as it will be error having the same variable name upper in the scope). Another similar example of already existing type inference is foreach(i, v; arr) Here i and v are inferred from enumerated collection type, and map is actually the same arr.map((i, v)=>v+v); Hmm, but you are right with your question, it seems that parenthesis are mandatory because otherwise it will be impossible to differentiate how many arguments needed. So the correct version will look like auto sorted = sort(arr, (a,b) => a<b );
 *groans*  My brain hurts just trying to think about it >_<
Ouch, I'm sorry for this. You give me a wonderful functools.d and I hurt your brain in response. Never wanted such thing to happen. But that are actual examples of how I am currently using functools.d :-). Many thanks for this lib, it helps me a lot. Actually they implemented comprehensions too, but with somewhat strange "SQL-like" syntax. So my example with such syntax will look something like: var res = FROM [1,2,3] AS x SELECT x+x WHERE x<2 ORDER BY x; It's probably more readable but that's totally different language, no spirit of C here. To conclude - D needs parametrized lazy arguments and more aggressive type inference. It will cover most syntax sugar issues with array comprehensions and much more, because syntax will not be restricted. Example I actually use often: Given an array of people build an associative array with name as a key; Person[char[]] peopleByName = people.hashBy((person)=>person.name);
Mar 13 2007
parent reply Daniel Keep <daniel.keep.lists gmail.com> writes:
Vassily Gavrilyak wrote:
 Strange, for me inferring RETURN type is much more difficult then argument
type, 
 and D already do exactly this.  
 Arguments types are already declared, in declaration of map
 R[] map(T[] arr, R delegate(T) fun);
 
 From here it is clear that there is one argument, and its type is T for array
of T's.
 But probably some D features will disallow such simple kind of inference.
 Inferring type R from above example seems much more complicated - 
 you need to look at the delegate code and find the return type.
See, the way I *think* DMD does it is that it goes from the inner-most expression out. So at the very inner-most level, we've got the delegate. It starts off by getting the type of the arguments, since we need to know these to make sense of the body. All good. We then have "return a>b". Well, we know a and b, so the result of this is obviously a bool. We go to check the return type and... it's missing. Hmm, well, let's just fix it to bool. Alright--delegate's done. Now we come to the map call. We're given an argument that's int[], so T is obviously int. We're given a delegate of type bool delegate(int,int), so R is obviously bool. Easy. If we switch it around, it becomes messier: we need to do the type inference for the call to map BEFORE we work out what the type of the delegate is. But we can't work out all the types, since we need to know the type of the delegate to get R. So we end up with the types of map depending on the delegate, and the types on the delegate depending on map. Where do you start? The obvious answer to this is to make the whole AST lazily-evaluated, but I like Walter, and I think it's important for people to go outside once in a while :P
 Whoa, now *that* is nasty.  Quick: is foo(a,b=>a>b) a delegate of two
 arguments or one?  What if a is declared outside the scope; which is it
Hmm, for me it looks simple :-) It's a shortcut for delegate (int a, int b){return a>b;} It's the same as lazy 3+2 is just a shortcut for (void){return 3+2;}, but with parameters. From expanded version it is clear that a and b are local arguments and normal D rules of name resolution is applied. (well, I do not know the exact rules, but it seems as it will be error having the same variable name upper in the scope). Another similar example of already existing type inference is foreach(i, v; arr) Here i and v are inferred from enumerated collection type, and map is actually the same arr.map((i, v)=>v+v); Hmm, but you are right with your question, it seems that parenthesis are mandatory because otherwise it will be impossible to differentiate how many arguments needed. So the correct version will look like auto sorted = sort(arr, (a,b) => a<b );
I just wanted to point out that the syntax is wildly different from anything else in D. The advantage of the current syntax, is that it *looks* like some kind of function... it's got the parenthesised argument list and the curly-brace body. I see "=>" and immediately think of maps (er, the associative-array kind.) Of course, the above syntax is also much shorter for single expressions.
 *groans*  My brain hurts just trying to think about it >_<
Ouch, I'm sorry for this. You give me a wonderful functools.d and I hurt your brain in response. Never wanted such thing to happen. But that are actual examples of how I am currently using functools.d :-). Many thanks for this lib, it helps me a lot.
You're very welcome! I'm overjoyed to hear that someone is actually using it!

I know; I always preferred Nemerle, tho :P You wanna talk about type-inference, go check that one out!
 Actually they implemented comprehensions too, but with somewhat strange
"SQL-like"
 syntax. So my example with such syntax will look something like:
 var res = FROM [1,2,3] AS x SELECT x+x WHERE x<2 ORDER BY x;
 It's probably more readable but that's totally different language, no spirit
of C here.
I think that they started developing LINQ because people wanted list comprehensions, but instead of taking their cues from Haskell or Python... they used SQL. It's debatable as to whether that was a good idea or not; I'll just say that I prefer Haskell/Python style list comprehensions :)
 To conclude - D needs parametrized lazy arguments and more aggressive type
inference. 
 It will cover most syntax sugar issues with array comprehensions and much
more, 
 because syntax will not be restricted.
 Example I actually use often:
 Given an array of people build an associative array with name as a key;
 Person[char[]] peopleByName = people.hashBy((person)=>person.name);
With enough semantic analysis, I imagine you could get D to do anything. I agree, it *would* be nice to have, and being able to write shorter lambda functions is always nice. I wouldn't say it "needs" them, though: I'd prefer to see more features that really honestly *can't* be done at the moment added (like compile-time function evaluation or better compile-time reflection) before incremental improvements like that. Anyway, that's just my opinion, for what that's worth :P I'll go now, I think I've started rambling again. -- Daniel -- Unlike Knuth, I have neither proven or tried the above; it may not even make sense. v2sw5+8Yhw5ln4+5pr6OFPma8u6+7Lw4Tm6+7l6+7D i28a2Xs3MSr2e4/6+7t4TNSMb6HTOp5en5g6RAHCP http://hackerkey.com/
Mar 13 2007
parent Vassily Gavrilyak <gavrilyak gmail.com> writes:
Daniel Keep Wrote:
 See, the way I *think* DMD does it is that it goes from the inner-most
 expression out.  So at the very inner-most level, we've got the
 delegate.  It starts off by getting the type of the arguments, since we
 need to know these to make sense of the body.  All good.  We then have
 "return a>b".  Well, we know a and b, so the result of this is obviously
 a bool.  We go to check the return type and... it's missing.  Hmm, well,
 let's just fix it to bool.  Alright--delegate's done.
 
 Now we come to the map call.  We're given an argument that's int[], so T
 is obviously int.  We're given a delegate of type bool
 delegate(int,int), so R is obviously bool.  Easy.
 
 If we switch it around, it becomes messier: we need to do the type
 inference for the call to map BEFORE we work out what the type of the
 delegate is.  But we can't work out all the types, since we need to know
 the type of the delegate to get R.  So we end up with the types of map
 depending on the delegate, and the types on the delegate depending on
 map.  Where do you start?
 
 The obvious answer to this is to make the whole AST lazily-evaluated,
 but I like Walter, and I think it's important for people to go outside
 once in a while :P
Nice explanation, thanks. That's the current state of features of D made me think that we almost there. We already have type inference almost everywhere but not in function arguments. It seems like one little step and we will have the full inference engine. But it only "looks" so and the reality is probably classic 80/20 situation when the remaining 20% of features will take 80% of time. And it is probably better to just stick with 80%.
 I just wanted to point out that the syntax is wildly different from
 anything else in D.  The advantage of the current syntax, is that it
 *looks* like some kind of function... it's got the parenthesised
 argument list and the curly-brace body.
 
 I see "=>" and immediately think of maps (er, the associative-array kind.)
PHP, Perl or Ruby? I think about maps when I see {hello:"world"} ;-) Well, => is just one of possibilities for lambdas. Haskell's a -> a+a almost the same. C, C++ and Java don't have this at all, so we can't just still it from here. Now Ruby and Smalltalk uses a| a+a. They are not from C family though. Javascript will adopt function(a) a+a, at least Brendan promised it here. http://weblogs.mozillazine.org/roadmap/archives/2006/05/javascript_2_ecmascript_ ditio.html#comments This approach seems suitable for D too - no new keywords and also allows delegate(a) a+a and int(a,b) a+b It's just looks a little long for me, but probably I'm the only one thinking so :-) Taking some other syntax would be good too, but that's will be D's only syntax, foreign for for everybody. Probably it's better to mimic something people familiar with.
 
 Of course, the above syntax is also much shorter for single expressions.
 I know; I always preferred Nemerle, tho :P  You wanna talk about
 type-inference, go check that one out!
Of course I already checked it, and liked very much. I would use it, but have no place for it in my projects. All my server and client side development is JS. And I choose D because for one task only because of native compilation and Linux support. I need controlling hardware and my brains are so broken with JS that I practically can't imagine to do something in C. If Nemerle could help me here then JS will too and I would choose JS :-)
 
 Actually they implemented comprehensions too, but with somewhat strange
"SQL-like"
 syntax. So my example with such syntax will look something like:
 var res = FROM [1,2,3] AS x SELECT x+x WHERE x<2 ORDER BY x;
 It's probably more readable but that's totally different language, no spirit
of C here.
I think that they started developing LINQ because people wanted list comprehensions, but instead of taking their cues from Haskell or Python... they used SQL. It's debatable as to whether that was a good idea or not; I'll just say that I prefer Haskell/Python style list comprehensions :)
Yes, I would prefer those too, but that's not so simple feature to get right and implement . JS already has it (Python way), and I still don't use it, it just seems foreign for me in C family. Also it is not very clear what should be used as collection types. Python has lists and generators. JS has array and generators. D has arrays, hashes and some kind of custom iterators (opApply). Should hashes be there? Should iterators be there? What should be the result type for comprehension custom iterators? E.g if comprehension will be allowed for arrays only - that will be too restrictive for me. It's very complex issue.
 To conclude - D needs parametrized lazy arguments and more aggressive type
inference. 
 It will cover most syntax sugar issues with array comprehensions and much
more, 
 because syntax will not be restricted.
 Example I actually use often:
 Given an array of people build an associative array with name as a key;
 Person[char[]] peopleByName = people.hashBy((person)=>person.name);
With enough semantic analysis, I imagine you could get D to do anything. I agree, it *would* be nice to have, and being able to write shorter lambda functions is always nice. I wouldn't say it "needs" them, though:
Well, that's probably my bad English :-) I didn't mean that D needs it badly. Remember, we are discussing the array comprehensions. And I said that probably they are NOT needed. We can have the same effect with little adoptions of current syntax and not big changes.
I'd prefer to see more features that really honestly *can't* be
 done at the moment added (like compile-time function evaluation or
 better compile-time reflection) before incremental improvements like that.
Yes, me too, but I keep silent about 'hard' ones too. (well, closures is my top wanted feature).
 Anyway, that's just my opinion, for what that's worth :P
 I'll go now, I think I've started rambling again.
Well, you see, I agreed with you about type inference, it's complex and probably not needed. Functions expressions (parametrized lazy's) seems like just syntax sugar that's already partially resolved with lazy expressions (only not parametrized). Done properly this will give one more feature in D's checklist that many other languages already have. And also it will give some more consistense to current unparametrized 'lazy' expressions. Probably even the keyword lazy can be deprecated at all, as unneccessary, delegates are good enough. And removing some code is always nice :-)
 
 	-- Daniel
 
 -- 
 Unlike Knuth, I have neither proven or tried the above; it may not even
 make sense.
 
 v2sw5+8Yhw5ln4+5pr6OFPma8u6+7Lw4Tm6+7l6+7D
 i28a2Xs3MSr2e4/6+7t4TNSMb6HTOp5en5g6RAHCP  http://hackerkey.com/
It was nice to talk with you, thanks Vassily
Mar 14 2007
prev sibling parent reply Thomas Kuehne <thomas-dloop kuehne.cn> writes:
-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1

Jarrett Billingsley schrieb am 2007-02-13:
 "BCS" <BCS pathlink.com> wrote in message 
 news:eqq7nq$2tut$1 digitalmars.com...

 Half?, more like one or two hard misses and a few more close calls.
Well let's see:
[snip]
 15. Static typing and duck typing

 Yes.  (Unless some duck typing expert wants to correct me, I _think_ D has 
 it)
Shouldn't the code below be legal if D supported duck typing? Thomas -----BEGIN PGP SIGNATURE----- iD8DBQFF0eWfLK5blCcjpWoRAhUwAJ9DflOJIIo4wN0FiqBqWl39Y6/cogCfS7Al QXsO2nfgt3JzdzkD0nurXPc= =oAuz -----END PGP SIGNATURE-----
Feb 13 2007
parent Bruno Medeiros <brunodomedeiros+spam com.gmail> writes:
Thomas Kuehne wrote:
 -----BEGIN PGP SIGNED MESSAGE-----
 Hash: SHA1
 
 Jarrett Billingsley schrieb am 2007-02-13:
 "BCS" <BCS pathlink.com> wrote in message 
 news:eqq7nq$2tut$1 digitalmars.com...

 Half?, more like one or two hard misses and a few more close calls.
Well let's see:
[snip]
 15. Static typing and duck typing

 Yes.  (Unless some duck typing expert wants to correct me, I _think_ D has 
 it)
Shouldn't the code below be legal if D supported duck typing? Thomas -----BEGIN PGP SIGNATURE----- iD8DBQFF0eWfLK5blCcjpWoRAhUwAJ9DflOJIIo4wN0FiqBqWl39Y6/cogCfS7Al QXsO2nfgt3JzdzkD0nurXPc= =oAuz -----END PGP SIGNATURE-----
Yup, D doesn't actually support duck typing. Not on the object system method call at least, since in metaprogramming (compile-time) it has something that can be considered duck typing: Using the is-expression to test for features: template func(T) (T foo) { static if(is(foo.grow())) { foo.grow(); } else ... } -- Bruno Medeiros - MSc in CS/E student http://www.prowiki.org/wiki4d/wiki.cgi?BrunoMedeiros#D
Feb 15 2007
prev sibling next sibling parent reply Bill Baxter <dnewsgroup billbaxter.com> writes:
Deewiant wrote:
 Mentions D, and is an interesting article overall.
 
 http://steve-yegge.blogspot.com/2007/02/next-big-language.html
 
Here's another interesting article, relavent to current discussions, that I found while trying to find out who this steve yegge guy is: http://steve.yegge.googlepages.com/scheming-is-believing But I didn't succeed in finding out who Mr. Yegge is other than a guy with a blog who knows how to program. Is he famous for something besides his blog? --bb
Feb 12 2007
next sibling parent Walter Bright <newshound digitalmars.com> writes:
Bill Baxter wrote:
 Here's another interesting article, relavent to current discussions, 
 that I found while trying to find out who this steve yegge guy is:
    http://steve.yegge.googlepages.com/scheming-is-believing
That's a good read.
Feb 12 2007
prev sibling parent Jeff Nowakowski <jeff dilacero.org> writes:
Bill Baxter wrote:
    http://steve.yegge.googlepages.com/scheming-is-believing
Interesting (but long!) article. Thanks for posting it.
 But I didn't succeed in finding out who Mr. Yegge is other than a guy 
 with a blog who knows how to program.  Is he famous for something 
 besides his blog?
I didn't know who he was either, but some googling found this page: http://steve-yegge.blogspot.com/2006/07/get-famous-by-not-programming.html He describes himself as being famous for being a "loudmouth" blogger. He's worked at Amazon and now works at Google, so I guess that gives him a leg-up in the loudmouth blog arena :) -Jeff
Feb 12 2007
prev sibling next sibling parent Chad J <gamerChad _spamIsBad_gmail.com> writes:
Deewiant wrote:
 Mentions D, and is an interesting article overall.
 
 http://steve-yegge.blogspot.com/2007/02/next-big-language.html
 
Attached is what happens when I go to Kinematics class after reading this post :)
Feb 13 2007
prev sibling parent mario pernici <mario.pernici mi.infn.it> writes:
Frits van Bommel Wrote:

 Foo wrote:
 I think the syntax of delegate literal should be simplified, like this:
 int[] squares = numbers.map( int(int x){return x * x;} );
 
 or ruby-like syntax:
 int[] squares = numbers.map( {int|int x| x * x} );
*ahem* You just didn't simplify _enough_ ;): --- $ cat test.d import std.stdio; R[] map(T,R)(T[] arr, R delegate(T) dg){ R[] result = new R[arr.length]; foreach(i, item; arr) result[i] = dg(item); return result; } void main(){ int[] numbers = [1, 2, 3, 4, 5, 6, 7, 8]; int[] squares = numbers.map( (int x){return x * x;} ); writefln(squares); } $ dmd -run test.d [1,4,9,16,25,36,49,64] --- As you can see, your first example works if you also leave out the return type :). (See http://www.digitalmars.com/d/expression.html#FunctionLiteral) I'm not quite sure why you're not allowed to explicitly specify the return type without also specifying "function" or "delegate" first, but it could be there's some syntactic ambiguity that would create which I can't think of right now. Or it could just be that Walter overlooked it, thought it too hard to implement, or simply not worth it for some reason... [a bit later] I just thought of a semi-ambiguity. If the return type and the types of any parameters are user-defined, and all parameters (if any) are anonymous and implicitly 'in', the first part looks just like a function call: "foo(bar)" can then be either a call to a function 'foo' with parameter 'bar', or the start of a delegate returning a value of type 'foo' taking an anonymous parameter of type 'bar'. But since IIRC D already requires an infinite-lookahead parser, the next character (either a '{' or not) should disambiguate, which is why I only called this a semi-ambiguity. Can anyone think of an actual ambiguity, or think of another reason this is not allowed? Barring fault, oversight or laziness (or perhaps just busy-ness) on Walter's part, of course :P.
With Python's list comprehensions one can do
 [x*x for x in numbers if not(x&1)]
[4, 16, 36, 64] A similar thing can be done in D overloading map() in this thread with R[] map(T,R,S)(T[] arr, R delegate(T) dg, S delegate(T) df){ R[] result; foreach(i, item; arr) { if(df(item)) result ~= dg(item); } return result; } void main(){ int[] numbers = [1, 2, 3, 4, 5, 6, 7, 8]; writefln(numbers.map( (int x){return x * x;} )); writefln(numbers.map((int x){return x * x;}, (int x) { return !(x & 1);} )); } Output: [1,4,9,16,25,36,49,64] [4,16,36,64]
Mar 12 2007