www.digitalmars.com         C & C++   DMDScript  

digitalmars.D - Three Unlikely Successful Features of D

reply Andrei Alexandrescu <SeeWebsiteForEmail erdani.org> writes:
I plan to give a talk at Lang.NEXT 
(http://channel9.msdn.com/Events/Lang-NEXT/Lang-NEXT-2012) with the 
subject above. There are a few features of D that turned out to be 
successful, in spite of them being seemingly unimportant or diverging 
from related consecrated approaches.

What are your faves? I have a few in mind, but wouldn't want to 
influence answers.


Thanks,

Andrei
Mar 20 2012
next sibling parent =?ISO-8859-1?Q?Alex_R=F8nne_Petersen?= <xtzgzorex gmail.com> writes:
On 20-03-2012 20:02, Andrei Alexandrescu wrote:
 I plan to give a talk at Lang.NEXT
 (http://channel9.msdn.com/Events/Lang-NEXT/Lang-NEXT-2012) with the
 subject above. There are a few features of D that turned out to be
 successful, in spite of them being seemingly unimportant or diverging
 from related consecrated approaches.

 What are your faves? I have a few in mind, but wouldn't want to
 influence answers.


 Thanks,

 Andrei
In no particular order: Lazy values, guaranteed initialization, scope guards, perhaps array slices, alias this / single inheritance, unittest blocks. -- - Alex
Mar 20 2012
prev sibling next sibling parent reply Dmitry Olshansky <dmitry.olsh gmail.com> writes:
On 20.03.2012 23:02, Andrei Alexandrescu wrote:
 I plan to give a talk at Lang.NEXT
 (http://channel9.msdn.com/Events/Lang-NEXT/Lang-NEXT-2012) with the
 subject above. There are a few features of D that turned out to be
 successful, in spite of them being seemingly unimportant or diverging
 from related consecrated approaches.

 What are your faves? I have a few in mind, but wouldn't want to
 influence answers.
To throw in a few: Scope guards, opDispatch, alias and _string_ template parameters. -- Dmitry Olshansky
Mar 20 2012
next sibling parent "Jesse Phillips" <Jessekphillips+D gmail.com> writes:
On Tuesday, 20 March 2012 at 19:50:25 UTC, Dmitry Olshansky wrote:

 To throw in a few:
 Scope guards, opDispatch, alias and _string_ template 
 parameters.
I like this list. And add, the template shorthand to!(int)() -> to!int() and q{} strings (though I need to remember them more often.
Mar 20 2012
prev sibling parent bcs <bcs example.com> writes:
On 03/20/2012 12:50 PM, Dmitry Olshansky wrote:
 On 20.03.2012 23:02, Andrei Alexandrescu wrote:
 I plan to give a talk at Lang.NEXT
 (http://channel9.msdn.com/Events/Lang-NEXT/Lang-NEXT-2012) with the
 subject above. There are a few features of D that turned out to be
 successful, in spite of them being seemingly unimportant or diverging
 from related consecrated approaches.

 What are your faves? I have a few in mind, but wouldn't want to
 influence answers.
To throw in a few: Scope guards, opDispatch, alias and _string_ template parameters.
that and d2 operator overloading.
Mar 20 2012
prev sibling next sibling parent maarten van damme <maartenvd1994 gmail.com> writes:
I really like the $ opperator on slices. It's something small and looks
rather unneeded. When I was dealing with java I never even wished it was
there but when I came to d and did some array manipulation I was really
glad we had that $ sign. I regularly use it and I don't seem to be the only
one feeling that way.

Maarten
Mar 20 2012
prev sibling next sibling parent "H. S. Teoh" <hsteoh quickfur.ath.cx> writes:
On Tue, Mar 20, 2012 at 02:02:15PM -0500, Andrei Alexandrescu wrote:
 I plan to give a talk at Lang.NEXT
 (http://channel9.msdn.com/Events/Lang-NEXT/Lang-NEXT-2012) with the
 subject above. There are a few features of D that turned out to be
 successful, in spite of them being seemingly unimportant or
 diverging from related consecrated approaches.
 
 What are your faves? I have a few in mind, but wouldn't want to
 influence answers.
[...] By far: CTFE. Unittest blocks, extended concept of purity, template syntax (as opposed to C++'s ugly mess), all types have a default value (.init - makes it so painless to write generic code!), scope guards. T -- I am a consultant. My job is to make your job redundant. -- Mr Tom
Mar 20 2012
prev sibling next sibling parent reply Don <nospam nospam.com> writes:
On 20.03.2012 20:02, Andrei Alexandrescu wrote:
 I plan to give a talk at Lang.NEXT
 (http://channel9.msdn.com/Events/Lang-NEXT/Lang-NEXT-2012) with the
 subject above. There are a few features of D that turned out to be
 successful, in spite of them being seemingly unimportant or diverging
 from related consecrated approaches.

 What are your faves? I have a few in mind, but wouldn't want to
 influence answers.


 Thanks,

 Andrei
There's one huge one. Strings as built-in types, including concatenation and slicing. This meant that they could be constant-folded. Together with 'static if', this was the basis of metaprogramming in D. Pretty much all the rest was a natural consequence of that foundation. It was *completely* unexpected. When, as a D newbie, I posted some of my initial exploration of the language, Walter wrote "I had no idea this was even possible." Probably not what you have in mind, though -- it *was* expected to be a success, just not to anything like this extent. * pragma(msg) is something that's been used 100X as often as anticipated. * Builtin properties of types, eg int.max. Doesn't sound like much of an improvement over a header file of constants, but it's had a huge impact. It really encourages you to write correct code, (I especially notice it for floating point, but I bet if you grep for "int.max" in D code, you'll get far more hits than for "MAXINT" in C code).
Mar 20 2012
parent reply Don <nospam nospam.com> writes:
On 20.03.2012 21:33, Don wrote:
 On 20.03.2012 20:02, Andrei Alexandrescu wrote:
 I plan to give a talk at Lang.NEXT
 (http://channel9.msdn.com/Events/Lang-NEXT/Lang-NEXT-2012) with the
 subject above. There are a few features of D that turned out to be
 successful, in spite of them being seemingly unimportant or diverging
 from related consecrated approaches.

 What are your faves? I have a few in mind, but wouldn't want to
 influence answers.


 Thanks,

 Andrei
There's one huge one. Strings as built-in types, including concatenation and slicing. This meant that they could be constant-folded. Together with 'static if', this was the basis of metaprogramming in D. Pretty much all the rest was a natural consequence of that foundation. It was *completely* unexpected. When, as a D newbie, I posted some of my initial exploration of the language, Walter wrote "I had no idea this was even possible." Probably not what you have in mind, though -- it *was* expected to be a success, just not to anything like this extent. * pragma(msg) is something that's been used 100X as often as anticipated.
Note that because it was so successful, it was incorporated into static assert.
 * Builtin properties of types, eg int.max. Doesn't sound like much of an
 improvement over a header file of constants, but it's had a huge impact.
 It really encourages you to write correct code, (I especially notice it
 for floating point, but I bet if you grep for "int.max" in D code,
 you'll get far more hits than for "MAXINT" in C code).
And is(typeof()), even though the syntax is really horrible. Brilliant concept.
Mar 20 2012
parent Brad Roberts <braddr slice-2.puremagic.com> writes:
On Tue, 20 Mar 2012, Don wrote:

 On 20.03.2012 21:33, Don wrote:
 * pragma(msg) is something that's been used 100X as often as anticipated.
Note that because it was so successful, it was incorporated into static assert.
I wrote the original msg part of assert and static assert. It wasn't because of pragma(msg), it was because I wanted a message with my asserts. :) Later, Brad
Mar 20 2012
prev sibling next sibling parent "dsimcha" <dsimcha yahoo.com> writes:
1.  Scope guards.  The need to execute some code at the end of a
scope is pervasive and has led to about a zillion workarounds

with statements in Python.  D is the only language I know of that
lets the programmer specify such a simple and common intention
directly.

2.  CTFE.  There's a certain elegance to having most of the
language available at compile time and it seems like there's no
shortage of creative uses for this.

3.  Static if.  This is the most important feature for converting
template metaprogramming from an esoteric form of sorcery to a
practical, readable tool for the masses.  Most of the compile time
introspection D provides would be almost unusable without it.
Mar 20 2012
prev sibling next sibling parent "H. S. Teoh" <hsteoh quickfur.ath.cx> writes:
On Tue, Mar 20, 2012 at 01:31:08PM -0700, H. S. Teoh wrote:
 On Tue, Mar 20, 2012 at 02:02:15PM -0500, Andrei Alexandrescu wrote:
 I plan to give a talk at Lang.NEXT
 (http://channel9.msdn.com/Events/Lang-NEXT/Lang-NEXT-2012) with the
 subject above. There are a few features of D that turned out to be
 successful, in spite of them being seemingly unimportant or
 diverging from related consecrated approaches.
 
 What are your faves? I have a few in mind, but wouldn't want to
 influence answers.
[...] By far: CTFE. Unittest blocks, extended concept of purity, template syntax (as opposed to C++'s ugly mess), all types have a default value (.init - makes it so painless to write generic code!), scope guards.
[...] Oh, and I forgot static if. It's a major feature in making compile-time stuff work like a charm. T -- Life is too short to run proprietary software. -- Bdale Garbee
Mar 20 2012
prev sibling next sibling parent reply Walter Bright <newshound2 digitalmars.com> writes:
On 3/20/2012 12:02 PM, Andrei Alexandrescu wrote:
 What are your faves? I have a few in mind, but wouldn't want to influence
answers.
Although array slices have been in D nearly since the beginning, I had little idea they would become so darn useful and foundational. They originated from an idea by Jan Knepper. The unexpected utility of them explains why they haven't appeared in other languages (yet).
Mar 20 2012
next sibling parent reply Andrei Alexandrescu <SeeWebsiteForEmail erdani.org> writes:
On 3/20/12 4:43 PM, Walter Bright wrote:
 On 3/20/2012 12:02 PM, Andrei Alexandrescu wrote:
 What are your faves? I have a few in mind, but wouldn't want to
 influence answers.
Although array slices have been in D nearly since the beginning, I had little idea they would become so darn useful and foundational. They originated from an idea by Jan Knepper. The unexpected utility of them explains why they haven't appeared in other languages (yet).
Go has slices. (Unlike D slices, they include capacity.) Andrei
Mar 20 2012
parent reply Walter Bright <newshound2 digitalmars.com> writes:
On 3/20/2012 2:51 PM, Andrei Alexandrescu wrote:
 On 3/20/12 4:43 PM, Walter Bright wrote:
 On 3/20/2012 12:02 PM, Andrei Alexandrescu wrote:
 What are your faves? I have a few in mind, but wouldn't want to
 influence answers.
Although array slices have been in D nearly since the beginning, I had little idea they would become so darn useful and foundational. They originated from an idea by Jan Knepper. The unexpected utility of them explains why they haven't appeared in other languages (yet).
Go has slices. (Unlike D slices, they include capacity.)
Can you, in Go: 1. slice a static string? 2. slice any arbitrary data?
Mar 20 2012
parent bcs <bcs example.com> writes:
On 03/20/2012 04:10 PM, Walter Bright wrote:
 On 3/20/2012 2:51 PM, Andrei Alexandrescu wrote:
 On 3/20/12 4:43 PM, Walter Bright wrote:
 On 3/20/2012 12:02 PM, Andrei Alexandrescu wrote:
 What are your faves? I have a few in mind, but wouldn't want to
 influence answers.
Although array slices have been in D nearly since the beginning, I had little idea they would become so darn useful and foundational. They originated from an idea by Jan Knepper. The unexpected utility of them explains why they haven't appeared in other languages (yet).
Go has slices. (Unlike D slices, they include capacity.)
Can you, in Go: 1. slice a static string? 2. slice any arbitrary data?
3. have arbitrary overlapping slices? OTOH slices in D do have a capacity in some regards in that the GC can allow in place extend.
Mar 20 2012
prev sibling next sibling parent Jan Knepper <jan smartsoft.us> writes:
On 03/20/2012 17:43, Walter Bright wrote:
 On 3/20/2012 12:02 PM, Andrei Alexandrescu wrote:
 What are your faves? I have a few in mind, but wouldn't want to
 influence answers.
Although array slices have been in D nearly since the beginning, I had little idea they would become so darn useful and foundational. They originated from an idea by Jan Knepper. The unexpected utility of them explains why they haven't appeared in other languages (yet).
Oh... I remember those early D-Days...
Mar 21 2012
prev sibling parent "Kagamin" <spam here.lot> writes:
On Tuesday, 20 March 2012 at 21:43:25 UTC, Walter Bright wrote:
 On 3/20/2012 12:02 PM, Andrei Alexandrescu wrote:
 What are your faves? I have a few in mind, but wouldn't want 
 to influence answers.
Although array slices have been in D nearly since the beginning, I had little idea they would become so darn useful and foundational. They originated from an idea by Jan Knepper. The unexpected utility of them explains why they haven't appeared in other languages (yet).
As to me, slices are the most important feature of D, and they were the major improvement from the start, aimed to fix the buffer overflow vulnerabilities - the plague of low level languages - at the lowest cost. What can do more than that? I thought they were born to be epic: safety, minimalism a efficiency combined.
Mar 21 2012
prev sibling next sibling parent "F i L" <witte2008 gmail.com> writes:
Andrei Alexandrescu wrote:
 What are your faves?
opDispatch was expectantly successful for me. I haven't seen it often used in examples or others peoples code, but it allows for some really awesome stuff. For instance, who says D doesn't have multiple inheritance? struct A { void a() { writeln("a"); } } struct B { void b() { writeln("b"); } } struct C { private A _a; private B _b; void opDispatch(string s)() { static if (__traits(hasMember, A, s)) mixin("_a."~s~"();"); else if (__traits(hasMember, B, s)) mixin("_b."~s~"();"); else static assert("Method not found."); } } void main() { auto c = C(); c.a(); c.b(); } and similarly, "alias x this" is useful for pseudo hierarchy. The only down-side to doing this is that Mono-D doesn't currently parse the syntax.
Mar 20 2012
prev sibling next sibling parent reply deadalnix <deadalnix gmail.com> writes:
Le 20/03/2012 20:02, Andrei Alexandrescu a écrit :
 I plan to give a talk at Lang.NEXT
 (http://channel9.msdn.com/Events/Lang-NEXT/Lang-NEXT-2012) with the
 subject above. There are a few features of D that turned out to be
 successful, in spite of them being seemingly unimportant or diverging
 from related consecrated approaches.

 What are your faves? I have a few in mind, but wouldn't want to
 influence answers.


 Thanks,

 Andrei
To me it is pragma(msg, blabla) and slices.
Mar 20 2012
parent Piotr Szturmaj <bncrbme jadamspam.pl> writes:
deadalnix wrote:
 Le 20/03/2012 20:02, Andrei Alexandrescu a écrit :
 I plan to give a talk at Lang.NEXT
 (http://channel9.msdn.com/Events/Lang-NEXT/Lang-NEXT-2012) with the
 subject above. There are a few features of D that turned out to be
 successful, in spite of them being seemingly unimportant or diverging
 from related consecrated approaches.

 What are your faves? I have a few in mind, but wouldn't want to
 influence answers.


 Thanks,

 Andrei
To me it is pragma(msg, blabla) and slices.
Yes, pragma(msg, ...) is very handy when debugging templates and generic code.
Mar 20 2012
prev sibling next sibling parent Andrej Mitrovic <andrej.mitrovich gmail.com> writes:
On 3/20/12, Andrei Alexandrescu <SeeWebsiteForEmail erdani.org> wrote:
 What are your faves? I have a few in mind, but wouldn't want to
 influence answers.
Here's one: C compatibility. Maybe it wasn't "unlikely" to be successful but most new languages don't seem to care about C compatibility all that much. It's been a boon for D though.
Mar 20 2012
prev sibling next sibling parent David <d dav1d.de> writes:
I really love CTFE, even though it's sometimes pretty slow, maybe 
because I am axaggerating it …

One more thing are these slices, they really impressed me when working 
with pointers, float* v; v[x..y] = foo; ! awesome, no more memcpy

And of yourse opDispatch, I haven't used it a lot yet, just in gl3n for 
vector swizzling, I've seen glms swizzling ... I thought I can never do 
this in D, I made it in nearly no time and 10 lines of code!
Mar 20 2012
prev sibling next sibling parent Andrej Mitrovic <andrej.mitrovich gmail.com> writes:
On 3/20/12, Andrej Mitrovic <andrej.mitrovich gmail.com> wrote:
 Here's one: C compatibility.
Now a real one: auto type inference. Could you possibly imagine what the type name should be on the left-hand side? ? x = retro(stride(chain([1, 2], [3, 4]), 2)); Who knows. auto is great for these higher-level types.
Mar 20 2012
prev sibling next sibling parent reply "Nick Sabalausky" <a a.a> writes:
- Type inference
- alias
- foreach
- Everything about arrays/slices
- Built-in associative arrays that support nearly any type as a key
- Reference semantics for classes
- All the niceities of ctors compared with C++'s ctors
- Backtick strings
- Scope guards (And even finally: I head somewhere C++ doesn't even have 
finally: Is that true?!?)
- GC
- Name any of D's metaprogramming features

Many of those can seem like simple things, but I'd *hate* to have to get by 
without them. Heck, most of them I now take for granted.

Alias in particular is a much bigger deal than it seems since it's seemingly 
trivial but can be *incredibly* helpful with templates *and* with importing.

Actually, looking at this list, I'm now starting to get a little worried 
about an upcoming C++ project... No doubt I'll be trying to reinvent a lot 
of D in it. Probably in ugly hackish ways.
Mar 20 2012
next sibling parent reply Walter Bright <newshound2 digitalmars.com> writes:
On 3/20/2012 3:58 PM, Nick Sabalausky wrote:
 Alias in particular is a much bigger deal than it seems since it's seemingly
 trivial but can be *incredibly* helpful with templates *and* with importing.
I'd have to agree with this. I find it amazing that other languages entirely miss the boat on this. C++ has a very crippled version of it in "template template parameters".
Mar 20 2012
parent "Nick Sabalausky" <a a.a> writes:
"Walter Bright" <newshound2 digitalmars.com> wrote in message 
news:jkb2v6$kq4$2 digitalmars.com...
 On 3/20/2012 3:58 PM, Nick Sabalausky wrote:
 Alias in particular is a much bigger deal than it seems since it's 
 seemingly
 trivial but can be *incredibly* helpful with templates *and* with 
 importing.
I'd have to agree with this. I find it amazing that other languages entirely miss the boat on this. C++ has a very crippled version of it in "template template parameters".
I particulary love how D's alias is used to disambiguate symbol conflicts. Brilliant approach. I know I wouldn't have thought of it.
Mar 20 2012
prev sibling next sibling parent reply "H. S. Teoh" <hsteoh quickfur.ath.cx> writes:
On Tue, Mar 20, 2012 at 06:58:31PM -0400, Nick Sabalausky wrote:
 - Type inference
Yeah I forgot about this one. Being able to write: auto veryLongNamedObject = new VeryLongNamedClass(veryLongArguments); is a big boon over C++ or Java's stuttering verbosity: VeryLongNamedClass veryLongNamedObject = new VeryLongNamedClass(veryLongArguments); Plus, it's immensely useful when dealing with Range templates... can you imagine the horrifically long typenames you'd have to type you have to explicitly specify the type of a long chain of functional expressions involving 15+ std.algorithm and std.range templates?
 - alias
This, together with static ifs and templates, make for awesome tricks involving templates that would've been an utter bear to pull off in C++. template innerKeyType(T) { static if (is(T U : U[K], K)) alias innerKeyType!K innerKeyType; else alias T innerKeyType; } innerKeyType!(int[string[char[byte]]]) innerKey; [...]
 - Built-in associative arrays that support nearly any type as a key
This is actually quite buggy right now... but that's merely an implementation issue. :-) My new AA implementation, for example, already correctly supports AA's with AA keys, which can be arbitrarily nested. So you could have something like int[string[char[byte]]], and it does lookups correctly based on the contents of the AA's you pass in as key.
 - All the niceities of ctors compared with C++'s ctors
C++ ctors are a royal pain in the neck. I remember in the early days of C++ when you can still call the base class ctor in the body of the derived class ctor... nowadays you have to contort ctor code into a horrible ugly mess just to get your ctor to do things right. Plus, the C++ standard requires fields to be initialized in declaration order, which is needlessly restrictive and basically makes ctors even more of a pain. I ended up using just stub ctors for a lot of my code, and doing the actual initialization after the object is constructed. Which is very bad OO style, I agree, but the pain of working with C++ ctors just pushes me in the wrong direction, y'know?
 - Scope guards (And even finally: I head somewhere C++ doesn't even have 
 finally: Is that true?!?)
Yes, it's true. I don't know about C++11, but certainly the previous standard has no finally clause, leading to horribly unmaintainable and ugly code like: Resource r = acquireResource(); try { doSomethingDangerous(); } catch(...) { r.release(); } r.release(); (Yes, yes, I know, RAII and all that... which leads to inventing ridiculous classes which make no sense in terms of OO, just to wrap resource handles.)
 - GC
For all the warts the current GC has, the fact that D has a GC at all makes things like array slicing possible, and *fast*, which leads to all the other niceties of slicing.
 - Name any of D's metaprogramming features
[...]
 Alias in particular is a much bigger deal than it seems since it's
 seemingly trivial but can be *incredibly* helpful with templates *and*
 with importing.
Definitely. Using alias and static if in a recursive template is one of the hallmarks of the awesomeness of D templates.
 Actually, looking at this list, I'm now starting to get a little worried 
 about an upcoming C++ project... No doubt I'll be trying to reinvent a lot 
 of D in it. Probably in ugly hackish ways.
[...] #include "dmd.h" ;-) T -- Don't modify spaghetti code unless you can eat the consequences.
Mar 20 2012
next sibling parent reply "Nick Sabalausky" <a a.a> writes:
"H. S. Teoh" <hsteoh quickfur.ath.cx> wrote in message 
news:mailman.933.1332286692.4860.digitalmars-d puremagic.com...
 On Tue, Mar 20, 2012 at 06:58:31PM -0400, Nick Sabalausky wrote:
 - Type inference
Yeah I forgot about this one. Being able to write: auto veryLongNamedObject = new VeryLongNamedClass(veryLongArguments); is a big boon over C++ or Java's stuttering verbosity: VeryLongNamedClass veryLongNamedObject = new VeryLongNamedClass(veryLongArguments); Plus, it's immensely useful when dealing with Range templates... can you imagine the horrifically long typenames you'd have to type you have to explicitly specify the type of a long chain of functional expressions involving 15+ std.algorithm and std.range templates?
 - alias
This, together with static ifs and templates, make for awesome tricks involving templates that would've been an utter bear to pull off in C++. template innerKeyType(T) { static if (is(T U : U[K], K)) alias innerKeyType!K innerKeyType; else alias T innerKeyType; } innerKeyType!(int[string[char[byte]]]) innerKey;
Yea, C++'s STL *needs* type inference and alias. At least the new spec has "auto". Don't know about other stuff though.
 [...]
 - Built-in associative arrays that support nearly any type as a key
This is actually quite buggy right now... but that's merely an implementation issue. :-)
Heck, I just love that I can use a string, or an int, or make my own struct work as a key, etc. Actually, over just the last 24 hours I've been making a lot of use of AAs with int keys. (AA's make it *so* much easier to avoid poor time complexity in a lot of things.) Many langauges (like Haxe, for example) will have hashtables, and may even have them templated (or otherwise generic) on *value*, but the keys will be string-only. Which is still very useful, but it also misses out on many other use-cases.
 My new AA implementation, for example,
 already correctly supports AA's with AA keys, which can be arbitrarily
 nested. So you could have something like int[string[char[byte]]], and it
 does lookups correctly based on the contents of the AA's you pass in as
 key.
Crazy stuff :) Actually I've been meaning to ask what the main benefits of your new AA implementation are. I know there's the benefit of just simply having it be implemented in the library. And you mention using AA's as AA keys here. Are there any other, umm, "key" points?
 - All the niceities of ctors compared with C++'s ctors
C++ ctors are a royal pain in the neck. I remember in the early days of C++ when you can still call the base class ctor in the body of the derived class ctor... nowadays you have to contort ctor code into a horrible ugly mess just to get your ctor to do things right. Plus, the C++ standard requires fields to be initialized in declaration order, which is needlessly restrictive and basically makes ctors even more of a pain. I ended up using just stub ctors for a lot of my code, and doing the actual initialization after the object is constructed. Which is very bad OO style, I agree, but the pain of working with C++ ctors just pushes me in the wrong direction, y'know?
Yea, that's what I've been planning on doing with the C++ stuff I have coming up. Don't even want to bother with C++'s ctor limitations. Just make an init() member and be done with it. Actually, that seems to be turning into more and more of a common C++ idiom though, from what (little) I've seen.
 - Scope guards (And even finally: I head somewhere C++ doesn't even have
 finally: Is that true?!?)
Yes, it's true. I don't know about C++11, but certainly the previous standard has no finally clause, leading to horribly unmaintainable and ugly code like: Resource r = acquireResource(); try { doSomethingDangerous(); } catch(...) { r.release(); } r.release();
Haxe also lacks finally! Which I always found rediculous. So yea, I'm intimately familiar with that idiom. I've used it myself far more than I would like. And even *that* still doesn't work if you don't catch *every* exception (and then rethrow the ones you don't care about? Ick!). I've seen C++ programmers swear off exceptions because of this, and I can't blame them at all. Exception systems *need* a finally.
 (Yes, yes, I know, RAII and all that... which leads to inventing
 ridiculous classes which make no sense in terms of OO, just to wrap
 resource handles.)
Yea, if I wanted to write Java-style code, I'd just use Java (and at least not have to deal with header files).
 - GC
For all the warts the current GC has, the fact that D has a GC at all makes things like array slicing possible, and *fast*, which leads to all the other niceties of slicing.
I used to do indie game dev in C/C++ and I feel downright spoiled now with tossing in a "new" whenever appropriate and not have to worry about cleanup (and even that wouldn't be *too* bad...in certain cases...if there were at least scope guards).
 - Name any of D's metaprogramming features
[...]
 Alias in particular is a much bigger deal than it seems since it's
 seemingly trivial but can be *incredibly* helpful with templates *and*
 with importing.
Definitely. Using alias and static if in a recursive template is one of the hallmarks of the awesomeness of D templates.
I'd say one of the hallmarks of D's metaprogramming is the enormous *decrease* in the need for recursive templates in the first place ;) With C++'s templates, it would appear that you have to use recursion and helper templates for damn near anything.
 Actually, looking at this list, I'm now starting to get a little worried
 about an upcoming C++ project... No doubt I'll be trying to reinvent a 
 lot
 of D in it. Probably in ugly hackish ways.
[...] #include "dmd.h" ;-)
Heh, yea. :)
 -- 
 Don't modify spaghetti code unless you can eat the consequences.
Hah! :)
Mar 20 2012
next sibling parent "Nick Sabalausky" <a a.a> writes:
"Nick Sabalausky" <a a.a> wrote in message 
news:jkbcoh$15k3$1 digitalmars.com...
 And even *that* still doesn't work if you don't catch *every* exception 
 (and then rethrow the ones you don't care about? Ick!).
And AIUI, even *that* doesn't work in C++ because, IIRC, the class hierarchy doesn't have *any* common root. So what, are you going to have a catch block for *every* class type in your program? Heck, even *that* might be feasable in D thanks to the compile-time reflection and quality metaprogramming, but with C++, you're SOL.
Mar 20 2012
prev sibling next sibling parent reply "H. S. Teoh" <hsteoh quickfur.ath.cx> writes:
On Tue, Mar 20, 2012 at 09:59:27PM -0400, Nick Sabalausky wrote:
 "H. S. Teoh" <hsteoh quickfur.ath.cx> wrote in message 
 news:mailman.933.1332286692.4860.digitalmars-d puremagic.com...
 On Tue, Mar 20, 2012 at 06:58:31PM -0400, Nick Sabalausky wrote:
[...]
 - Built-in associative arrays that support nearly any type as a key
This is actually quite buggy right now... but that's merely an implementation issue. :-)
Heck, I just love that I can use a string, or an int, or make my own struct work as a key, etc. Actually, over just the last 24 hours I've been making a lot of use of AAs with int keys. (AA's make it *so* much easier to avoid poor time complexity in a lot of things.)
Yeah, AA's with int keys are like arrays enhanced with O(1) insertion/removal and sparse storage (if you have very large indices, e.g.). :-) You can even have (pseudo) linear access if you iterate keys from 0 to $.
 Many langauges (like Haxe, for example) will have hashtables, and may
 even have them templated (or otherwise generic) on *value*, but the
 keys will be string-only. Which is still very useful, but it also
 misses out on many other use-cases.
Yep.
 My new AA implementation, for example, already correctly supports
 AA's with AA keys, which can be arbitrarily nested. So you could
 have something like int[string[char[byte]]], and it does lookups
 correctly based on the contents of the AA's you pass in as key.
Crazy stuff :) Actually I've been meaning to ask what the main benefits of your new AA implementation are. I know there's the benefit of just simply having it be implemented in the library. And you mention using AA's as AA keys here. Are there any other, umm, "key" points?
Haha, I love that pun. I would say the main benefit is having it implemented in the library, because that allows the implementation have direct access to key/value types. I didn't implement any clever new hashing algorithm at all, I just mainly followed the implementation in aaA.d. But having direct access to key/value types is a *huge* win. For example, it lets you accept keys/values that are not strictly the AA's key/value type, but can be implicitly converted to them. It lets you return keys and values without needing the ugly typeinfo and void* casts that are necessary in aaA.d. This in turn lets you mark many AA methods as pure, and almost all as safe or trusted. It lets you cleanly interoperate with types that define opAssign (currently aaA.d does a blind binary copy of data from key/value pointers, which leads to potential bugs when the data has subobjects.) It also makes it *much* easier to fix many existing AA bugs in the bugtracker. So far, I have working unittests for the following issues: 3824, 3825, 4337, 4463, 5685, 6210, 7512, 7512, 7602, 7632, 7665, 7665, 7704. I haven't looked through all AA-related issues yet; this list may very well grow. :-) To fix these in the current aaA.d implementation can be rather tricky, and quite possibly requires compiler changes. Better yet, I thought of a way of making AA's instantiable at compile-time via CTFE and mixins: this will let you write AA literals that can be evaluated at compile-time and have them turn into object code directly without needing runtime initialization. Another major benefit is that once the AA implementation is decoupled from the compiler (the compiler will only provide syntactic sugar like V[K] and literal syntax), we can finally fix AA bugs without getting roadblocked by compiler limitations or hard-to-repair compiler design flaws (or dirty hacks in the compiler that were introduced to paper over the fundamental schizophrenic problem of struct AssociativeArray being distinct yet not different from the AA implementation in aaA.d). Things are MUCH easier to fix when you can directly access key/value types instead of having only TypeInfo's and needing to resort to void* casting. [...]
 C++ ctors are a royal pain in the neck. [...]
 I ended up using just stub ctors for a lot of my code, and doing the
 actual initialization after the object is constructed. Which is very
 bad OO style, I agree, but the pain of working with C++ ctors just
 pushes me in the wrong direction, y'know?
Yea, that's what I've been planning on doing with the C++ stuff I have coming up. Don't even want to bother with C++'s ctor limitations. Just make an init() member and be done with it. Actually, that seems to be turning into more and more of a common C++ idiom though, from what (little) I've seen.
The fact that C++ is pushing people in that direction is scary. It breaks one of the principles of good object design, which is that all sequences of method calls should never cause it to enter into an inconsistent state. This no longer holds if init() has to be called first. This is a sign that something is fundamentally wrong with the language.
 [...] (And even finally: I head somewhere C++ doesn't even have
 finally: Is that true?!?)
Yes, it's true. I don't know about C++11, but certainly the previous standard has no finally clause, leading to horribly unmaintainable and ugly code like: Resource r = acquireResource(); try { doSomethingDangerous(); } catch(...) { r.release(); } r.release();
Haxe also lacks finally! Which I always found rediculous. So yea, I'm intimately familiar with that idiom. I've used it myself far more than I would like.
And actually there's already a bug in the code I wrote: I forgot the rethrow inside the catch(...). See, that's how bug-prone this stupid idiom is.
 And even *that* still doesn't work if you don't catch *every*
 exception (and then rethrow the ones you don't care about? Ick!).
Actually, you can catch "..." and it will catch *everything*. And I believe a single "throw;" will rethrow whatever it is you caught.
 I've seen C++ programmers swear off exceptions because of this, and I
 can't blame them at all.  Exception systems *need* a finally.
Yeah. "catch(...)" sorta works, but it's very ugly. And while being able to throw *anything* at all is nice (I'm guilty of writing code that throws char*, for example), not being able to make *any* assumptions at all about what you caught (e.g., no common exception superclass with some useful methods, like .msg) is, shall we say, practically useless in a large enough project? (Actually, the lack of .msg was what drove me to throw char*. Obviously checking return codes for every lousy function I call is out of the question, but so is throwing error codes that come from different subsystems, since you've no way of telling which error code scheme to use to look up the error. So I said to myself, why not throw a string that actually tells you what the error is? Furthermore, if these strings were predefined in char arrays that had unique pointer addresses, the value of the pointer itself serves as a kind of "global error number". So this worked as a kind of a poor man's error code + message exception that can be freely thrown around without problems --- the reason I shied away from throwing class objects in the first place was because early implementations of C++ had problems that sometimes caused pointer bugs and all kinds of nasty side effects when a class object is thrown. Like if you forget to define a copy ctor for your exception class, and you forget to catch by reference instead of by value... With a char*, there can be no such problem unless the compiler is completely unusable.) [...]
 For all the warts the current GC has, the fact that D has a GC at
 all makes things like array slicing possible, and *fast*, which
 leads to all the other niceties of slicing.
I used to do indie game dev in C/C++ and I feel downright spoiled now with tossing in a "new" whenever appropriate and not have to worry about cleanup (and even that wouldn't be *too* bad...in certain cases...if there were at least scope guards).
Scope guards rule. Ironically, D's GC mostly alleviates the need for scope guards. :-) They're still immensely useful when you acquire resources that must be cleaned up no matter what happens later. D is the first and only language I know that got resource cleanup done right. Cleanups belong with the acquisition code, not dangling somewhere 200 lines down at the end of the scope, with who knows how many possible leaks in between due to goto's, exceptions, returns, and who knows what! [...]
 Definitely. Using alias and static if in a recursive template is one
 of the hallmarks of the awesomeness of D templates.
I'd say one of the hallmarks of D's metaprogramming is the enormous *decrease* in the need for recursive templates in the first place ;)
CTFE even makes it possible to express what many recursive templates express, in pure imperative style. I mean, you can't get any better than this: int factorial(int n) { int result = 1; while (n>1) { result *= n; result--; } return result; } enum x = factorial(12); // compile-time computation int y = factorial(12); // runtime computation In C++, you'd have to use recursive templates that are extremely difficult to read and write beyond the simplest of functions.
 With C++'s templates, it would appear that you have to use recursion
 and helper templates for damn near anything.
[...] Not to mention the horrible, horrible, syntax that comes with recursive templates. My previous manager used to tell me that as soon as he sees nested templates deeper than 2 levels, his eyes start glazing over, and it all becomes just arcane black magic. T -- Which is worse: ignorance or apathy? Who knows? Who cares? -- Erich Schubert
Mar 20 2012
parent reply "Nick Sabalausky" <a a.a> writes:
"H. S. Teoh" <hsteoh quickfur.ath.cx> wrote in message 
news:mailman.949.1332305140.4860.digitalmars-d puremagic.com...
 Yeah, AA's with int keys are like arrays enhanced with O(1)
 insertion/removal and sparse storage (if you have very large indices,
 e.g.). :-) You can even have (pseudo) linear access if you iterate keys
 from 0 to $.
Exactly.
 For example, it lets you accept keys/values that are not strictly the
 AA's key/value type, but can be implicitly converted to them. It lets
 you return keys and values without needing the ugly typeinfo and void*
 casts that are necessary in aaA.d.  This in turn lets you mark many AA
 methods as pure, and almost all as  safe or  trusted. It lets you
 cleanly interoperate with types that define opAssign (currently aaA.d
 does a blind binary copy of data from key/value pointers, which leads to
 potential bugs when the data has subobjects.)

 It also makes it *much* easier to fix many existing AA bugs in the
 bugtracker. So far, I have working unittests for the following issues:
 3824, 3825, 4337, 4463, 5685, 6210, 7512, 7512, 7602, 7632, 7665, 7665,
 7704. I haven't looked through all AA-related issues yet; this list may
 very well grow. :-) To fix these in the current aaA.d implementation can
 be rather tricky, and quite possibly requires compiler changes.
I see. Cool stuff.
 Better yet, I thought of a way of making AA's instantiable at
 compile-time via CTFE and mixins: this will let you write AA literals
 that can be evaluated at compile-time and have them turn into object
 code directly without needing runtime initialization.
Ah! Now *that's* fucking awesome! That limitation has kinda stuck out as an odd, annoying wart.
 And even *that* still doesn't work if you don't catch *every*
 exception (and then rethrow the ones you don't care about? Ick!).
Actually, you can catch "..." and it will catch *everything*. And I believe a single "throw;" will rethrow whatever it is you caught.
I see. It has been awhile since I've been in the C++ loop.
 I've seen C++ programmers swear off exceptions because of this, and I
 can't blame them at all.  Exception systems *need* a finally.
Yeah. "catch(...)" sorta works, but it's very ugly. And while being able to throw *anything* at all is nice (I'm guilty of writing code that throws char*, for example), not being able to make *any* assumptions at all about what you caught (e.g., no common exception superclass with some useful methods, like .msg) is, shall we say, practically useless in a large enough project?
Boy, it really has been awhile. I knew you could throw any class object in C++, but I thought that was all. Haxe lets you throw literally anything, even Int, and I found that to be more of a problem than a feature (In very much the same way as VB's ability to change the lower bound of an array: It gains little and just means you have to remember to do the rediculous "UBound(arr) - LBound(arr)".) Just have a proper Exception class and nothing else should be throwable (D's "Error" notwithstanding).
 (Actually, the lack of .msg was what drove me to throw char*. Obviously
 checking return codes for every lousy function I call is out of the
 question, but so is throwing error codes that come from different
 subsystems, since you've no way of telling which error code scheme to
 use to look up the error. So I said to myself, why not throw a string
 that actually tells you what the error is? Furthermore, if these strings
 were predefined in char arrays that had unique pointer addresses, the
 value of the pointer itself serves as a kind of "global error number".
 So this worked as a kind of a poor man's error code + message exception
 that can be freely thrown around without problems
That is an interesting work around.
 the reason I shied
 away from throwing class objects in the first place was because early
 implementations of C++ had problems that sometimes caused pointer bugs
 and all kinds of nasty side effects when a class object is thrown.
Ouch!
 Scope guards rule. Ironically, D's GC mostly alleviates the need for
 scope guards. :-) They're still immensely useful when you acquire
 resources that must be cleaned up no matter what happens later. D is the
 first and only language I know that got resource cleanup done right.
 Cleanups belong with the acquisition code, not dangling somewhere 200
 lines down at the end of the scope, with who knows how many possible
 leaks in between due to goto's, exceptions, returns, and who knows what!
I've even come across at least a couple uses of scope guard that aren't strictly related to releasing resources. Actually, I've just been working with both of them today: - Temporarily changing a value: int bar; void foo() { // Change bar temporarily auto saveBar = bar; bar = 777; scope(exit) bar = saveBar; [...do anything here...] } - Timing a section of code. I saw this trick in someone else's code once, loved it, and made a helper tool out of it: https://bitbucket.org/Abscissa/semitwistdtools/src/4455e019cd95/src/semitwist/util/mixins.d#cl-643 It's a string mixin that, after features and hygenic issues and such, basically boils down to mixing in this psuedo-code: if(verbose) { write(customMessage, "..."); // no newline stdout.flush(); startTimer(); // Using the awesome new std.datetime } scope(exit) if(verbose) writeln(timerInMilliseconds(), "ms");
 CTFE even makes it possible to express what many recursive templates
 express, in pure imperative style. I mean, you can't get any better than
 this:

 int factorial(int n) {
 int result = 1;
 while (n>1) {
 result *= n;
 result--;
 }
 return result;
 }
 enum x = factorial(12); // compile-time computation
 int y = factorial(12); // runtime computation

 In C++, you'd have to use recursive templates that are extremely
 difficult to read and write beyond the simplest of functions.
Yup exactly. It's Haskell with bad syntax and compile times. Not only that, but even something as trivial as "if" has to be built out of pure-fp primitives in C++-template-land, whereas D just has: "static if...done!" Of course, to C++'s credit, its templates (AIUI) weren't really designed for metaprogramming, just for generics. The metaprogramming was just a happy accident (At least that's my understanding, maybe I'm wrong...)
 With C++'s templates, it would appear that you have to use recursion
 and helper templates for damn near anything.
[...] Not to mention the horrible, horrible, syntax that comes with recursive templates. My previous manager used to tell me that as soon as he sees nested templates deeper than 2 levels, his eyes start glazing over, and it all becomes just arcane black magic.
Yea. Even a "simpler" use of C++'s templates can feel like staring into the depths of hell: Ever see a loop over a collection using STL iterators? Sheesh. I like the idea behind the STL, but with syntax like that I'd rather use the old "for(int i=0; i<theEnd; i++)". Gimme a proper foreach anyday. Come to think of it, foreach probably fits the bill for the OP: For people who came from C/C++ like I did, it can seem like a relatively trivial sugar over "for(int i=0; i<theEnd; i++)". But it makes such a difference to just not have to constantly deal with those minute mechanics.
 -- 
 Which is worse: ignorance or apathy? Who knows? Who cares? -- Erich 
 Schubert
lol :) Now that's without a doubt one of my favorites.
Mar 21 2012
parent Walter Bright <newshound2 digitalmars.com> writes:
On 3/21/2012 1:01 AM, Nick Sabalausky wrote:
 Of course, to C++'s credit, its templates (AIUI) weren't really designed for
 metaprogramming, just for generics. The metaprogramming was just a happy
 accident (At least that's my understanding, maybe I'm wrong...)
You're correct. Metaprogramming was an emergent property of C++ templates, and was discovered, not designed.
Mar 21 2012
prev sibling next sibling parent reply Brad Anderson <eco gnuk.net> writes:
On Tue, Mar 20, 2012 at 10:47 PM, H. S. Teoh <hsteoh quickfur.ath.cx> wrote:

[snip]

I would say the main benefit is having it implemented in the library,
 because that allows the implementation have direct access to key/value
 types. I didn't implement any clever new hashing algorithm at all, I
 just mainly followed the implementation in aaA.d. But having direct
 access to key/value types is a *huge* win.

 For example, it lets you accept keys/values that are not strictly the
 AA's key/value type, but can be implicitly converted to them. It lets
 you return keys and values without needing the ugly typeinfo and void*
 casts that are necessary in aaA.d.  This in turn lets you mark many AA
 methods as pure, and almost all as  safe or  trusted. It lets you
 cleanly interoperate with types that define opAssign (currently aaA.d
 does a blind binary copy of data from key/value pointers, which leads to
 potential bugs when the data has subobjects.)
It's probably far too early to think about this with all the other important issues you're addressing but have you given much thought to improving the hashing function? I haven't hit any issues with the speed of the current hasher but better performance is always welcome. MurmurHash seems to be all the rage these days with a lot of languages and systems adopting it <http://en.wikipedia.org/wiki/MurmurHash> (it compiles down to ~52 instructions on x86). It'd be interesting to see benchmarks with it. I'm not sure where the current hashing function lives to see what it's like. Regards, Brad Anderson
Mar 20 2012
parent reply "Martin Nowak" <dawg dawgfoto.de> writes:
 It's probably far too early to think about this with all the other
 important issues you're addressing but have you given much thought to
 improving the hashing function?  I haven't hit any issues with the speed  
 of
 the current hasher but better performance is always welcome. MurmurHash
 seems to be all the rage these days with a lot of languages and systems
 adopting it <http://en.wikipedia.org/wiki/MurmurHash> (it compiles down  
 to
 ~52 instructions on x86). It'd be interesting to see benchmarks with it.
 I'm not sure where the current hashing function lives to see what it's  
 like.

 Regards,
 Brad Anderson
More throughput but higher latency. http://codepad.org/kCVQ8eoq Murmurhash was a little slower than CityHash but both are a little expensive for very few bytes.
Mar 21 2012
parent Brad Anderson <eco gnuk.net> writes:
On Wed, Mar 21, 2012 at 2:06 AM, Martin Nowak <dawg dawgfoto.de> wrote:

 It's probably far too early to think about this with all the other
 important issues you're addressing but have you given much thought to
 improving the hashing function?  I haven't hit any issues with the speed
 of
 the current hasher but better performance is always welcome. MurmurHash
 seems to be all the rage these days with a lot of languages and systems
 adopting it <http://en.wikipedia.org/wiki/**MurmurHash<http://en.wikipedia.org/wiki/MurmurHash>>
 (it compiles down to
 ~52 instructions on x86). It'd be interesting to see benchmarks with it.
 I'm not sure where the current hashing function lives to see what it's
 like.

 Regards,
 Brad Anderson
More throughput but higher latency. http://codepad.org/kCVQ8eoq Murmurhash was a little slower than CityHash but both are a little expensive for very few bytes.
Interesting. Thanks for the link. Regards, Brad Anderson
Mar 21 2012
prev sibling next sibling parent "H. S. Teoh" <hsteoh quickfur.ath.cx> writes:
On Tue, Mar 20, 2012 at 11:54:37PM -0600, Brad Anderson wrote:
[...]
 It's probably far too early to think about this with all the other
 important issues you're addressing but have you given much thought to
 improving the hashing function?  I haven't hit any issues with the
 speed of the current hasher but better performance is always welcome.
 MurmurHash seems to be all the rage these days with a lot of languages
 and systems adopting it <http://en.wikipedia.org/wiki/MurmurHash> (it
 compiles down to ~52 instructions on x86). It'd be interesting to see
 benchmarks with it.  I'm not sure where the current hashing function
 lives to see what it's like.
[...] The current implementation actually has (at least) two different hash functions: - Paul Hsieh's SuperFastHash (rt.util.hash.hashOf) - A custom hash for char[] and string: look in rt/typeinfo/ti_Ag.d for class TypeInfo_Aa, which has this: hash_t hash = 0; foreach (char c; s) hash = hash * 11 + c; I'm going to benchmark both hash functions to see which is actually faster. I suspect the custom hash is faster for small strings, though it may not have good hash distribution. T -- Microsoft is to operating systems & security ... what McDonalds is to gourmet cooking.
Mar 21 2012
prev sibling parent reply Sean Kelly <sean invisibleduck.org> writes:
On Mar 20, 2012, at 10:54 PM, Brad Anderson wrote:
=20
 It's probably far too early to think about this with all the other =
important issues you're addressing but have you given much thought to = improving the hashing function? I haven't hit any issues with the speed = of the current hasher but better performance is always welcome. = MurmurHash seems to be all the rage these days with a lot of languages = and systems adopting it <http://en.wikipedia.org/wiki/MurmurHash> (it = compiles down to ~52 instructions on x86). It'd be interesting to see = benchmarks with it. I'm not sure where the current hashing function = lives to see what it's like. Druntime actually did use MurmurHash for a while and then dropped it = because the site had no copyright license for the code (a mistake that = has since been rectified). I'd consider switching back, though I don't = really like that MurmurHash has a number of separate implementations = targeted at different platforms, each having different performance = characteristics. It's 4x faster than SuperFastHash on x86 but 10x = slower than SuperFastHash on SPARC, for example.=
Mar 21 2012
next sibling parent reply "Nick Sabalausky" <a a.a> writes:
"Sean Kelly" <sean invisibleduck.org> wrote in message 
news:mailman.981.1332359368.4860.digitalmars-d puremagic.com...
Druntime actually did use MurmurHash for a while and
then dropped it because the site had no copyright license
for the code (a mistake that has since been rectified).  I'd
consider switching back, though I don't really like that
MurmurHash has a number of separate implementations
targeted at different platforms, each having different
performance characteristics.  It's 4x faster than SuperFastHash
on x86 but 10x slower than SuperFastHash on SPARC,
for example.=
People still use SPARC? /me out of the loop
Mar 21 2012
parent Sean Kelly <sean invisibleduck.org> writes:
On Mar 21, 2012, at 1:24 PM, Nick Sabalausky wrote:

 "Sean Kelly" <sean invisibleduck.org> wrote in message=20
 news:mailman.981.1332359368.4860.digitalmars-d puremagic.com...
=20
 Druntime actually did use MurmurHash for a while and
 then dropped it because the site had no copyright license
 for the code (a mistake that has since been rectified).  I'd
 consider switching back, though I don't really like that
 MurmurHash has a number of separate implementations
 targeted at different platforms, each having different
 performance characteristics.  It's 4x faster than SuperFastHash
 on x86 but 10x slower than SuperFastHash on SPARC,
 for example.=3D
=20 People still use SPARC? =20 /me out of the loop
Yup. Though these days it seems more common to use x86 Solaris instead, = and even that subset is transitioning to Linux.=
Mar 21 2012
prev sibling parent reply Jacob Carlborg <doob me.com> writes:
On 2012-03-21 20:49, Sean Kelly wrote:

 Druntime actually did use MurmurHash for a while and then dropped it because
the site had no copyright license for the code (a mistake that has since been
rectified).  I'd consider switching back, though I don't really like that
MurmurHash has a number of separate implementations targeted at different
platforms, each having different performance characteristics.  It's 4x faster
than SuperFastHash on x86 but 10x slower than SuperFastHash on SPARC, for
example.
Would it be possible to use different algorithms on different platforms? -- /Jacob Carlborg
Mar 21 2012
next sibling parent "Jonathan M Davis" <jmdavisProg gmx.com> writes:
On Wednesday, March 21, 2012 22:18:16 Jacob Carlborg wrote:
 On 2012-03-21 20:49, Sean Kelly wrote:
 Druntime actually did use MurmurHash for a while and then dropped it
 because the site had no copyright license for the code (a mistake that
 has since been rectified). I'd consider switching back, though I don't
 really like that MurmurHash has a number of separate implementations
 targeted at different platforms, each having different performance
 characteristics. It's 4x faster than SuperFastHash on x86 but 10x slower
 than SuperFastHash on SPARC, for example.
Would it be possible to use different algorithms on different platforms?
I'm sure that it would be, but it sounds like part of his complaint is that you end up with different implementations per platform with using MurmurHash, and using a different hash algorithm per architecture is just as bad in that respect. If you're trying to absolutely maximize performance though, that would probably be the way to go if there isn't one which is a clear winner on all architectures. It doesn't matter all that much for dmd at present though, since it's x86-only. - Jonathan M Davis
Mar 21 2012
prev sibling next sibling parent Sean Kelly <sean invisibleduck.org> writes:
On Mar 21, 2012, at 2:18 PM, Jacob Carlborg wrote:

 On 2012-03-21 20:49, Sean Kelly wrote:
=20
 Druntime actually did use MurmurHash for a while and then dropped it =
because the site had no copyright license for the code (a mistake that = has since been rectified). I'd consider switching back, though I don't = really like that MurmurHash has a number of separate implementations = targeted at different platforms, each having different performance = characteristics. It's 4x faster than SuperFastHash on x86 but 10x = slower than SuperFastHash on SPARC, for example.
=20
 Would it be possible to use different algorithms on different =
platforms? Depends whether there's any reason to have different platforms attempt = to generate the same hash for a given input.=
Mar 21 2012
prev sibling parent "H. S. Teoh" <hsteoh quickfur.ath.cx> writes:
On Wed, Mar 21, 2012 at 10:18:16PM +0100, Jacob Carlborg wrote:
 On 2012-03-21 20:49, Sean Kelly wrote:
 
Druntime actually did use MurmurHash for a while and then dropped it
because the site had no copyright license for the code (a mistake
that has since been rectified).  I'd consider switching back, though
I don't really like that MurmurHash has a number of separate
implementations targeted at different platforms, each having
different performance characteristics.  It's 4x faster than
SuperFastHash on x86 but 10x slower than SuperFastHash on SPARC, for
example.
Would it be possible to use different algorithms on different platforms?
[...] Should be as simple as adding version() to rt.util.hash.hashOf, I think. But I don't know if there may be potential issues with that. T -- If you want to solve a problem, you need to address its root cause, not just its symptoms. Otherwise it's like treating cancer with Tylenol...
Mar 21 2012
prev sibling parent reply Walter Bright <newshound2 digitalmars.com> writes:
On 3/20/2012 4:39 PM, H. S. Teoh wrote:
 On Tue, Mar 20, 2012 at 06:58:31PM -0400, Nick Sabalausky wrote:
 - Type inference
Yeah I forgot about this one. Being able to write: auto veryLongNamedObject = new VeryLongNamedClass(veryLongArguments); is a big boon over C++ or Java's stuttering verbosity: VeryLongNamedClass veryLongNamedObject = new VeryLongNamedClass(veryLongArguments); Plus, it's immensely useful when dealing with Range templates... can you imagine the horrifically long typenames you'd have to type you have to explicitly specify the type of a long chain of functional expressions involving 15+ std.algorithm and std.range templates?
Andrei discovered an amazing use of auto. It enables you to create variables with voldemort types "that may not be named". For example: auto foo() { struct S { ... } S s; return s; } auto x = foo(); And now x is an instance of a voldemort type! It's completely encapsulated.
Mar 20 2012
next sibling parent reply Andrei Alexandrescu <SeeWebsiteForEmail erdani.org> writes:
On 3/20/12 9:47 PM, Walter Bright wrote:
 auto foo()
 {
 struct S { ... }
 S s;
 return s;
 }

 auto x = foo();

 And now x is an instance of a voldemort type! It's completely encapsulated.
LOL. Heck, I'd include "Voldemort types" just because it sounds so cool. Andrei
Mar 20 2012
parent Walter Bright <newshound2 digitalmars.com> writes:
On 3/20/2012 8:00 PM, Andrei Alexandrescu wrote:
 On 3/20/12 9:47 PM, Walter Bright wrote:
 And now x is an instance of a voldemort type! It's completely encapsulated.
LOL. Heck, I'd include "Voldemort types" just because it sounds so cool.
Yeah, I'm going to title my next blog entry that!
Mar 20 2012
prev sibling next sibling parent Andrej Mitrovic <andrej.mitrovich gmail.com> writes:
On 3/21/12, Walter Bright <newshound2 digitalmars.com> wrote:
 Andrei discovered an amazing use of auto.
It's funny how the book explicitly stated that this doesn't work (page 263): "Nested struct objects cannot be returned from functions because the caller doesn't have access to their type". I posted about this back in 2011: http://www.digitalmars.com/d/archives/digitalmars/D/Has_the_ban_on_returning_function_nested_structs_been_lifted_132233.html It might have been a relic from earlier TDPL writing when this feature didn't exist. :)
Mar 20 2012
prev sibling next sibling parent "Patrick Down" <patrick.down gmail.com> writes:
On Wednesday, 21 March 2012 at 02:47:20 UTC, Walter Bright wrote:
 Andrei discovered an amazing use of auto. It enables you to 
 create variables with voldemort types "that may not be named".
+1 LOL for Voldemort types
Mar 21 2012
prev sibling parent reply Don Clugston <dac nospam.com> writes:
On 21/03/12 03:47, Walter Bright wrote:
 On 3/20/2012 4:39 PM, H. S. Teoh wrote:
 On Tue, Mar 20, 2012 at 06:58:31PM -0400, Nick Sabalausky wrote:
 - Type inference
Yeah I forgot about this one. Being able to write: auto veryLongNamedObject = new VeryLongNamedClass(veryLongArguments); is a big boon over C++ or Java's stuttering verbosity: VeryLongNamedClass veryLongNamedObject = new VeryLongNamedClass(veryLongArguments); Plus, it's immensely useful when dealing with Range templates... can you imagine the horrifically long typenames you'd have to type you have to explicitly specify the type of a long chain of functional expressions involving 15+ std.algorithm and std.range templates?
Andrei discovered an amazing use of auto. It enables you to create variables with voldemort types "that may not be named". For example: auto foo() { struct S { ... } S s; return s; } auto x = foo(); And now x is an instance of a voldemort type! It's completely encapsulated.
That idiom is already built into the language. Anonymous nested classes don't have a name at all. auto x = new class { ... }
Mar 21 2012
parent reply Walter Bright <newshound2 digitalmars.com> writes:
On 3/21/2012 8:21 AM, Don Clugston wrote:
 On 21/03/12 03:47, Walter Bright wrote:
 And now x is an instance of a voldemort type! It's completely encapsulated.
That idiom is already built into the language. Anonymous nested classes don't have a name at all. auto x = new class { ... }
True, but it's the ability to return them from a function that's new & cool! (Yes, I know you can return x as type "Object".)
Mar 21 2012
parent reply Don <nospam nospam.com> writes:
On 21.03.2012 18:14, Walter Bright wrote:
 On 3/21/2012 8:21 AM, Don Clugston wrote:
 On 21/03/12 03:47, Walter Bright wrote:
 And now x is an instance of a voldemort type! It's completely
 encapsulated.
That idiom is already built into the language. Anonymous nested classes don't have a name at all. auto x = new class { ... }
True, but it's the ability to return them from a function that's new & cool! (Yes, I know you can return x as type "Object".)
BTW what is 'nested' about anonymous nested classes? They seem to work anywhere! Can we just drop that from the name?
Mar 21 2012
parent Timon Gehr <timon.gehr gmx.ch> writes:
On 03/21/2012 09:00 PM, Don wrote:
 BTW what is 'nested' about anonymous nested classes? They seem to work
 anywhere! Can we just drop that from the name?
Seems reasonable. BTW: They don't work in a typeof expression: http://d.puremagic.com/issues/show_bug.cgi?id=7104
Mar 21 2012
prev sibling parent Jacob Carlborg <doob me.com> writes:
On 2012-03-20 23:58, Nick Sabalausky wrote:
 - Type inference
 - alias
 - foreach
 - Everything about arrays/slices
 - Built-in associative arrays that support nearly any type as a key
 - Reference semantics for classes
 - All the niceities of ctors compared with C++'s ctors
 - Backtick strings
 - Scope guards (And even finally: I head somewhere C++ doesn't even have
 finally: Is that true?!?)
 - GC
 - Name any of D's metaprogramming features

 Many of those can seem like simple things, but I'd *hate* to have to get by
 without them. Heck, most of them I now take for granted.

 Alias in particular is a much bigger deal than it seems since it's seemingly
 trivial but can be *incredibly* helpful with templates *and* with importing.

 Actually, looking at this list, I'm now starting to get a little worried
 about an upcoming C++ project... No doubt I'll be trying to reinvent a lot
 of D in it. Probably in ugly hackish ways.
I did that in one project. I emulated properties, using boost I emulated foreach, auto, lambdas and other features. If you're using C++11 you'll have these features native, expect for properties. I did the mistake and learned D before I learned C++. -- /Jacob Carlborg
Mar 21 2012
prev sibling next sibling parent reply "Adam D. Ruppe" <destructionator gmail.com> writes:
What you might want to do is look back at
early ng posts about features and see which
ones were met with "meh", but universally
considered to rok now.

Asking for stuff now will be hard to be
unbiased on the surprise issue.


If my memory serves, a few things that were
"meh" when announced but that rok now are:

1) enum. I remember an argument over if we
should call it invariant, manifest, or the
relatively unpopular enum keyword, but I
don't recall people at the time expecting
it to be as useful as it is now.

The argument was between

manifest MY_VALUE = 1;
and
enum MY_VALUE = 1;

without thoughts along the line of:

template octal(...) {
     alias octalImpl(t) octal;
}

or most the other stuff we use ctfe with now.


(Speaking of octal, I remember that being dismisses
as a "hack" by some members too. Now, it looks like
that pattern is catching on for user defined literals,
and it rox.)


My memory might be bad, but looking at some old posts
could confirm if the "unlikely success" label is warranted.




2) Leaving the parenthesis off of simple template
instantiations is something I was against early on,
and now I love it.

IIRC, you wanted to use a different symbol entirely,
and leaving the parens off was a compromise between
the radical Unicode character proposal and Walter's
conservative parenthesis.



This is a really small change. At the time, it seemed
like it would be stupid and useless.



But, would templates be as popular now if we didn't
make this change?

auto a = to!(int)("10");

vs

auto a = to!int("10");



to!int feels like one word, unlike to!(int)().
Who needs atoi when we can say to!int?


Decls too: Appender!int, etc. The popularity of
this in phobos and outside speaks to a success
I didn't expect.



3) My mind is coming up blank on a third newsgroup argument
over an awesome feature we use now. But, something I
am often amazed about is how cool structs are.

When you say "struct", I used to think of "whoo a collection
of vars, big deal".

But, now, with D2, when you say "struct", I think "fully
customizable powerhouse".

(even coming from C++, where much of this can be done, D's
structs are still a little mindblowing in comparison.)
Mar 20 2012
next sibling parent "Adam D. Ruppe" <destructionator gmail.com> writes:
On Wednesday, 21 March 2012 at 00:53:19 UTC, Adam D. Ruppe wrote:
 template octal(...) {
     alias octalImpl(t) octal;
 }
LOL, I was bloviating about "enum" and ended up using "alias" here. alias rox too (which is a bit amazing, considering how simple it is), but I should have said: enum octal = octalImpl(t);
Mar 20 2012
prev sibling parent reply "Nick Sabalausky" <a a.a> writes:
"Adam D. Ruppe" <destructionator gmail.com> wrote in message 
news:txwnbkafemkurcqjermf forum.dlang.org...
 2) Leaving the parenthesis off of simple template
 instantiations is something I was against early on,
 and now I love it.

 IIRC, you wanted to use a different symbol entirely,
 and leaving the parens off was a compromise between
 the radical Unicode character proposal and Walter's
 conservative parenthesis.

 This is a really small change. At the time, it seemed
 like it would be stupid and useless.
Yea, that's a good one. I seem to remember initally thinking that it felt sloppy, but I was otherwise relatively indifferent about it. But now I absolutely love it...sooo much.
 But, would templates be as popular now if we didn't
 make this change?

 auto a = to!(int)("10");

 vs

 auto a = to!int("10");
Exactly. Ooh, nested functions and closures are another good one (or two). I get so much use of of those. Speaking of, here's a good one (IMO): The syntax for delegate types (as opposed to C's crude function pointer syntax). A small change, but really helps open up the world of first-class functions, even just by itself.
Mar 20 2012
parent reply "Adam D. Ruppe" <destructionator gmail.com> writes:
On Wednesday, 21 March 2012 at 02:14:26 UTC, Nick Sabalausky 
wrote:
 Ooh, nested functions and closures are another good one (or 
 two).
I wouldn't call that unlikely, since nested functions are one of the things I considered a potential killer feature when I started with D. (and indeed, it is very useful!) Nested functions, auto, and scope guards were the three killers in the pre-D1 that roped me in. And they rok, oh they rok. But that is "likely success" :) (well, and fast compilation; going back to Digital Mars after some years of slow ass g++ was/is heaven) One that surprised me personally though is import. Indeed, import is why I passed over D the first time I looked at it (in 2004 IIRC) - I saw "import" and said "gah include is fine, eff this Java like poo.. Even when I got into D, I had to give myself comfort that I can still have #include with mixin(import()) - something I have never actually wanted to use after writing the first line of real code. import is amazing. D gets it all right, even with stuff like bug 314, it is awesome. But, is import unlikely success, or is this just a leftover feeling from my massive bias in the early days? I have to say it is my bias, since everyone else uses import and they all know it is good.
Mar 21 2012
next sibling parent reply Walter Bright <newshound2 digitalmars.com> writes:
On 3/21/2012 7:23 AM, Adam D. Ruppe wrote:
 But, is import unlikely success, or is this just a
 leftover feeling from my massive bias in the early
 days? I have to say it is my bias, since everyone
 else uses import and they all know it is good.
I knew import would be good :-) It's because I've used languages before with an import, and as a compiler guy, I knew what a kludge #include is. The preprocessor in C/C++ is a crutch to make up for deficiencies in the language.
Mar 21 2012
next sibling parent Jacob Carlborg <doob me.com> writes:
On 2012-03-21 18:20, Walter Bright wrote:

 I knew import would be good :-)

 It's because I've used languages before with an import, and as a
 compiler guy, I knew what a kludge #include is. The preprocessor in
 C/C++ is a crutch to make up for deficiencies in the language.
