February 14, 2017
On Tuesday, 14 February 2017 at 14:37:39 UTC, Andrei Alexandrescu wrote:
> what steps can we take to improve them.

You really can't unfortunately. Verbose-ness is a nessesary component of type-safe duck typing.
February 14, 2017
On Tuesday, 14 February 2017 at 09:55:51 UTC, Jacob Carlborg wrote:
> Why? It looks awful. The signatures we already have in Phobos is quite ridiculous, this will not improve. Isn't this and the whole idea of DIP 1005 just a workaround for the compiler not lazily analyzing the symbols.

https://github.com/dlang/DIPs/blob/master/DIPs/DIP1005.md#alternative-lazy-imports
February 14, 2017
On Tuesday, 14 February 2017 at 16:25:17 UTC, Andrei Alexandrescu wrote:
> 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);

[...]

> 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", ...). This is what has buried not one, but two concepts proposals for C++, leading to the current Concepts Lite proposal. 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 am not familiar with all of the past discussion of this issue, but something that I have wondered is why we can't do something like

alias fooConstraint = (s != SwapStrategy.stable
  && isBidirectionalRange!Range
  && hasLvalueElements!Range
  && hasLength!Range
  && Offset.length >= 1);

Range remove
  (SwapStrategy s = SwapStrategy.stable, Range, Offset...)
  (Range range, Offset offset) if fooConstraint;
February 14, 2017
On Tuesday, 14 February 2017 at 19:08:53 UTC, bachmeier wrote:

> I am not familiar with all of the past discussion of this issue, but something that I have wondered is why we can't do something like
>
> alias fooConstraint = (s != SwapStrategy.stable
>   && isBidirectionalRange!Range
>   && hasLvalueElements!Range
>   && hasLength!Range
>   && Offset.length >= 1);
>
> Range remove
>   (SwapStrategy s = SwapStrategy.stable, Range, Offset...)
>   (Range range, Offset offset) if fooConstraint;

I mean, is there some reason that this shouldn't be allowed? Any feature can be abused, but it looks useful in many cases.
February 14, 2017
On Tue, Feb 14, 2017 at 07:14:08PM +0000, bachmeier via Digitalmars-d wrote:
> On Tuesday, 14 February 2017 at 19:08:53 UTC, bachmeier wrote:
> 
> > I am not familiar with all of the past discussion of this issue, but something that I have wondered is why we can't do something like
> > 
> > alias fooConstraint = (s != SwapStrategy.stable
> >   && isBidirectionalRange!Range
> >   && hasLvalueElements!Range
> >   && hasLength!Range
> >   && Offset.length >= 1);
> > 
> > Range remove
> >   (SwapStrategy s = SwapStrategy.stable, Range, Offset...)
> >   (Range range, Offset offset) if fooConstraint;
> 
> I mean, is there some reason that this shouldn't be allowed? Any feature can be abused, but it looks useful in many cases.

This is already possible:

	enum fooConstraint(R) = isBidirectionalRange!Range &&
				hasLvalueElements!Range && ... ;

	Range remove(SwapStrategy s, R)(...) if (fooConstraint!R) { ... }


T

-- 
"Maybe" is a strange word.  When mom or dad says it it means "yes", but when my big brothers say it it means "no"! -- PJ jr.
February 14, 2017
On Tuesday, 14 February 2017 at 19:08:53 UTC, bachmeier wrote:
> I am not familiar with all of the past discussion of this issue, but something that I have wondered is why we can't do something like

Because at that point, it's no longer a set of lego's being put together (design by introspection) which build a larger whole. It's the genericism problem of requiring a name for everything.

