July 23, 2015
On 7/23/15 6:56 AM, "Marc =?UTF-8?B?U2Now7x0eiI=?= <schuetzm@gmx.net>" wrote:
>> Traits
>> ------
>> I think the ability to express an interface without buying into
>> inheritance is the right move. The alternative in D is specifying the
>> behavior as a template and verifying the contract in a unittest for
>> the type.
>
> Not only that, but Rust does so much more with traits, e.g. closures.
> They seem to be a simple, yet powerful concept, that a big part of the
> language is built on.
>
> http://blog.rust-lang.org/2015/05/11/traits.html
>
> On the other hand, it is extremely restrictive in contrast to `static
> if()` and template constraints. D's approach is a lot more expressive
> and - at least for me - intuitive.

Thanks for the link, good quick read to get the overview of Rust's traits feature. It's ingenious because it integrates static and dynamic dispatch.

For dynamic dispatch, traits are better than interfaces - more flexible, better informed. For static dispatch, they don't hold a candle to D's constraints. This is important because dynamic dispatch is more of a cut-and-dried matter, whereas static dispatch is where it's at.

For static dispatch I think D's template constraints are quite a lot better; they have a lot more power and offer a lot more to promise. They are an out-of-the-box solution that's a bit unwieldy because it's new enough to not yet have established idioms. In contrast, traits come from straight within the box.

From a language perspective, it is my belief that Design by Introspection (enabled collectively by template constraints, introspection, compile-time function evaluation, and static if) is the one crushing advantage that D has over any competitor. Things like range-based algorithms are good but easy to copy and adapt.

The faster we manage to get creative with Design by Introspection and describe it, systematize it, create compelling designs with it, the quicker will D win the minds and hearts of people.

There's a lot at stake here. An question often asked by would-be users is "What does D offer that's special?" or "What does D offer over language Xyz?" As we all know there are many answers to that. Maybe too many. Now I know what the answer is: Design by Introspection.


Andrei

July 23, 2015
On 7/23/15 5:07 AM, Walter Bright wrote:
> On 7/22/2015 11:47 PM, Jacob Carlborg wrote:
>> On 2015-07-22 20:47, simendsjo wrote:
>>
>>> Traits
>>> ------
>>> I think the ability to express an interface without buying into
>>> inheritance is the right move. The alternative in D is specifying the
>>> behavior as a template
>>
>> I completely agree and don't really like the approach D has
>> implemented template
>> constraints. Yeah I know, Andrei will destroy this :)
>
> Consider that template constraints can be arbitrarily complex, and can
> even check behavior, not just a list of function signatures ANDed
> together. Turns out many constraints in Phobos are of the form (A || B),
> not just (A && B).

Agreed. And that's just scratching the surface.

Serious question: how do you express in Rust that a type implements one trait or another, then figure out statically which?

>  >> and verifying the contract in a unittest for the type.
>
> I am a bit puzzled by the notion of shipping template code that has
> never been instantiated as being a positive thing. This has also turned
> up in the C++ static_if discussions.

This is easy to understand. Weeding out uncovered code during compilation is a central feature of C++ concepts. Admitting you actually never want to do that would be a major blow.


Andrei

July 23, 2015
On 2015-07-23 09:45, Joakim wrote:

> That's because it has its own top-level link in the sidebar, More
> libraries.  You could argue that's not the best description of dub, but
> it's certainly prominently placed.

Ah, right, I completely forgot about that. But one could expect the actual tool be available to download from dlang.org as well.

-- 
/Jacob Carlborg
July 23, 2015
On 2015-07-23 11:07, Walter Bright wrote:

> Consider that template constraints can be arbitrarily complex, and can
> even check behavior, not just a list of function signatures ANDed
> together. Turns out many constraints in Phobos are of the form (A || B),
> not just (A && B).

I know that is possible, but in most cases it's only a list of function signatures that is needed.

-- 
/Jacob Carlborg
July 23, 2015
On 2015-07-23 12:56, "Marc =?UTF-8?B?U2Now7x0eiI=?= <schuetzm@gmx.net>" wrote:

>> Expressions
>> -----------
>> This probably also falls in the "too late" category, but
>> statements-as-expressions is really nice. `auto a = if ...` <- why not?
>
> Generally I find this an elegant concept. But in Rust, it leads to the
> distinction between expressions terminated with `;` and those without,
> which in turn makes it necessary to use braces even if you have only one
> statement or expression. This is something that I dislike very much.

In Scala there's no problem. No semicolons are required a no braces.

-- 
/Jacob Carlborg
July 23, 2015
On Thursday, 23 July 2015 at 13:33:43 UTC, Adam D. Ruppe wrote:
> On Wednesday, 22 July 2015 at 21:04:57 UTC, simendsjo wrote:
>> :) The example was written to save space. I recon you understand what I mean.
>
> Yeah, but the if/else is one of the most useful examples of it, and is covered by ?:, so the whole thing becomes less compelling then.
>
> The other places where I've used it in languages that support it are little blocks crammed into a line and sometimes exception grabbing... but still, the value isn't that great.