I've never been able to properly handle includes in C/C++. Import is SO much better. -- /Jacob Carlborg
Mar 21 2012
prev sibling parent reply "Kapps" <opantm2+spam gmail.com> writes:
On Wednesday, 21 March 2012 at 17:20:28 UTC, Walter Bright wrote:
 On 3/21/2012 7:23 AM, Adam D. Ruppe wrote:
 But, is import unlikely success, or is this just a
 leftover feeling from my massive bias in the early
 days? I have to say it is my bias, since everyone
 else uses import and they all know it is good.
I knew import would be good :-) It's because I've used languages before with an import, and as a compiler guy, I knew what a kludge #include is. The preprocessor in C/C++ is a crutch to make up for deficiencies in the language.
On the topic of import, mixin imports are something that I believe will eventually become a great deal more popular than they are today. First, there's the advantage of being able to use a language/syntax more appropriate for the task at hand. For example, for things that output html you could just import mixin a raw html file. But the real advantage is that you can still do compile-time processing on this. Plug in an xml parser, or something like pegged, and you can now extend Html and generate D code for it. For example, if you have something like runat="server" on an element, just like in ASP.net you could create a serverside element for this and manipulate it. Because you know exactly which parts are static and which are dynamic, you could (at compile time) create buffers containing the static portions to prevent having to copy things many times. Unlike other languages, there would be no performance hit to doing this because it's all done at compile time. This is just one example. Another one would be automatically creating bindings for a scripting language, or even automatically creating bindings for a C header file.
Mar 21 2012
next sibling parent reply "F i L" <witte2008 gmail.com> writes:
Kapps wrote:
 or even automatically creating bindings for a C header file.
