March 20, 2019
On Tuesday, 19 March 2019 at 14:08:24 UTC, Steven Schveighoffer wrote:
> The problem is a simple one: typeof(a.length) is not size_t, but a function type.
>
> If you put @property on the length function it would work, but I think we should not require that.
>
> -Steve

struct S
{
   size_t length() const { return 0; }
}

auto ref property(T)(auto ref T a){ return a; }

void f()
{
   S s;
   assert(s.length == 0); //OK
   static assert(is(typeof(property(s.length))==size_t));
}

Can this work?
March 20, 2019
On 3/19/19 9:04 AM, Vladimir Panteleev wrote:
> On Tuesday, 19 March 2019 at 02:52:34 UTC, Andrei Alexandrescu wrote:
>> And why was Phobos under the obligation to cater for such a type and its tenuous relationship to a range?
> 
> There's two paths to investigate this:
> 
> 1. Use git blame to find the commit when it was introduced, and follow the thread to the pull request, Bugzilla issue, etc.
> 
> 2. Open a draft PR with a fix, and see what breaks (both within D repositories i.e. auto-tester, and in the D ecosystem at large i.e. the project tester).

Thanks. I'm less preoccupied with figuring out who wrote that code, as with addressing the systemic matter. My working hypothesis is a (milder) form of "the road to hell is paved with good intentions" - some arguably undesirable generality has accumulated slowly as many contributors with varying design sensibilities operated under the vague desideratum that more generality is better, ran into a variety of complex cases, and contributed their solution to the standard library.

I got word a similar phenomenon is at work in Scala - the language and its libraries are very powerful, but the boundaries of power are fuzzy and some users are in a continuous state of frustration that some constructs that ought to work do not due to byzantine limitations.

At any rate, there seems to be some good opportunity to significantly simplifying the standard library by dropping some of the more obscure supported cases.
March 20, 2019
On 3/20/19 1:41 PM, Kagamin wrote:
> On Tuesday, 19 March 2019 at 14:08:24 UTC, Steven Schveighoffer wrote:
>> The problem is a simple one: typeof(a.length) is not size_t, but a function type.
>>
>> If you put @property on the length function it would work, but I think we should not require that.
>>
>> -Steve
> 
> struct S
> {
>     size_t length() const { return 0; }
> }
> 
> auto ref property(T)(auto ref T a){ return a; }
> 
> void f()
> {
>     S s;
>     assert(s.length == 0); //OK
>     static assert(is(typeof(property(s.length))==size_t));
> }
> 
> Can this work?

Yep, that's a good idea actually. Make it inout, to cut down on template bloat.

I actually use something less nice in iopipe[1], so I may switch to this.

-Steve

[1] https://github.com/schveiguy/iopipe/blob/master/source/iopipe/traits.d#L111-L119
March 21, 2019
On Wednesday, 20 March 2019 at 19:45:13 UTC, Steven Schveighoffer wrote:
> Yep, that's a good idea actually. Make it inout, to cut down on template bloat.

T property(T)(auto ref T a);

This still compiles. Will it bloat?
March 21, 2019
On Wednesday, 20 March 2019 at 19:45:13 UTC, Steven Schveighoffer wrote:
> On 3/20/19 1:41 PM, Kagamin wrote:
>> struct S
>> {
>>     size_t length() const { return 0; }
>> }
>> 
>> auto ref property(T)(auto ref T a){ return a; }
>> 
>> void f()
>> {
>>     S s;
>>     assert(s.length == 0); //OK
>>     static assert(is(typeof(property(s.length))==size_t));
>> }
>> 
>> Can this work?
>
> Yep, that's a good idea actually. Make it inout, to cut down on template bloat.
>
> I actually use something less nice in iopipe[1], so I may switch to this.

Rather than define a new `property` symbol, why not rewrite the template constraint for `empty` as:


@property bool empty (T) (auto ref scope T a)
    if(is(ReturnType!((T t) => t.length) : size_t))
{
    return !a.length;
}

This matches what is done in the `isInputRange` check for the existence of `empty` (I suspect it's done that way because it's quite common for `SomeRange.empty` to be an enum rather than a method or property).
March 21, 2019
On Thursday, 21 March 2019 at 16:11:04 UTC, Joseph Rushton Wakeling wrote:
> @property bool empty (T) (auto ref scope T a)
>     if(is(ReturnType!((T t) => t.length) : size_t))
> {
>     return !a.length;
> }

Here comes generality creep :)

struct A
{
    int a;
    @disable this(this);
    bool opCast(){ return !!a; }
}
struct S
{
    A a;
    ref A p() { return a; }
}

T property(T)(auto ref T a);
import std.traits;

void f()
{
    S s;
    assert(!s.p); //negation works
    static assert(is(typeof(property(s.p))==A));
    static assert(is(ReturnType!(()=>s.p):A));
}

The ReturnType assert doesn't pass. Any idea why? Well, maybe it shouldn't.
March 22, 2019
Apparently there are options

T property(T)(scope T a);
will check that the value can be retained from the property for local use

T property(T)(T a);
will check that the value can be returned from function (not scoped)
March 22, 2019
On 3/21/19 12:03 PM, Kagamin wrote:
> On Wednesday, 20 March 2019 at 19:45:13 UTC, Steven Schveighoffer wrote:
>> Yep, that's a good idea actually. Make it inout, to cut down on template bloat.
> 
> T property(T)(auto ref T a);
> 
> This still compiles. Will it bloat?

It's not the auto ref, it's the mutability:

auto ref property1(T)(auto ref T a)
{
  pragma(msg, T.stringof ~ " without inout");
  return a;
}

auto ref property2(T)(auto ref inout(T) a)
{
   pragma(msg, T.stringof ~ " with inout");
   return a;
}

void main()
{
   const int a = 1;
   immutable int b = 2;
   int c = 3;

   // 3 instantiations
   assert(a.property1 == a);
   assert(b.property1 == b);
   assert(c.property1 == c);

   // 1 instantiation
   assert(a.property2 == a);
   assert(b.property2 == b);
   assert(c.property2 == c);
}

output:

const(int) without inout
immutable(int) without inout
int without inout
int with inout

-Steve
March 28, 2019
A topical example:

https://github.com/dlang/phobos/pull/6346#issuecomment-477504005
March 28, 2019
On 28.03.19 09:52, Walter Bright wrote:
> A topical example:
> 
> https://github.com/dlang/phobos/pull/6346#issuecomment-477504005

That pull request was open for a year(!) waiting for someone to make a decision. And before that I had asked about the issue on the forum [1].

If you want things to go your way, consider answering when someone asks for direction.

By the way, I didn't get an email notification from GitHub for that comment. Does GitHub stop sending those when the pull request is merged? That would be worrying. Did anyone else get a notificaton?


[1] https://forum.dlang.org/post/p96gs4$22fp$1@digitalmars.com