March 20, 2012 Re: Three Unlikely Successful Features of D | ||||
---|---|---|---|---|
| ||||
Posted in reply to Nick Sabalausky | 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".
|
March 20, 2012 Re: Three Unlikely Successful Features of D | ||||
---|---|---|---|---|
| ||||
Posted in reply to Don | 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
|
March 20, 2012 Re: Three Unlikely Successful Features of D | ||||
---|---|---|---|---|
| ||||
Posted in reply to Nick Sabalausky | 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. |
March 21, 2012 Re: Three Unlikely Successful Features of D | ||||
---|---|---|---|---|
| ||||
Posted in reply to Andrei Alexandrescu | 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.) |
March 21, 2012 Re: Three Unlikely Successful Features of D | ||||
---|---|---|---|---|
| ||||
Posted in reply to Adam D. Ruppe | 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);
|
March 21, 2012 Re: Three Unlikely Successful Features of D | ||||
---|---|---|---|---|
| ||||
Posted in reply to Andrei Alexandrescu | > 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
|
March 21, 2012 Re: Three Unlikely Successful Features of D | ||||
---|---|---|---|---|
| ||||
Posted in reply to Walter Bright | "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. |
March 21, 2012 Re: Three Unlikely Successful Features of D | ||||
---|---|---|---|---|
| ||||
Posted in reply to Andrei Alexandrescu | 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] ~ ");"; } |
March 21, 2012 Re: Three Unlikely Successful Features of D | ||||
---|---|---|---|---|
| ||||
Posted in reply to Rene Zwanenburg | 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] ~ ");"; > } |
March 21, 2012 Re: Three Unlikely Successful Features of D | ||||
---|---|---|---|---|
| ||||
Posted in reply to H. S. Teoh | "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! :) |
Copyright © 1999-2021 by the D Language Foundation