I've thought about that before. It would be great to have fully automatic linking to C libs. You could even have a cache system that stores .di files and only regenerates them if the .h file was modified.
Mar 21 2012
next sibling parent reply "Nick Sabalausky" <a a.a> writes:
"F i L" <witte2008 gmail.com> wrote in message 
news:sofbqiiyvragxjaxqbix forum.dlang.org...
 Kapps wrote:
 or even automatically creating bindings for a C header file.
I've thought about that before. It would be great to have fully automatic linking to C libs. You could even have a cache system that stores .di files and only regenerates them if the .h file was modified.
That hits on the one irritating limitation of CTFE: No I/O. So that cache system would be a no-go right now.
Mar 21 2012
next sibling parent "F i L" <witte2008 gmail.com> writes:
On Wednesday, 21 March 2012 at 21:38:16 UTC, Nick Sabalausky 
wrote:
 "F i L" <witte2008 gmail.com> wrote in message
 news:sofbqiiyvragxjaxqbix forum.dlang.org...
 Kapps wrote:
 or even automatically creating bindings for a C header file.
I've thought about that before. It would be great to have fully automatic linking to C libs. You could even have a cache system that stores .di files and only regenerates them if the .h file was modified.
That hits on the one irritating limitation of CTFE: No I/O. So that cache system would be a no-go right now.
Didn't realize that. Well until IO in CTFE is possible, converting a .h file into a .di file is still possible. Once that's done then it could just be wrapped up into a mixin cache system. D already has a tool to do this I believe (htod). Never used it though.
Mar 21 2012
prev sibling parent Timon Gehr <timon.gehr gmx.ch> writes:
On 03/21/2012 10:37 PM, Nick Sabalausky wrote:
 "F i L"<witte2008 gmail.com>  wrote in message
 news:sofbqiiyvragxjaxqbix forum.dlang.org...
 Kapps wrote:
 or even automatically creating bindings for a C header file.
