February 15, 2017
On 2/14/2017 9:28 PM, Adam D. Ruppe wrote:
> On Tuesday, 14 February 2017 at 20:46:17 UTC, Walter Bright wrote:
>> A further improvement in the documentation would be to add links to
>> isBidirectionalRange and hasLvalueElements.
>
> Kneel before your god!
>
> http://dpldocs.info/experimental-docs/std.algorithm.mutation.remove.1.html
>
> Take a look at this insane automatic cross referencing:
>
> http://dpldocs.info/experimental-docs/std.range.chain.html
>
>
> My ref thing still isn't perfect, but dpldocs is already streets ahead of
> anything dlang.org has to offer and continues to make bursts of strides.

That looks pretty sweet!
February 15, 2017
On 2017-02-14 17:25, Andrei Alexandrescu wrote:

> My recollection is past discussions got stalled because the approach is
> combinatorially bankrupt. How would one express the constraints of the
> functions above with simple named constraints? (Not rhetorical; please
> do provide an example if possible.)

It would obviously take a while for me to figure that out. Is not like I have a fully defined new language feature in my head.

I do see a possibility for a slightly improvement in a different area, in the example of "remove". If we look at the signature, without the constraints:

Range remove
(SwapStrategy s = SwapStrategy.stable, Range, Offset...)
(Range range, Offset offset)

Why isn't it possible to use "auto" when declaring a parameter with a default argument?

Range remove
(auto s = SwapStrategy.stable, Range, Offset...)
(Range range, Offset offset)

A minor improvement, but I also feel like it would lift an arbitrary limitation in the language.

Alternatively something that Swift supports:

Range remove
(SwapStrategy s = .stable, Range, Offset...)
(Range range, Offset offset)

The compiler knows that the type of "s" is SwapStrategy, therefore "stable" has to be a member of SwapStrategy. In the case of D, the leading dot has a different meaning so another syntax would be required. Unfortunately this has already been discussed and rejected by Walter.

> Before long there is an explosion in
> names ("BidirectionalWithLvalueElementsAndLength", ...). This is what
> has buried not one, but two concepts proposals for C++, leading to the
> current Concepts Lite proposal.

I don't see that as a problem, but I would rather name it "Removable" or something that does not include all the conditions in the name. But I imagine that a constraint would consist of a combination of declarations (like an interface) and boolean conditions.

Lets look it differently. For a regular (non-template) function with a user defined type (class, struct). If it was possible to define the type inline, would you? I hope that answer is no. Example:

Standard D:

struct Bar
{
    int a;
    int b;
}

void foo(Bar bar);

With inline user defined types:

void foo(struct { int a; int b; } bar);

Assuming the answer is no, why would it be any different for a template type? You can see all the template constraints for a type as a form of metatype.

> I haven't followed that lately but I
> remember it combines an engineering effort to reduce the number of names
> introduced (for the standard library only, which is a limitation) with
> adding support to Boolean logic (surprise, surprise) to the feature (see
> http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2015/n4377.pdf), the
> most recent proposal, which was rejected for C++17. Over time, C++
> concepts have moved from the broken combinatorially-bankrupt form slowly
> toward D's Boolean constraints (just with a gratuitously awkward
> notation). I presume they will be merged into the language when they'll
> have capabilities comparable to D's system.
>
> The question is, given this experience, do we want to move the opposite
> direction?

I haven't followed the C++ concepts lately either and not very closely at all so I don't feel I can comment on the C++ concepts. But if I recall correctly, you're "static if" proposal wasn't well received [1]. But now with "if constexpr" it looks like they're changing their minds.

[1] "The static if feature recently proposed for C++ [1, 2] is fundamentally flawed, and its adoption would be a disaster for the language" http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2013/n3613.pdf

-- 
/Jacob Carlborg
February 15, 2017
On 2017-02-14 17:25, Andrei Alexandrescu wrote:

> My recollection is past discussions got stalled because the approach is
> combinatorially bankrupt. How would one express the constraints of the
> functions above with simple named constraints? (Not rhetorical; please
> do provide an example if possible.) Before long there is an explosion in
> names ("BidirectionalWithLvalueElementsAndLength", ...).

Forgot to say that I don't think it's unreasonable to have a named constraint for each function (regardless if using only existing language features or adding something new). That way you can lift out the constraint separately from the function declaration. One way to make something complex less complex, is to split it up. It's not like you would have the complete source code of an application in a single file, that would be too much to read in one place (yes, there are other reasons to have multiple files). Same idea here.

