March 21, 2012
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
March 21, 2012
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
March 21, 2012
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 {  ... }

March 21, 2012
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.
March 21, 2012
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 C# nested classes can be instanced individually and therefor 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() { ... }
  }

In C# I'd have to manually pass an Fighter reference to Idle's 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.
March 21, 2012
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


March 21, 2012
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.
March 21, 2012
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();

March 21, 2012
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".)
March 21, 2012
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