I've thought about that before. It would be great to have fully automatic linking to C libs. You could even have a cache system that stores .di files and only regenerates them if the .h file was modified.
That hits on the one irritating limitation of CTFE: No I/O. So that cache system would be a no-go right now.
I once cached CTFE results by wrapping some templates into another template that would generate pragma(msg, ...) output that was then fitered out by an external d program and written to temporary files. On the next compilation run, the wrapper template would notice the existence of a suitable cache file and use its contents instead of starting the CTFE execution.
Mar 21 2012
prev sibling parent reply Jacob Carlborg <doob me.com> writes:
On 2012-03-21 22:32, F i L wrote:
 Kapps wrote:
 or even automatically creating bindings for a C header file.
I've thought about that before. It would be great to have fully automatic linking to C libs. You could even have a cache system that stores .di files and only regenerates them if the .h file was modified.
I've been thinking on that as well since I'm writing a tool for converting header files. But I was thinking more of modifying the compiler and adding a new pragma that calls into my library. -- /Jacob Carlborg
Mar 21 2012
parent "F i L" <witte2008 gmail.com> writes:
Jacob Carlborg wrote:
 But I was thinking more of modifying the compiler and adding a 
 new pragma that calls into my library.
That would probably be a better option I think. In fact, eventually DMD could just have the cache system built in and the ability to import .h files just like .d ones. Now that would be pretty cool. All the .di cache files could be stored in ~/.dmd/ (or equivalent) or converted manually (dmd -CtoD file.h) for distribution.
Mar 21 2012
prev sibling next sibling parent "Nick Sabalausky" <a a.a> writes:
"Kapps" <opantm2+spam gmail.com> wrote in message 
news:nnqtlpjqwdnzuwiqcycr forum.dlang.org...
 On Wednesday, 21 March 2012 at 17:20:28 UTC, Walter Bright wrote:
 On 3/21/2012 7:23 AM, Adam D. Ruppe wrote:
 But, is import unlikely success, or is this just a
 leftover feeling from my massive bias in the early
 days? I have to say it is my bias, since everyone
 else uses import and they all know it is good.