-- 
/Jacob Carlborg
February 15, 2017
On 2017-02-15 09:19, Walter Bright wrote:
> On 2/14/2017 9:28 PM, Adam D. Ruppe wrote:
>> On Tuesday, 14 February 2017 at 20:46:17 UTC, Walter Bright wrote:
>>> A further improvement in the documentation would be to add links to
>>> isBidirectionalRange and hasLvalueElements.
>>
>> Kneel before your god!
>>
>> http://dpldocs.info/experimental-docs/std.algorithm.mutation.remove.1.html
>>
>>
>> Take a look at this insane automatic cross referencing:
>>
>> http://dpldocs.info/experimental-docs/std.range.chain.html
>>
>>
>> My ref thing still isn't perfect, but dpldocs is already streets ahead of
>> anything dlang.org has to offer and continues to make bursts of strides.
>
> That looks pretty sweet!

Doesn't help when reading the source code :(.

-- 
/Jacob Carlborg
February 15, 2017
On Wednesday, 15 February 2017 at 08:59:49 UTC, Jacob Carlborg wrote:
> On 2017-02-15 09:19, Walter Bright wrote:
>> On 2/14/2017 9:28 PM, Adam D. Ruppe wrote:
>>> On Tuesday, 14 February 2017 at 20:46:17 UTC, Walter Bright wrote:
>>>> A further improvement in the documentation would be to add links to
>>>> isBidirectionalRange and hasLvalueElements.
>>>
>>> Kneel before your god!
>>>
>>> http://dpldocs.info/experimental-docs/std.algorithm.mutation.remove.1.html
>>>
>>>
>>> Take a look at this insane automatic cross referencing:
>>>
>>> http://dpldocs.info/experimental-docs/std.range.chain.html
>>>
>>>
>>> My ref thing still isn't perfect, but dpldocs is already streets ahead of
>>> anything dlang.org has to offer and continues to make bursts of strides.
>>
>> That looks pretty sweet!
>
> Doesn't help when reading the source code :(.

Something akin to this would improve readability at least for me, also more DRY.

   isInputRange!(InputRange1)
&& isInputRange!(InputRange2)
&& hasSwappableElements!(InputRange1)
&& hasSwappableElements!(InputRange2)

  =>

every!(InputRange1, InputRange2).
satisfies!(isInputRange, hasSwappableElements);



template every(T...)
{
	template satisfies(U...)
	{
		enum satisfies = true;
	}
}

February 15, 2017
On Wednesday, 15 February 2017 at 09:22:14 UTC, Daniel N wrote:
> template every(T...)
> {
> 	template satisfies(U...)
> 	{
> 		enum satisfies = true;
> 	}
> }

(lunch-break => time to hack D!)

template every(T...)
{
  template satisfies(U...)
  {
    enum satisfies = {
      foreach(t; T)
        foreach(u; U)
	  if(!u!t)
            return false;
      return true;
    }();
  }
}

February 15, 2017
On Wednesday, 15 February 2017 at 01:09:59 UTC, Chris Wright wrote:
> Because now I have to look up the definition of fooConstraint and then I have to look up the definition of each element within it.

