October 15, 2019
On Tuesday, 15 October 2019 at 16:39:47 UTC, Paul Backus wrote:
> [snip]
>
> The one advantage C++ concepts have over D's template predicates is that they're transparent to the compiler. As a result, the compiler is able to determine a partial order on template constraints [1], and use that order to resolve overloads (just like D does with regular function overloads [2]). D can't do this, so we're stuck writing awkward things like this:
>
> auto myAlgorithm(R)(R r) if (isInputRange!R && !isRandomAccessRange!R) { ... }
> auto myAlgorithm(R)(R r) if (isRandomAccessRange!R) { ... }
>
> .[snip]

That's an interesting point. The problem is the template constraints aren't considered for the overloading, right? However, if they were expressed as in something like below

auto myAlgorithm(T)(InputRange!T r) { ... }
auto myAlgorithm(T)(RandomAccessRange!T r) { ... }

then I presume that it wouldn't be an issue. You might find DIP 1023 [1] interesting. One of the purposes of DIP1023 is to allow for template aliases to be used like types in functions. One of the arguments against DIP1023 is that you can simply use template constraints to do the same thing. However, your example shows that template constraints might get complicated in some instances.

[1] https://github.com/dlang/DIPs/blob/bf5157d3dc29a591826e22d188448fbc04ca81b2/DIPs/DIP1023.md


October 15, 2019
On Tuesday, 15 October 2019 at 17:50:52 UTC, jmh530 wrote:
> On Tuesday, 15 October 2019 at 16:39:47 UTC, Paul Backus wrote:
>> [snip]
>>
>> The one advantage C++ concepts have over D's template predicates is that they're transparent to the compiler. As a result, the compiler is able to determine a partial order on template constraints [1], and use that order to resolve overloads (just like D does with regular function overloads [2]). D can't do this, so we're stuck writing awkward things like this:
>>
>> auto myAlgorithm(R)(R r) if (isInputRange!R && !isRandomAccessRange!R) { ... }
>> auto myAlgorithm(R)(R r) if (isRandomAccessRange!R) { ... }
>>
>> .[snip]
>
> That's an interesting point. The problem is the template constraints aren't considered for the overloading, right? However, if they were expressed as in something like below
>
> auto myAlgorithm(T)(InputRange!T r) { ... }
> auto myAlgorithm(T)(RandomAccessRange!T r) { ... }
>
> then I presume that it wouldn't be an issue.

You misunderstand.

The problem isn't that template constraints aren't considered for overloading--they are. It's that, if two overloads both have constraints that match, the compiler has no way of telling which one is "more specific".

In other words, if you pass an input range to the above overload set, it will satisfy *both* isInputRange and isRandomAccessRange, because all random access ranges are also input ranges, and you'll get an ambiguity error. Ideally, we would like the compiler to understand that isRandomAccessRange is "more specific" than isInputRange, and choose the correct overload without requiring any additional disambiguation.

Because templates are Turing-complete, it is undecidable, in the general case, whether one template predicate is "more specific" than another (i.e., whether A!T == true implies B!T == true for all T). So there's no way to have the compiler do what we want unless we replace template predicates like isInputRange with something else that the compiler can understand without needing to solve the halting problem.

Some possible solutions:
  - Designate a particular subset of templates--for example, those whose body
    consists of a single boolean expression--as "concepts", and add code in the
    compiler to analyze them.
  - Add C++-style concepts as a language construct distinct from templates.
  - Change predicates like isInputRange to return strings instead of boolean
    values, and use mixin to inject their expressions directly into template
    constraints without evaluating them first.
  - Add AST macros to D, and change predicates like isInputRange into macros
    that return unevaluated expressions instead of boolean values.
October 15, 2019
On Tuesday, 15 October 2019 at 18:39:44 UTC, Paul Backus wrote:
>   - Add AST macros to D, and change predicates like isInputRange into macros
>     that return unevaluated expressions instead of boolean values.

Not going to happen, walter had express numerous times that AST Macros are not going to be accepted.

- Alex
October 15, 2019
On Tuesday, 15 October 2019 at 18:52:24 UTC, 12345swordy wrote:
> On Tuesday, 15 October 2019 at 18:39:44 UTC, Paul Backus wrote:
>>   - Add AST macros to D, and change predicates like isInputRange into macros
>>     that return unevaluated expressions instead of boolean values.
>
> Not going to happen, walter had express numerous times that AST Macros are not going to be accepted.
>
> - Alex

Yes, I'm aware. It wasn't meant as a serious proposal, just an example.
October 15, 2019
On Tuesday, 15 October 2019 at 13:09:15 UTC, Mike Parker wrote:
> This thread is for general feedback and discussion regarding Átila's blog post on his vision for D's future.
>
> https://dlang.org/blog/2019/10/15/my-vision-of-ds-future/

While I agree mostly with the vision I feel that that roadmap for betterC has been left out. There is currently not any roadmap how to continue to improve betterC and "pay as you go".

betterC is a great step of embedded programming but libraries are lacking as well as the benefits of the built features like dynamic arrays and associative arrays. It would be a great benefit to port these features to a non GC environment as well.