If we had a clean sheet wouldn't it be better to have if return a value and ditch ternary?
July 23, 2015
On Thursday, 23 July 2015 at 14:15:30 UTC, Andrei Alexandrescu wrote:
> On 7/23/15 5:07 AM, Walter Bright wrote:
>> On 7/22/2015 11:47 PM, Jacob Carlborg wrote:
>>> On 2015-07-22 20:47, simendsjo wrote:
>>>
>>>> Traits
>>>> ------
>>>> I think the ability to express an interface without buying into
>>>> inheritance is the right move. The alternative in D is specifying the
>>>> behavior as a template
>>>
>>> I completely agree and don't really like the approach D has
>>> implemented template
>>> constraints. Yeah I know, Andrei will destroy this :)
>>
>> Consider that template constraints can be arbitrarily complex, and can
>> even check behavior, not just a list of function signatures ANDed
>> together. Turns out many constraints in Phobos are of the form (A || B),
>> not just (A && B).
>
> Agreed. And that's just scratching the surface.

It is definitely a big issue for designing more advanced generic libraries and one of my major issues with Rust but you need to realize that vast majority of application domain usage of such constraints is simply ensuring list of methods. You may be biased by too much standard library development ;)

At the same time one HUGE deal breaker with rust traits that rarely gets mentioned is the fact that they are both constraints and interfaces at the same time:

// this is template constraint, it will generate new `foo` symbol for each new T
fn foo <T : InputRange> (range : T)

// this use the very same trait definition but creates "fat pointer" on demand with simplistic dispatch table
fn foo (range : InputRange)

It kills all the necessity for hacks like RangeObject and is quite a salvation once you get to defining dynamic shared libraries with stable ABI.

This is probably my most loved feature of Rust.

> Serious question: how do you express in Rust that a type implements one trait or another, then figure out statically which?

As far as I understand current idiomatics, you don't. Code that tries to use functions that are not ensured by trait will simply not compile and for any complicated generic programming one is supposed to use macros. Rust does not have templates, only trait-restricted generics.

I find it terribly unproductive but it seems to appeal to certain developer mindset, primarily the ones that associate "templates" with "C++ templates".
July 23, 2015
On Wednesday, 22 July 2015 at 23:25:56 UTC, jmh530 wrote:
>
> If traits were deemed important enough to add to D, I would suggest just extending interfaces so that they have inheritance and can be easily used in template constraints.
>

I think I had a few misconception about D interfaces. The documentation does not say anything about interface inheritance, but it seems to work when I tried it. It definitely seems weird that this behavior isn't mentioned anywhere.

Also, the use of static* or final methods in the interface can allow default implementations of methods. This is something that can be done with Scala traits. I feel like this isn't documentated as well as it could be. A weirder thing is that when I tried to test that static and final methods could not overridden (which is allowed in Scala), it seemed like they were getting overridden. The tricky part is that I had been using something like final foo() { } instead of final void foo() { }. For some reason you can override the first, but not the second.

So really, I guess the D interfaces are more powerful than I had thought. Only downside is that they only work for classes.

* I feel like these also aren't particularly described well in the documentation either.
July 23, 2015
On Thursday, 23 July 2015 at 13:30:49 UTC, Andrei Alexandrescu wrote:
> I used to be quite jazzed about the everything-is-an-expression mantra, but it's not all great.
>
> 1. Inferring function return types when everything is an expression (i.e. last expression there is the return type) may yield WAT results.
>
> 2. Defining a result type for loops is awkward.
>
> At the end of the day everything-is-an-expression is natural for functional languages, but doesn't seem it makes a large difference to an imperative language.

It also works well for Ruby with its dynamic typing. Function return types don't matter, of course, and for loops you just use whatever the last executed expression happens to be.

Anyway, in D we have delegate literals, for the rare cases where it's useful.
July 23, 2015
"> On Wednesday, 22 July 2015 at 19:41:16 UTC, Jack Stouffer wrote:
On Wednesday, 22 July 2015 at 20:43:04 UTC, simendsjo wrote:
>> On Wednesday, 22 July 2015 at 18:47:33 UTC, simendsjo wrote:
>>> Expressions
>>> -----------
>>> This probably also falls in the "too late" category, but statements-as-expressions is really nice. `auto a = if ...` <- why not?
>>
>> Don't quite know what you mean here.
>
> When "everything" is an expressions, you can write things like
>     auto a = if(e) c else d;
>
> In D you have to write
>     type a = invalid_value;
>     if(e) a = c;
>     else  a = d;
>     assert(a != invalid_value);
>"

I frequently do things like this in D:

        auto good = ( true == true ) ? "true" : "false";

which looks a lot like your Rust example?  Is that not what you were looking for?