I knew import would be good :-) It's because I've used languages before with an import, and as a compiler guy, I knew what a kludge #include is. The preprocessor in C/C++ is a crutch to make up for deficiencies in the language.
On the topic of import, mixin imports are something that I believe will eventually become a great deal more popular than they are today. First, there's the advantage of being able to use a language/syntax more appropriate for the task at hand. For example, for things that output html you could just import mixin a raw html file. But the real advantage is that you can still do compile-time processing on this. Plug in an xml parser, or something like pegged, and you can now extend Html and generate D code for it. For example, if you have something like runat="server" on an element, just like in ASP.net you could create a serverside element for this and manipulate it. Because you know exactly which parts are static and which are dynamic, you could (at compile time) create buffers containing the static portions to prevent having to copy things many times. Unlike other languages, there would be no performance hit to doing this because it's all done at compile time. This is just one example. Another one would be automatically creating bindings for a scripting language, or even automatically creating bindings for a C header file.
Oh yea, definitely. I'm already using HTML mixin imports for the little bit of sever-side web stuff I've started playing around with in D.
Mar 21 2012
prev sibling parent reply "Adam D. Ruppe" <destructionator gmail.com> writes:
On Wednesday, 21 March 2012 at 21:01:10 UTC, Kapps wrote:
 On the topic of import, mixin imports are something that I 
 believe will eventually become a great deal more popular than 
 they are today.