At the end of the day this would actually make constraints less *verbose*, but more *complicated*.
February 14, 2017
On Tuesday, 14 February 2017 at 19:08:53 UTC, bachmeier wrote:
> I am not familiar with all of the past discussion of this issue, but something that I have wondered is why we can't do something like
>
> alias fooConstraint = (s != SwapStrategy.stable

You can do that, it would just be a helper function / template instead of an alias. You can use the shorthand enum syntax:

enum removable(R) = isBidirectionalRange!R && isInputRange!R;

Range remove(Range)(Range r) if(removable!Range) {
        return r;
}


That works today.


But the problems is: what name do you give it? Quite often it would just be `fooConstraint` or `removable` or other non-reusable things... you'd just be *adding* complication because you'd need to forward all the arguments and write different ones for each function anyway.

There's a few common cases we might combine, like Phobos often uses `isInputRange!Range && is(ElementType!Range == Something)` and perhaps that could be combined into `isInputRangeOf!(Range, Something)` or something like that, but in many cases, there'd be an equal number of aliases constraints to existing inline ones anyway....
February 14, 2017
On Tuesday, 14 February 2017 at 19:15:06 UTC, H. S. Teoh wrote:

> This is already possible:
>
> 	enum fooConstraint(R) = isBidirectionalRange!Range &&
> 				hasLvalueElements!Range && ... ;
>
> 	Range remove(SwapStrategy s, R)(...) if (fooConstraint!R) { ... }
>
>
> T

That's good to know. I didn't try that syntax, though, which explains why I couldn't get it to work.
February 14, 2017
On Tuesday, 14 February 2017 at 19:27:36 UTC, Adam D. Ruppe wrote:
> But the problems is: what name do you give it? Quite often it would just be `fooConstraint` or `removable` or other non-reusable things... you'd just be *adding* complication because you'd need to forward all the arguments and write different ones for each function anyway.
>
> There's a few common cases we might combine, like Phobos often uses `isInputRange!Range && is(ElementType!Range == Something)` and perhaps that could be combined into `isInputRangeOf!(Range, Something)` or something like that, but in many cases, there'd be an equal number of aliases constraints to existing inline ones anyway....

Makes sense. I had assumed there would be a lot of duplication of constraints.
February 14, 2017
On Tuesday, February 14, 2017 09:37:39 Andrei Alexandrescu via Digitalmars-d wrote:
> On 02/14/2017 04:55 AM, Jacob Carlborg wrote:
> > The signatures we already have in Phobos is quite ridiculous
>
> How are they so, and what steps can we take to improve them. Could you please give a few examples on how to do things better? Thx! -- Andrei

Unfortunately, I'm not sure that there's much that we can do. Each of the features that clutter up a function signature is useful and valuable in and of itself, but when you add them all together, it can get pretty messy. We've managed to improve some aspects over time, but there has to be a limit to it. At some point, the information takes up however much space it takes up.

Having auto functions helped considerably for cleaning up function signatures where templates were involved. Declaring eponymous templates to use as traits for commonly used idioms helps - and in some cases, maybe we should add more of those for common combinations, but the best we could do is clean up some common cases, because it ultimately doesn't scale well for the reasons that you explained why C++ has had issue with getting concepts into the standard. Having different defaults for function attributes would help in some cases (e.g. have @safe and pure be the default), but I don't see how we could do that at this point without breaking a bunch of code. And attribute inference already takes care of the attributes on the most cluttered functions, since those are going to be templated functions with template constraints.

I think that things just reach a point where if you want the functionality, you get a messy function signature, and you can't do much more than try and format it nicely. For better or worse, it's just one of the costs of what D provides.

That being said, at some point, you have to ask whether each added feature is worth the cost when you consider how it's going to clutter up function signatures even further. And while I do think that there is value in DIP 1005 and the proposed from template, I also think that it's taking it too far. IMHO, it's just not worth marking functions even further - at least not in most code. Maybe it's worth it in something like Phobos where everyone is using it and benefiting from the compilation speed up, but Walter has been wanting to implement lazy imports anyway, and that would fix the problem without doing anything to any function signatures. It does lose the benefits of tying the imports to the function, but personally, I don't think that that's's worth the extra cost of further cluttering up the function signature. As it is, I'm increasingly of the opinion that local and selective imports aren't worth it. It's just so much nicer to able to slap the required imports at the beginning of the module and forget about them than having to worry about maintaining a list of selective imports or have all of the extra import lines inside of all of the functions. And adding imports to the function signatures is just making the whole local import situation that much worse.

So, regardless of what happens with DIP 1005 or from, I'd very much like to see lazy imports implemented, and I don't expect use DIP 1005 or from in much code that I write.

- Jonathan M Davis