June 10, 2020
On Wednesday, 10 June 2020 at 22:50:17 UTC, Paul Backus wrote:
> static assert(isInputRange!S); // passes

isInputRange doesn't check it but others do. std.random.isSeedable requires @property on front for example.

Some apparently test incorrectly too, like std.range.primitives.moveFront seems to incorrectly reject front variables.

@property is done wrong and I wish they would fix it but right now it is... often ignorable but sometimes will do mysterious inconsistency due to library use.
June 10, 2020
On Wednesday, 10 June 2020 at 23:03:21 UTC, Adam D. Ruppe wrote:
> On Wednesday, 10 June 2020 at 22:50:17 UTC, Paul Backus wrote:
>> static assert(isInputRange!S); // passes
>
> isInputRange doesn't check it but others do. std.random.isSeedable requires @property on front for example.

Nope:

struct S {
    bool empty() { return false; }
    int front() { return 0; }
    void popFront() {}
    enum bool isUniformRandom = true;
    void seed(int s) {}
}
	
static assert(isSeedable!(S, int));
June 10, 2020
On Wednesday, 10 June 2020 at 23:26:35 UTC, Paul Backus wrote:
> On Wednesday, 10 June 2020 at 23:03:21 UTC, Adam D. Ruppe wrote:
>> On Wednesday, 10 June 2020 at 22:50:17 UTC, Paul Backus wrote:
>>> static assert(isInputRange!S); // passes
>>
>> isInputRange doesn't check it but others do. std.random.isSeedable requires @property on front for example.
>
> Nope:
>
> struct S {
>     bool empty() { return false; }
>     int front() { return 0; }
>     void popFront() {}
>     enum bool isUniformRandom = true;
>     void seed(int s) {}
> }
> 	
> static assert(isSeedable!(S, int));

My bad, missed the one-argument overload. That one does require @property.
June 10, 2020
On Wednesday, June 10, 2020 3:41:54 PM MDT H. S. Teoh via Digitalmars-d-learn wrote:
> On Wed, Jun 10, 2020 at 08:24:19PM +0000, Vinod K Chandran via Digitalmars-
d-learn wrote:
> > Hi all,
> > I read in an old thread that authors of D wants to eliminate
> > @property. I just roughly read the big thread bu couldn't find a
> > conclusion. After all that thread is a 48 page longer jumbo thread. So
> > out of curiosity, i am asking this. What is the current state of
> > @property ? Is it deprecated ?
>
> It's stuck in limbo, like many things that people just cannot agree on. There are a few places where it's needed (like satisfying the range API, which implicitly checks for it), but for the most part, you can just ignore it, it doesn't really make a big difference.  Life goes on.

Yeah. There was a ton of arguing about what to do with it in the past, with the intention at one point being that @property functions would always be called without parens, and all function without @property would always be called with parens, but there was never full agreement on it, and once UFCS became widespread, the idea of requiring parens on non-@property functions became a lot less popular, because many people don't like the idea of having empty runtime argument parens on a function call after the template argument parens - e.g. foo.map!(a => a * 42)() vs foo.map!(a => a * 42). Ultimately, @property was never completed, and it's sort of just lingered on.

As I understand it, @property currently does exactly two things:

1. Become an attribute on the function which affects the mangling and can be queried my metaprogramming. IIRC, one result of this is that you can't overload a function that has @property with one that doesn't. Most traits in Phobos do not check for @property, but it's possible that some do. At one point, isForwardRange checked for it for save (which never made sense, since save doesn't act like a property), but that was removed.

2. Screw with the type of the function so that traits will mostly claim that its type is the return type of the function rather than a function that returns that type. This can cause some subtle and annoying problems with metaprogramming.

Now, there is one ambiguity that @property was supposed to solve that was never solved, and that's a property function that returns a callable. Right now, you're forced to use double parens (one set being the optional parens, and the other being the set to call the return value), whereas if it were truly treated as a property function, then the first set of parens would call the return value. As such, you can't really have a property function that returns a callable (whether @property is used or not). So, even if we were to actually get rid of @property, we might want to keep it for that case, but since it's never actually be made to fix that case, such a change would sadly be a breaking change.

As things stand, @property has no real practical purpose but frequently gets used to indicate that it's the intention of a function's author for it to be used as if it were a variable. I suspect that it's also frequently misunderstand that it's required if you want to call a function without parens. So, you're likely to see @property in quite a lot of D code, but ultimately, all it's really doing is serving as documentation of the author's intent and screwing up metaprogramming.

- Jonathan M Davis



June 10, 2020
On Wed, Jun 10, 2020 at 10:58:57PM -0600, Jonathan M Davis via Digitalmars-d-learn wrote: [...]
> As things stand, @property has no real practical purpose but frequently gets used to indicate that it's the intention of a function's author for it to be used as if it were a variable. I suspect that it's also frequently misunderstand that it's required if you want to call a function without parens. So, you're likely to see @property in quite a lot of D code, but ultimately, all it's really doing is serving as documentation of the author's intent and screwing up metaprogramming.
[...]

Ironically, just today I ran into this corner case where @property actually became a solution to a real problem:

	//-----module1.d------
	auto someGenericFunc(T)(T t) {
		...
		static if (is(typeof(T.init.method) : T)) {
			R someRange = ...; // ElementType!R == T
			auto value = someRange.map!(e => e.method);
		}
		...
	}

	//-----module2.d------
	struct MyType {
		...
		auto method()() {
			return ...;
		}
		...
	}

	//------module3.d-----
	import module1;
	import module2;
	auto someFunc(...) {
		auto result = someGenericFunc!MyType;
	}

This was failing compilation, because when MyType.method is a template, the static if condition in module1 fails.  Adding @property to MyType.method tells the compiler that `T.init.method` is intended to refer to the return value rather than the template function itself, and thus neatly solves the problem.


T

-- 
It's amazing how careful choice of punctuation can leave you hanging:
June 11, 2020
On Thursday, 11 June 2020 at 05:41:25 UTC, H. S. Teoh wrote:
>
> Ironically, just today I ran into this corner case where @property actually became a solution to a real problem:
>
> 	//-----module1.d------
> 	auto someGenericFunc(T)(T t) {
> 		...
> 		static if (is(typeof(T.init.method) : T)) {
> 			R someRange = ...; // ElementType!R == T
> 			auto value = someRange.map!(e => e.method);
> 		}
> 		...
> 	}

Personally I like the way Phobos does it:

    ReturnType!((T t) => t.method)

This works for both @property and non-@property methods.
June 12, 2020
On Thu, Jun 11, 2020 at 10:46:32AM +0000, Paul Backus via Digitalmars-d-learn wrote:
> On Thursday, 11 June 2020 at 05:41:25 UTC, H. S. Teoh wrote:
> > 
> > Ironically, just today I ran into this corner case where @property actually became a solution to a real problem:
> > 
> > 	//-----module1.d------
> > 	auto someGenericFunc(T)(T t) {
> > 		...
> > 		static if (is(typeof(T.init.method) : T)) {
> > 			R someRange = ...; // ElementType!R == T
> > 			auto value = someRange.map!(e => e.method);
> > 		}
> > 		...
> > 	}
> 
> Personally I like the way Phobos does it:
> 
>     ReturnType!((T t) => t.method)
> 
> This works for both @property and non-@property methods.

Mmm, very nice!  I'll keep this in mind for next time!


T

-- 
The two rules of success: 1. Don't tell everything you know. -- YHL
1 2
Next ›   Last »