To be honest, I don't often look at function definitions for the template constraints, but this thread suggests that's the main reason others read source code. My opinion is that inlining the constraints greatly detracts from readability and provides little benefit in return. I also don't understand the problem with using simple names.
February 15, 2017
On Tuesday, 14 February 2017 at 16:25:17 UTC, Andrei Alexandrescu wrote:
> On 02/14/2017 10:49 AM, Jacob Carlborg wrote:
>> On 2017-02-14 15:37, Andrei Alexandrescu wrote:
>>
>>> How are they so,
>>
>> Example [1]. That signature spans 8 lines, it took me 10 seconds to find
>> the actual function name.
>
> Copying here to make things easier:
>
> Range remove
> (SwapStrategy s = SwapStrategy.stable, Range, Offset...)
> (Range range, Offset offset)
> if (s != SwapStrategy.stable
>     && isBidirectionalRange!Range
>     && hasLvalueElements!Range
>     && hasLength!Range
>     && Offset.length >= 1);
>
> The function name is on the first line. I think 10 seconds would be an exaggeration of an admittedly real issue.
>
>> Example [2], 5 lines.
>
> Copying here as well (reflowed for email):
>
> Tuple!(InputRange1, InputRange2)
> swapRanges(InputRange1, InputRange2)(InputRange1 r1, InputRange2 r2)
> if (isInputRange!(InputRange1) && isInputRange!(InputRange2)
>     && hasSwappableElements!(InputRange1)
>     && hasSwappableElements!(InputRange2)
>     && is(ElementType!(InputRange1) == ElementType!(InputRange2)));
>
> One immediate matter here is redundant parens, of which elimination would lead to the marginally more palatable:
>
> Tuple!(InputRange1, InputRange2)
> swapRanges(InputRange1, InputRange2)(InputRange1 r1, InputRange2 r2)
> if (isInputRange!InputRange1 && isInputRange!InputRange2
>     && hasSwappableElements!InputRange1
>     && hasSwappableElements!InputRange2
>     && is(ElementType!InputRange1 == ElementType!InputRange2));
>
>>> and what steps can we take to improve them. Could you
>>> please give a few examples on how to do things better? Thx! -- Andrei
>>
>> Well, I would prefer to have template constraints as its own entity in
>> the language not not just a bunch of boolean conditions. This has been
>> talked about before several times. Something like:
>>
>> constraint Foo
>> {
>>     void foo();
>> }
>>
>> void bar(T : Foo)(T t);
>
> My recollection is past discussions got stalled because the approach is combinatorially bankrupt. How would one express the constraints of the functions above with simple named constraints? (Not rhetorical; please do provide an example if possible.) Before long there is an explosion in names ("BidirectionalWithLvalueElementsAndLength", ...).

If I had my way, like so:

Tuple!(InputRange1, InputRange2)
swapRanges
(InputRange1: (InputRange, HasSwappableElements),
 InputRange2: (InputRange, HasSwappableElements))
(InputRange1 r1, InputRange2 r2)
if (is(ElementType!(InputRange1) == ElementType!(InputRange2)));

Assuming I'm still having my way, the above would result in the compiler telling me that given:

struct Foo {
     enum empty = false;
     enum front = 42;
}

If I tried to instantiate swapRanges!(Foo, Foo), I'd want to get something akin to:

error: foo.Foo does not satisfy InputRange: no function `popFront` for `foo.Foo`

For now I'm getting quite a bit of mileage from my concepts library.


Atila




February 15, 2017
On Tuesday, 14 February 2017 at 20:46:17 UTC, Walter Bright wrote:
> Range remove
[...]
> But there's another issue here. remove() has other overloads:
[...]
>
> Two constraints are common to all three, those are the only ones that actually need to be in the constraint. The others can go in the body under `static if`, as the user need not be concerned with them.
>
> This is a general issue in Phobos that too many constraints are user-facing when they don't need to be.

This!

Getting rid of overloads and at the same time simplify the constraints by moving them in the function with static if!
That would really improve the function signatures!
February 15, 2017
On 2/15/17 3:53 AM, Jacob Carlborg wrote:
> I do see a possibility for a slightly improvement in a different area,
> in the example of "remove". If we look at the signature, without the
> constraints:
>
> Range remove
> (SwapStrategy s = SwapStrategy.stable, Range, Offset...)
> (Range range, Offset offset)
>
> Why isn't it possible to use "auto" when declaring a parameter with a
> default argument?
>
> Range remove
> (auto s = SwapStrategy.stable, Range, Offset...)
> (Range range, Offset offset)
>
> A minor improvement, but I also feel like it would lift an arbitrary
> limitation in the language.

That's nice, could you please submit as an enhancement request on bugzilla?

> I haven't followed the C++ concepts lately either and not very closely
> at all so I don't feel I can comment on the C++ concepts.

You may want to correct that if you want to make a serious proposal for D concepts.

> But if I
> recall correctly, you're "static if" proposal wasn't well received [1].
> But now with "if constexpr" it looks like they're changing their minds.
>
> [1] "The static if feature recently proposed for C++ [1, 2] is
> fundamentally flawed, and its adoption would be a disaster for the
> language" http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2013/n3613.pdf

"I made a terrible mistake" is spelled http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2015/p0128r0.html here. It still has a cargo cult flavor because it introduces a new scope, which kinda misses the point of static if.


Andrei