I use a *lot* of import() (one of my work projects imports() about 140 files!) but I fairly rarely use mixin with it. What I love about it is simply having a one-piece executable. All your default data is right there. Deployment is easy. If replacement files exist at runtime, you might use them, but if not, you always have a default built in! It is much easier than external resource files, and being able to process is a nice win.
Mar 21 2012
next sibling parent "Tove" <tove fransson.se> writes:
 On Wednesday, 21 March 2012 at 21:01:10 UTC, Kapps wrote:
 On the topic of import, mixin imports are something that I 
 believe will eventually become a great deal more popular than 
 they are today.
Definitely.... mixin imports and ctfe gets my 3 votes!
Mar 21 2012
prev sibling parent reply "Nick Sabalausky" <a a.a> writes:
"Adam D. Ruppe" <destructionator gmail.com> wrote in message 
news:vuegxcpcbsefvmjdqesp forum.dlang.org...
 On Wednesday, 21 March 2012 at 21:01:10 UTC, Kapps wrote:
 On the topic of import, mixin imports are something that I believe will 
 eventually become a great deal more popular than they are today.
I use a *lot* of import() (one of my work projects imports() about 140 files!) but I fairly rarely use mixin with it. What I love about it is simply having a one-piece executable. All your default data is right there. Deployment is easy. If replacement files exist at runtime, you might use them, but if not, you always have a default built in! It is much easier than external resource files, and being able to process is a nice win.
Yea. It especially would have been great back when I was doing GBA homebrew. With that stuff having been in C/C++, just to include *any* real binary data, we had to use external tools (as a pre-compilation build step) to convert the binary data files into C files that contained "char myData[] = [0x01, 0x5B, 0xFF, 0x80, ...];" (or something like that - my C muscles have atrophied). And then later on someone made sort of a mini file-system where you could add data to a ROM image and then query/access it from your code in the ROM. If we had been doing things in D, we could all have just typed import("myData.dat") and been *done*. None of those extra tools or MIME-like-bloating^H^H^H^H^H^H^H^Hencoding bullshit.
Mar 21 2012
parent reply "Adam D. Ruppe" <destructionator gmail.com> writes:
On Thursday, 22 March 2012 at 04:49:24 UTC, Nick Sabalausky wrote:
 And then later on someone made sort of a mini file-system where 
 you could add data to a ROM
 image and then query/access it from your code