Basically a vision for D to improve being a real systems programming language suitable for bare metal and embedded programming.
October 15, 2019
On Tuesday, 15 October 2019 at 18:39:44 UTC, Paul Backus wrote:
> [snip]
>
> You misunderstand.

I think I understood it, though perhaps I wasn't able to communicate myself as well as I tended.

So for instance, suppose we have

enum isSlice(T) = is(T: Slice!(U), U);
auto foo(T)(T m) if(isSlice!T) { /* ... */ }

and then we also add
enum isPackedUpperTriangularMatrix(T) = is(T: Slice!(StairsIterator!(U*, "-")), U);
auto foo(T)(T m) if(isPackedUpperTriangularMatrix!T) { /* ... */ }

this has the same problems you describe with input range and random access range. A packed upper triangular matrix should satisfy both.

DIP1023 addresses creating the alias
alias PackedUpperTriangularMatrix(T) = Slice!(StairsIterator!(T*, "-"));
and then enabling the ability to write
auto foo(T)(PackedUpperTriangularMatrix!T m) { }
without the current error.

Nothing would be stopping you from writing the equivalent of
auto foo(T)(Slice!T m) { }
as well.

That last version of foo taking a slice would be the equivalent of your input range version, while the second one would be the equivalent of random access range version. Unlike above, these examples are no longer using the template constraints. It is treating the aliases as types so the normal function overloading rules should apply.
October 16, 2019
Everything looks good in the article.
As others have said pay as you go D would be nice.

Something I am concerned about is no mention of a big push to get dmd into a good state for library usage. That is really missing if we want a first class IDE experience IMO.

That is not what I personally care about to the point of working on it actively. What I care about is Phobos v2 as H.S. Teoh mentioned.

If we were to do it today, very little would have changed in terms of language integration. We would still have isInputRange and friends which is quite frankly a code smell. Yes its great that we can do it 100% with the tools we have, but it is absolutely horrible for integration into the compiler (e.g. errors) and easily being understood for newbies in that part of a given library.

I don't want anyone else to go through what I did in 2012-2013'ish to learn ranges. We can do better. We are missing a concept here in the language (see Rust and Swift as evidence that there is is a trend to have something for this).

My solution was to replace e.g. isInputRange with signatures from ML, sadly DIP 1020 was a major stepping stone on this path. So I'm now in a state of figuring out the entire thing from scratch.

Thoughts?
October 16, 2019
On Tuesday, 15 October 2019 at 23:52:52 UTC, jmh530 wrote:
> DIP1023 addresses creating the alias
> alias PackedUpperTriangularMatrix(T) = Slice!(StairsIterator!(T*, "-"));
> and then enabling the ability to write
> auto foo(T)(PackedUpperTriangularMatrix!T m) { }
> without the current error.
>
> Nothing would be stopping you from writing the equivalent of
> auto foo(T)(Slice!T m) { }
> as well.
>
> That last version of foo taking a slice would be the equivalent of your input range version, while the second one would be the equivalent of random access range version. Unlike above, these examples are no longer using the template constraints. It is treating the aliases as types so the normal function overloading rules should apply.

This does not solve the ambiguity issue. If I write the equivalent code with the aliases expanded by hand, I get a compile-time error:

import std.stdio;

struct Outer(T) {}
struct Inner(T) {}

void fun(T)(Outer!(Inner!T) arg) { writeln("Outer!(Inner!T)"); }
void fun(T)(Outer!T arg) { writeln("Outer!T"); }

void main() {
    Outer!(Inner!int) x;
    fun(x); // Error: onlineapp.fun called with argument types [...] matches both:
}

https://run.dlang.io/is/pHPa89
October 16, 2019
On Tuesday, 15 October 2019 at 13:09:15 UTC, Mike Parker wrote:
> This thread is for general feedback and discussion regarding Átila's blog post on his vision for D's future.
>
> https://dlang.org/blog/2019/10/15/my-vision-of-ds-future/

The second paragraph of 'Make D the default implementation language' lacks an example for those who are not familiar with it. How can D, compared to its contenders, make the code 'automagically' callable from other languages? A reference to an existing library could do.

Regarding interop with C++, what are your thoughts on tools like Calypso? It supports most C++ features, including advanced stuff like template instantiation, and it seems to be under active development: https://github.com/Syniurge/Calypso

I understand the main motivation behind the interpreter is fast iteration times. Is the idea to have an interpreter that can run entire applications?

Overall this was an interesting read. It's nice to see the efforts that are being made to make D @safe by default.

October 16, 2019
On Wednesday, 16 October 2019 at 00:22:08 UTC, Paul Backus wrote:
> [snip]
>
> This does not solve the ambiguity issue. If I write the equivalent code with the aliases expanded by hand, I get a compile-time error:
> [snip]

Damn. What you have seems to make sense.

I made some example earlier today that seemed to work, but I'm not sure I saved it to see where I went wrong. I feel like I had an alias this in there somewhere, but can't seem to replicate it now...