Now, this reminds me, what if you want to access the compile time files from runtime? For instance, one of my projects lets you include other files in the html. (Something I actually don't like, but it is an easy crutch.) You can also replace these at runtime, so the other team members can change stuff without access to the compiler. Here's what I ended up writing: // filesystem alternatives... string getFile(string name)() { if(std.file.exists(dir ~ name)) return std.file.readText(dir ~ name); else return import(name); } // runtime fetching string getIncludeFile(string name) { enum manifest = ["file1.html", "file2.html", ......]; string manifests() { string cases; foreach(f; manifest) cases ~= "case \""~f~"\": return getFile!(\""~f~"\");"; return cases; } switch(name) { default: assert(0, name); mixin(manifests()); } } I'm a bit disappointed that I needed a list of files duplicated there. With import(), if it is in the import directory, it just works, but then the name must be known at compile time. This is the best I have so far... and i like it, but it isn't quite ideal yet.
Mar 22 2012
parent "Nick Sabalausky" <a a.a> writes:
"Adam D. Ruppe" <destructionator gmail.com> wrote in message 
news:oyqxvngsgjfmrlrwhohf forum.dlang.org...
 On Thursday, 22 March 2012 at 04:49:24 UTC, Nick Sabalausky wrote:
 And then later on someone made sort of a mini file-system where you could 
 add data to a ROM
 image and then query/access it from your code
Now, this reminds me, what if you want to access the compile time files from runtime? For instance, one of my projects lets you include other files in the html. (Something I actually don't like, but it is an easy crutch.) You can also replace these at runtime, so the other team members can change stuff without access to the compiler. Here's what I ended up writing: // filesystem alternatives... string getFile(string name)() { if(std.file.exists(dir ~ name)) return std.file.readText(dir ~ name); else return import(name); } // runtime fetching string getIncludeFile(string name) { enum manifest = ["file1.html", "file2.html", ......]; string manifests() { string cases; foreach(f; manifest) cases ~= "case \""~f~"\": return getFile!(\""~f~"\");"; return cases; } switch(name) { default: assert(0, name); mixin(manifests()); } } I'm a bit disappointed that I needed a list of files duplicated there. With import(), if it is in the import directory, it just works, but then the name must be known at compile time. This is the best I have so far... and i like it, but it isn't quite ideal yet.
Clever idea, I like it.
Mar 22 2012
prev sibling parent reply "Nick Sabalausky" <a a.a> writes:
"Adam D. Ruppe" <destructionator gmail.com> wrote in message 
news:fuxnqnmrskrfqqmhdjws forum.dlang.org...
 Nested functions, auto, and scope guards were the
 three killers in the pre-D1 that roped me in. And
 they rok, oh they rok. But that is "likely success" :)
The main thing that grabbed me in the pre-D1 days was the lack of header files in a non-VM systems langauge. Everything else was icing on the cake. Although, while it wasn't a major selling point in and of itself, the ability to put underscores in numeric literals *really* helped tell me, "Now *this* is a language that's very well thought out and values pragmatism." And *that* was the other main thing about D that grabbed me.
 One that surprised me personally though is import. Indeed,
 import is why I passed over D the first time I looked
 at it (in 2004 IIRC) - I saw "import" and said "gah
 include is fine, eff this Java like poo..
Heh, really? I started getting tired of C++ around 2002-ish, and around the same time, some college courses I was taking were introducing me to Java. I was never a fan of Java overall, and there's a lot about it I always *hated*, but the lack of header files was one thing that *did* really impress me about Java (the other things were reference semantics for classes and GC). It was enough that, at the time, I considered it a reasonable alternative to C++ for things that didn't need number crunching, high
Mar 21 2012
next sibling parent reply "Adam D. Ruppe" <destructionator gmail.com> writes:
On Wednesday, 21 March 2012 at 19:11:08 UTC, Nick Sabalausky 
wrote:
 Although, while it wasn't a major selling point in and of 
 itself, the ability to put underscores in numeric literals
Aye, that's a nice touch.
 Heh, really?
Oh yes, I was a staunch defender of C++ for a while. "garbage collection? gah apparently you don't know how to use RAII" "header files? more like good thing, it's called a clean interface" BTW one thing I do kinda like is how you can group member functions however you want in C++. For example, in the dmd source, you have special features in separate files, with all the functions still virtual from the header. void InvariantDeclaration::toJsonBuffer(OutBuffer *buf) { } void DtorDeclaration::toJsonBuffer(OutBuffer *buf) { } void StaticCtorDeclaration::toJsonBuffer(OutBuffer *buf) { } etc. That's actually pretty cool. I like that kind of organization. But, eh, D pwns C++ in so many ways that while I still like C++, I'm no longer in the camp of "c++ is obviously great and totally sufficient and if you don't see it, you must be some kind of idiot" like I was for a while.
Mar 21 2012
parent "Nick Sabalausky" <a a.a> writes:
"Adam D. Ruppe" <destructionator gmail.com> wrote in message 
news:utkgtgcgguydxrabkily forum.dlang.org...
 But, eh, D pwns C++ in so many ways that while I still
 like C++, I'm no longer in the camp of "c++ is obviously
 great and totally sufficient and if you don't see it,
 you must be some kind of idiot" like I was for a while.
Heh, yea. I think in a way that's kind of the problem with C++: It can be technically considered "sufficient"...but that's it - it's *merely* sufficient. "Why have a Pop-Tart(tm) when you can have a warm delicious Pillsbury(tm) Toaster Strudel(tm)?" ;)
Mar 21 2012
prev sibling parent "Jesse Phillips" <Jessekphillips+D gmail.com> writes:
On Wednesday, 21 March 2012 at 19:11:08 UTC, Nick Sabalausky 
wrote:

 Although, while it wasn't a major selling point in and of 
 itself, the
 ability to put underscores in numeric literals *really* helped 
 tell me, "Now
 *this* is a language that's very well thought out and values 
 pragmatism."
 And *that* was the other main thing about D that grabbed me.
I take that feature for granted! Try using it in other languages and am always taken back on what it is complaining about, its just a stupid integer literal... oh.
Mar 22 2012
prev sibling next sibling parent "bearophile" <bearophileHUGS lycos.com> writes:
 There are a few features of D that turned out to be successful, 
 in spite of them being seemingly unimportant or diverging from 
 related consecrated approaches.

 What are your faves?
After thinking some time about this, I can't find one of them :-) I see many useful/successful features in D, but none of them seemed unimportant at first to me. Maybe I am just strange, but very little of syntax and semantics of a language is unimportant. In languages even unused features (C trigraphs?) sometimes bite your bum, so they become important, with negative value. Bye, bearophile
Mar 20 2012
prev sibling next sibling parent reply "Rene Zwanenburg" <renezwanenburg gmail.com> writes:
On Tuesday, 20 March 2012 at 19:02:16 UTC, Andrei Alexandrescu 
wrote:
 I plan to give a talk at Lang.NEXT 
 (http://channel9.msdn.com/Events/Lang-NEXT/Lang-NEXT-2012) with 
 the subject above. There are a few features of D that turned 
 out to be successful, in spite of them being seemingly 
 unimportant or diverging from related consecrated approaches.

 What are your faves? I have a few in mind, but wouldn't want to 
 influence answers.


 Thanks,

 Andrei
I've seen most of D's cool features mentioned, but I believe nobody mentioned mixins yet. Mixins are messy to maintain, but together with CTFE they can be used to create some really neat code if used properly. One of the first things I wrote while learning D is a vector class. In GLSL vectors can be 'swizzled', for example: vec3(1, 2, 3).zyx == vec3(3, 2, 1); Swizzles are often useful in graphics or physics code. I don't know of any non-shading language that allows me to use swizzle syntax. As the following code shows, it's quite easy to do in D: module main; import std.stdio; import std.process; import std.conv; int main(string[] argv) { alias Vec!4 Vec4; Vec4 v = Vec4(1, 2, 3, 4); writeln(v.bgra); // Prints Vec!(4)([3, 2, 1, 4]) writeln(v.rg); // Prints Vec!(2)([1, 2]) return 0; } private immutable (char[][]) elementNames = [['x', 'y', 'z', 'w'], ['r', 'g', 'b', 'a'], ['s', 't', 'p', 'q']]; struct Vec(size_t size) { alias size Size; mixin(generateConstructor(Size)); mixin(generateProperties(Size)); auto opDispatch(string s)() { mixin(generateSwizzle(s)); } float v[Size]; } private string generateConstructor(size_t size) { string constructorParams; string constructorBody; foreach(i; 0..size) { string paramName = "v" ~ to!string(i); constructorParams ~= "float " ~ paramName ~ "=0,"; constructorBody ~= "v[" ~ to!string(i) ~ "] = " ~ paramName ~ ";"; } return "this(" ~ constructorParams[0..$-1] ~ "){" ~ constructorBody ~ "}"; } private string generateProperties(size_t size) { string props; foreach(names; elementNames) { foreach(i, name; names[0..size]) { props ~= " property float " ~ name ~ "() const { return v[" ~ to!string(i) ~ "]; }"; props ~= " property void " ~ name ~ "(float f) { v[" ~ to!string(i) ~ "] = f; }"; } } return props; } private string generateSwizzle(string elements) { string swizzleImpl = "return Vec!" ~ to!string(elements.length) ~ "("; foreach(e; elements) { swizzleImpl ~= e ~ ","; } return swizzleImpl[0..$-1] ~ ");"; }
Mar 20 2012
parent "Rene Zwanenburg" <renezwanenburg gmail.com> writes:
And there goes the formatting, here's a pastebin version:
http://pastebin.com/dHdiG0ce

On Wednesday, 21 March 2012 at 01:41:27 UTC, Rene Zwanenburg 
wrote:
 On Tuesday, 20 March 2012 at 19:02:16 UTC, Andrei Alexandrescu 
 wrote:
 I plan to give a talk at Lang.NEXT 
 (http://channel9.msdn.com/Events/Lang-NEXT/Lang-NEXT-2012) 
 with the subject above. There are a few features of D that 
 turned out to be successful, in spite of them being seemingly 
 unimportant or diverging from related consecrated approaches.

 What are your faves? I have a few in mind, but wouldn't want 
 to influence answers.


 Thanks,

 Andrei
I've seen most of D's cool features mentioned, but I believe nobody mentioned mixins yet. Mixins are messy to maintain, but together with CTFE they can be used to create some really neat code if used properly. One of the first things I wrote while learning D is a vector class. In GLSL vectors can be 'swizzled', for example: vec3(1, 2, 3).zyx == vec3(3, 2, 1); Swizzles are often useful in graphics or physics code. I don't know of any non-shading language that allows me to use swizzle syntax. As the following code shows, it's quite easy to do in D: module main; import std.stdio; import std.process; import std.conv; int main(string[] argv) { alias Vec!4 Vec4; Vec4 v = Vec4(1, 2, 3, 4); writeln(v.bgra); // Prints Vec!(4)([3, 2, 1, 4]) writeln(v.rg); // Prints Vec!(2)([1, 2]) return 0; } private immutable (char[][]) elementNames = [['x', 'y', 'z', 'w'], ['r', 'g', 'b', 'a'], ['s', 't', 'p', 'q']]; struct Vec(size_t size) { alias size Size; mixin(generateConstructor(Size)); mixin(generateProperties(Size)); auto opDispatch(string s)() { mixin(generateSwizzle(s)); } float v[Size]; } private string generateConstructor(size_t size) { string constructorParams; string constructorBody; foreach(i; 0..size) { string paramName = "v" ~ to!string(i); constructorParams ~= "float " ~ paramName ~ "=0,"; constructorBody ~= "v[" ~ to!string(i) ~ "] = " ~ paramName ~ ";"; } return "this(" ~ constructorParams[0..$-1] ~ "){" ~ constructorBody ~ "}"; } private string generateProperties(size_t size) { string props; foreach(names; elementNames) { foreach(i, name; names[0..size]) { props ~= " property float " ~ name ~ "() const { return v[" ~ to!string(i) ~ "]; }"; props ~= " property void " ~ name ~ "(float f) { v[" ~ to!string(i) ~ "] = f; }"; } } return props; } private string generateSwizzle(string elements) { string swizzleImpl = "return Vec!" ~ to!string(elements.length) ~ "("; foreach(e; elements) { swizzleImpl ~= e ~ ","; } return swizzleImpl[0..$-1] ~ ");"; }
Mar 20 2012
prev sibling next sibling parent "Jay Norwood" <jayn prismnet.com> writes:
On Tuesday, 20 March 2012 at 19:02:16 UTC, Andrei Alexandrescu 
wrote:
 What are your faves? I have a few in mind, but wouldn't want to 
 influence answers.


 Thanks,

 Andrei
I'll have to say its whatever it is ( and I don't know what it is) that enabled that std.parallelism code to be written with such clean syntax and operate with such low overhead. You can explain what enabled both, I'm sure. Also I'm happy that the array operation syntax is included in the language.
Mar 20 2012
prev sibling next sibling parent "Joshua Niehus" <jm.niehus gmail.com> writes:
On Tuesday, 20 March 2012 at 19:02:16 UTC, Andrei Alexandrescu 
wrote:
 What are your faves? I have a few in mind, but wouldn't want to 
 influence answers.

 Thanks,

 Andrei
1) inferred types (auto) 2) slices 3) whole > sum(mixin, opDispatch, static if)
Mar 20 2012
prev sibling next sibling parent "so" <so so.so> writes:
On Tuesday, 20 March 2012 at 19:02:16 UTC, Andrei Alexandrescu
wrote:
 I plan to give a talk at Lang.NEXT 
 (http://channel9.msdn.com/Events/Lang-NEXT/Lang-NEXT-2012) with 
 the subject above. There are a few features of D that turned 
 out to be successful, in spite of them being seemingly 
 unimportant or diverging from related consecrated approaches.

 What are your faves? I have a few in mind, but wouldn't want to 
 influence answers.


 Thanks,

 Andrei
. ctfe - mixin . explain them why templates without "static if" is like a language without "if". . string, float and anything that matters can be used as template parameters.
Mar 21 2012
prev sibling next sibling parent "Masahiro Nakagawa" <repeatedly gmail.com> writes:
On Tuesday, 20 March 2012 at 19:02:16 UTC, Andrei Alexandrescu 
wrote:
 I plan to give a talk at Lang.NEXT 
 (http://channel9.msdn.com/Events/Lang-NEXT/Lang-NEXT-2012) with 
 the subject above. There are a few features of D that turned 
 out to be successful, in spite of them being seemingly 
 unimportant or diverging from related consecrated approaches.

 What are your faves? I have a few in mind, but wouldn't want to 
 influence answers.


 Thanks,

 Andrei
1. Compile time reflection This feature enables MessagePack to (de)serialize existing class and struct :) 2. Template friends Easy syntax, static if(and is), alias, mixin and other features are very useful. An essential parts ingredient to write D program. 3. Built-in array and slice I heavily use this feature in many cases. Template engine, complex computation and network programming :) Masahiro
Mar 21 2012
prev sibling next sibling parent reply "Steven Schveighoffer" <schveiguy yahoo.com> writes:
On Tue, 20 Mar 2012 15:02:15 -0400, Andrei Alexandrescu  
<SeeWebsiteForEmail erdani.org> wrote:

 I plan to give a talk at Lang.NEXT  
 (http://channel9.msdn.com/Events/Lang-NEXT/Lang-NEXT-2012) with the  
 subject above. There are a few features of D that turned out to be  
 successful, in spite of them being seemingly unimportant or diverging  
 from related consecrated approaches.

 What are your faves? I have a few in mind, but wouldn't want to  
 influence answers.
The two that I would cite are auto and slice syntax. I see others have chimed in with the same two. These were two features that did *not* attract me to D, but I found them to be two of my favorites, and ones I miss the most when writing in other languages. If I had to pick a third, I'd say the omitting parentheses for 1-arg templates was something I didn't expect to be as great as it is. Possibly one other thing I didn't expect to be so nice was shared (more specifically, the implications when something is *not* shared). That enabled weak-pure functions which I think are going to be a HUGE feature for D. -Steve
Mar 21 2012
parent reply Walter Bright <newshound2 digitalmars.com> writes:
On 3/21/2012 7:45 AM, Steven Schveighoffer wrote:
 If I had to pick a third, I'd say the omitting parentheses for 1-arg templates
 was something I didn't expect to be as great as it is.
Yes, Andrei was the lone advocate of that for a while. Everyone else pooh-poohed it, including me.
Mar 21 2012
parent Andrei Alexandrescu <SeeWebsiteForEmail erdani.org> writes:
On 3/21/12 12:26 PM, Walter Bright wrote:
 On 3/21/2012 7:45 AM, Steven Schveighoffer wrote:
 If I had to pick a third, I'd say the omitting parentheses for 1-arg
 templates
 was something I didn't expect to be as great as it is.
Yes, Andrei was the lone advocate of that for a while. Everyone else pooh-poohed it, including me.
I appreciate you implemented it in spite of not finding it compelling. Andrei
Mar 21 2012
prev sibling next sibling parent "pillsy" <pillsbury+dlist gmail.com> writes:
On Tuesday, 20 March 2012 at 19:02:16 UTC, Andrei Alexandrescu 
wrote:

 There are a few features of D that turned out to be successful, 
 in spite of them being seemingly unimportant or diverging from 
 related consecrated approaches.
 What are your faves? I have a few in mind, but wouldn't want to 
 influence answers.
I know people have said all of these already, but I still want to vote for them, because they're so useful, and I routinely find myself wishing I had them in other languages. 1. Array slices. These allow for a lot of gains from structure sharing and "flyweighting"; safe structure sharing is one of the potential big wins from GC, but in most languages with GC it's tricky to share structure that's in arrays, leading to a lot of extra space overhead for pointers and worse cache behavior due to excessive scattering of objects around the heap. 2. Scope guard. At first I thought it was a neat little curiosity, but it makes it so easy to write and (more importantly) *read* error handling code that, whenever I use D, I find myself thinking about and dealing with potential failure modes that I would gloss over in another language. 3. Template syntax. When I first saw that it used an infix '!' of all things, and that the parentheses were optional, I thought it was the dumbest syntax ever. In practice, though, it's so much better than C++'s <> disaster that it's just not funny. A bunch of other features, like type inference, I totally expected to be extremely useful. The way auto lets you work with objects that have unutterable types is pretty cool, though I picked that up from the C++11 materials I've seen. They really need the feature to make the new lambdas work. Cheers, Pillsy
Mar 21 2012
prev sibling next sibling parent "F i L" <witte2008 gmail.com> writes:
Another feature I like a lot about D, is it's approach to nested 
classes. I'm not sure how it compares to other languages, but in 

don't have access to their containing class's variables. D's 
approach is much more logical, and works great for simple state 
systems:

   abstract class Actor {
     interface State {
       void update();
     }
     State state;
     final void update() {
       assert(state, "State is null");
       state.update();
     }
   }

   class Fighter : Actor {
     Idle : State {
       void update() {
         punch(); // can punch automatically
       }
     }
     Idle idleState = new Idle();
     this() {
       state = idleState;
     }
     void punch() { ... }
   }


constructor and manually manage the reference. It's a small 
thing, but considering referencing the container class is a core 
mechanic of any Stated object, it's a pain having to rewrite it, 
while D just works.
Mar 21 2012
prev sibling next sibling parent reply "F i L" <witte2008 gmail.com> writes:
And for my third favorite (in no order), I like custom 
allocators/deallocators. They're nice for creating "invisible" 
memory pools:

   static class Pool(T, uint size = 100) {
     static T[size] pool;
     static void* alloc() { ... }
     static void free(void* p) { ... }
   }

   mixin template UsePool(T, uint size = 100) {
     new(uint s) {
       return Pool!(T, size).alloc();
     }
     delete(void* p) {
       Pool!(T, size).free(p);
     }
   }

   class Test {
     mixin UsePool!(Test, 50);
   }

then later in you code, you can just instantiate Test like any 
other object:

   auto t = new Test();

But if instances of Test are often created/released the 
performance is much better. Or you can wired it up so that you 
can pass custom Pools (overriding a default):

   auto t = new(CustomPool) Test();
Mar 21 2012
next sibling parent reply Dmitry Olshansky <dmitry.olsh gmail.com> writes:
On 21.03.2012 21:14, F i L wrote:
 And for my third favorite (in no order), I like custom
 allocators/deallocators. They're nice for creating "invisible" memory
 pools:
Sorry to spoil the excitement, but aren't they deprecated? [snip] -- Dmitry Olshansky
Mar 21 2012
parent reply "F i L" <witte2008 gmail.com> writes:
On Wednesday, 21 March 2012 at 17:16:55 UTC, Dmitry Olshansky 
wrote:
 On 21.03.2012 21:14, F i L wrote:
 And for my third favorite (in no order), I like custom
 allocators/deallocators. They're nice for creating "invisible" 
 memory
 pools:
Sorry to spoil the excitement, but aren't they deprecated? [snip]
Come on, really? What's the reason for this? I did here about delete being depreciated, though I guess I didn't make the connection. Why is delete being removed anyways? I really liked this ability, and I hope that it doesn't completely disappear, even if it's only sugar.
Mar 21 2012
parent "Nick Sabalausky" <a a.a> writes:
"F i L" <witte2008 gmail.com> wrote in message 
news:fnlcdpyemasuaomabxxl forum.dlang.org...
 On Wednesday, 21 March 2012 at 17:16:55 UTC, Dmitry Olshansky wrote:
 On 21.03.2012 21:14, F i L wrote:
 And for my third favorite (in no order), I like custom
 allocators/deallocators. They're nice for creating "invisible" memory
 pools:
Sorry to spoil the excitement, but aren't they deprecated? [snip]
Come on, really? What's the reason for this? I did here about delete being depreciated, though I guess I didn't make the connection. Why is delete being removed anyways? I really liked this ability, and I hope that it doesn't completely disappear, even if it's only sugar.
There's a new custom allocator system being worked on. And there's already emplace, which (I imagine) is a key component of it.
Mar 21 2012
prev sibling parent reply Andrei Alexandrescu <SeeWebsiteForEmail erdani.org> writes:
On 3/21/12 12:14 PM, F i L wrote:
 And for my third favorite (in no order), I like custom
 allocators/deallocators.
They don't exist anymore. Andrei
Mar 21 2012
parent deadalnix <deadalnix gmail.com> writes:
Le 21/03/2012 19:32, Andrei Alexandrescu a écrit :
 On 3/21/12 12:14 PM, F i L wrote:
 And for my third favorite (in no order), I like custom
 allocators/deallocators.
They don't exist anymore. Andrei
And we are waiting for the replacement !
Mar 21 2012
prev sibling next sibling parent reply Andrei Alexandrescu <SeeWebsiteForEmail erdani.org> writes:
On 3/20/12 2:02 PM, Andrei Alexandrescu wrote:
 I plan to give a talk at Lang.NEXT
 (http://channel9.msdn.com/Events/Lang-NEXT/Lang-NEXT-2012) with the
 subject above. There are a few features of D that turned out to be
 successful, in spite of them being seemingly unimportant or diverging
 from related consecrated approaches.

 What are your faves? I have a few in mind, but wouldn't want to
 influence answers.
It's official: http://channel9.msdn.com/Events/Lang-NEXT/Lang-NEXT-2012/Three-Unlikely-Successful-Features-of-D Andrei
Mar 21 2012
parent Andrej Mitrovic <andrej.mitrovich gmail.com> writes:
On 3/21/12, Andrei Alexandrescu <SeeWebsiteForEmail erdani.org> wrote:
 It's official:
 http://channel9.msdn.com/Events/Lang-NEXT/Lang-NEXT-2012/Three-Unlikely-Successful-Features-of-D
"Go In Three Easy Pieces" followed by "Three Unlikely Successful Features of D". Conspiracy? :P
Mar 21 2012
prev sibling next sibling parent Andrej Mitrovic <andrej.mitrovich gmail.com> writes:
On 3/20/12, Andrei Alexandrescu <SeeWebsiteForEmail erdani.org> wrote:
 What are your faves? I have a few in mind, but wouldn't want to
 influence answers.
Hey here's a big one: Phobos. Or maybe both Phobos and D2. I don't have the numbers but I think quite a few people thought D was going to die because of a backwards-incompatible change of a language, and the fact that Tango was missing from D2 (it seems people avoided using Phobos in D1 days).
Mar 21 2012
prev sibling parent reply "Matt Peterson" <ricochet1k gmail.com> writes:
On Tuesday, 20 March 2012 at 19:02:16 UTC, Andrei Alexandrescu 
wrote:
 I plan to give a talk at Lang.NEXT 
 (http://channel9.msdn.com/Events/Lang-NEXT/Lang-NEXT-2012) with 
 the subject above. There are a few features of D that turned 
 out to be successful, in spite of them being seemingly 
 unimportant or diverging from related consecrated approaches.

 What are your faves? I have a few in mind, but wouldn't want to 
 influence answers.


 Thanks,

 Andrei
It isn't mainline yet, but UFCS from git has made working with std.algorithm much nicer. Instead of something like array(filter!"a > 0"(map!((a){return somefunc(a);})(data))) where you can quickly drown in parenthesis and the order seems somewhat backwards, you can use data.map!((a){return somefunc(a);}).filter!"a > 0".array
Mar 22 2012
parent reply "bearophile" <bearophileHUGS lycos.com> writes:
Matt Peterson:

 It isn't mainline yet, but UFCS from git has made working with 
 std.algorithm much nicer. Instead of something like 
 array(filter!"a > 0"(map!((a){return somefunc(a);})(data))) 
 where you can quickly drown in parenthesis and the order seems 
 somewhat backwards, you can use data.map!((a){return 
 somefunc(a);}).filter!"a > 0".array
I suggest to compile all your D2 code with -wi (or -w) and -property. And one bug of UFCS will be probably fixed by Hara (http://d.puremagic.com/issues/show_bug.cgi?id=7722 ), so map and filter will require an ending () (I have closed my http://d.puremagic.com/issues/show_bug.cgi?id=7723 ). So your last line is better written like this: data.map!somefunc().filter!q{a > 0}().array() This is indeed a significant improvement in D syntax for functional-style code, because this reduced nesting a lot, making such code significantly more readable. Bye, bearophile
Mar 22 2012
parent "Matt Peterson" <ricochet1k gmail.com> writes:
On Friday, 23 March 2012 at 04:07:53 UTC, bearophile wrote:
 I suggest to compile all your D2 code with -wi (or -w) and 
 -property.
Already using -w, and I thought I was using -property. I am now, thanks.
 And one bug of UFCS will be probably fixed by Hara 
 (http://d.puremagic.com/issues/show_bug.cgi?id=7722 ), so map 
 and filter will require an ending () (I have closed my 
 http://d.puremagic.com/issues/show_bug.cgi?id=7723 ).

 So your last line is better written like this:

 data.map!somefunc().filter!q{a > 0}().array()
Yes, I agree. I had to work around a bug a few months ago that using map!some_nested_func wouldn't compile, and I still haven't gotten out of the habit of using delegate literals for all but the simplest maps.
Mar 23 2012