Re: Interaction of inheritance with property functions
On Friday, 8 June 2018 at 01:07:17 UTC, Luís Marques wrote: Shouldn't the property functions' resolution logic take into account the inherited functions? I had assumed that was the case (and I was confused by misleading error messages), and that seems like the more intuitive semantics to me. It is just the overload and hijacking rules. If you overload one, you need to bring the base class functions in too with alias width = Bits.width; in the child class. read this for rationale: https://dlang.org/articles/hijack.html
Interaction of inheritance with property functions
I had something like this: class Bits { int width() { return _width; } void width(int _width) { this._width = _width; } int _width; } class Bool : Bits { // make sure a Boolean is always 1 bit override int width() { assert(_width == 1); return _width; } } I was surprised that I could not do this: B b = new B; b.width = 42; Instead, I had to do this: B b = new B; (cast(Bits) b).width = 42; Or I had to add a redundant setter function to Bool. Shouldn't the property functions' resolution logic take into account the inherited functions? I had assumed that was the case (and I was confused by misleading error messages), and that seems like the more intuitive semantics to me.
Re: RFC: Implementation of binary assignment operators (e.g s.x += 2) for @property functions
On Tuesday, 15 August 2017 at 03:53:44 UTC, Michael V. Franklin wrote: An implementation of binary assignment operators for @property functions has been submitted to the DMD pull request queue at https://github.com/dlang/dmd/pull/7079. [snip] Walter has requested that I make this forum post to inform the community of this change in an effort to discuss its merits and/or shortcomings. We ask for your comments whether they be in approval or disapproval of this pull request so we can determine the best way forward. Thanks for the heads up. I think this would have been good for a DIP, to better guard against bad interplay with other D constructs. I've added to the PRs a few comments that immediately came to mind. It seems you already spent some time trying to break the new mechanics, that's good. But perhaps we need some more breakage ;-) (for example I think we can dig a little deeper down the opBinary hole) -Johan
Re: RFC: Implementation of binary assignment operators (e.g s.x += 2) for @property functions
On Tuesday, 15 August 2017 at 03:53:44 UTC, Michael V. Franklin wrote: An implementation of binary assignment operators for @property functions has been submitted to the DMD pull request queue at https://github.com/dlang/dmd/pull/7079. It addresses the following issues: Issue 8006 - Implement proper in-place-modification for properties https://issues.dlang.org/show_bug.cgi?id=8006 -- This is the primary issue motivating the pull request. The pull request is only a partial resolution of this issue; it implements binary assignment operators (e.g. `s.x += 2`), but not unary assignment operators (e.g. `s.x++`). The plan is to implement unary assignment operators in a separate pull request after the fate of the binary assignment operators pull request is decided. I'm a huge fan of this, but then I am of the mindset that @property functions should act like variables much in the way that they do for C# properties.
Re: RFC: Implementation of binary assignment operators (e.g s.x += 2) for @property functions
On Tuesday, 15 August 2017 at 07:52:17 UTC, Gary Willoughby wrote: On Tuesday, 15 August 2017 at 03:53:44 UTC, Michael V. Franklin wrote: An implementation of binary assignment operators for @property functions has been submitted to the DMD pull request queue at https://github.com/dlang/dmd/pull/7079. It addresses the following issues: Issue 8006 - Implement proper in-place-modification for properties https://issues.dlang.org/show_bug.cgi?id=8006 I thought @property's behaviour had been removed from the language and even though the attribute remains, it doesn't actually do anything? @property changes the typeof result (useful for introspection) [1][2]: --- For the expression typeof(exp) where exp is an @property function, the type is the return type of the function, rather than the type of the function. --- --- If the expression is a Property Function, typeof gives its return type. --- [1] https://dlang.org/spec/declaration.html#typeof [2] https://dlang.org/spec/function.html#property-functions
Re: RFC: Implementation of binary assignment operators (e.g s.x += 2) for @property functions
Am Tue, 15 Aug 2017 07:52:17 + schrieb Gary Willoughby : > On Tuesday, 15 August 2017 at 03:53:44 UTC, Michael V. Franklin > wrote: > > An implementation of binary assignment operators for @property > > functions has been submitted to the DMD pull request queue at > > https://github.com/dlang/dmd/pull/7079. It addresses the > > following issues: > > > > Issue 8006 - Implement proper in-place-modification for > > properties > > https://issues.dlang.org/show_bug.cgi?id=8006 > > I thought @property's behaviour had been removed from the > language and even though the attribute remains, it doesn't > actually do anything? > > You're probably thinking of the special optional/non-optional parenthesis rules and the -property compiler switch which was removed. @property should still be used according to the style guide: https://dlang.org/dstyle.html and as far as I can tell it's heavily used in phobos. Properties behave more like field variables in some traits: http://dlang.org/spec/traits.html https://dlang.org/phobos/std_traits.html But I think that's the only relevant difference between properties and normal functions right now. -- Johannes
Re: RFC: Implementation of binary assignment operators (e.g s.x += 2) for @property functions
On Tuesday, 15 August 2017 at 03:53:44 UTC, Michael V. Franklin wrote: An implementation of binary assignment operators for @property functions has been submitted to the DMD pull request queue at https://github.com/dlang/dmd/pull/7079. It addresses the following issues: Issue 8006 - Implement proper in-place-modification for properties https://issues.dlang.org/show_bug.cgi?id=8006 I thought @property's behaviour had been removed from the language and even though the attribute remains, it doesn't actually do anything?
Re: RFC: Implementation of binary assignment operators (e.g s.x += 2) for @property functions
Am Tue, 15 Aug 2017 03:53:44 + schrieb Michael V. Franklin : > We ask for your comments whether they be in approval or > disapproval of this pull request so we can determine the best way > forward. > > Thank you, > Michael V. Franklin +1. Then @property finally becomes useful ;-) -- Johannes
Re: RFC: Implementation of binary assignment operators (e.g s.x += 2) for @property functions
Michael V. Franklin wrote: An implementation of binary assignment operators for @property functions has been submitted to the DMD pull request queue at https://github.com/dlang/dmd/pull/7079. It addresses the following issues: Issue 8006 - Implement proper in-place-modification for properties https://issues.dlang.org/show_bug.cgi?id=8006 -- This is the primary issue motivating the pull request. The pull request is only a partial resolution of this issue; it implements binary assignment operators (e.g. `s.x += 2`), but not unary assignment operators (e.g. `s.x++`). The plan is to implement unary assignment operators in a separate pull request after the fate of the binary assignment operators pull request is decided. Issue 18187 – std.bitmap fields should be lvalues https://issues.dlang.org/show_bug.cgi?id=16187 - This is a more real-world example where binary assignment operators would be beneficial, as bit fields are not individually addressable. Issue 15231 - opOpAssign allows assignment to rvalue https://issues.dlang.org/show_bug.cgi?id=15231 While the pull request does not actually resolve the error illustrated in this issue, it demonstrates how a user desired binary assignment operators for @property functions so much that (s)he attempted to implement them indirectly by modeling the value type as a struct and overloading its operators. Had binary assignment operators been implemented the user probably would not have had any need expend such effort. Like the other users that commented in the issues above, I was a bit dismayed to discover that binary assignment operators were not implemented for @property functions. When I submitted the pull request I was under the assumption that the only reason they weren’t implemented was because noone had gotten around to it yet. Walter has requested that I make this forum post to inform the community of this change in an effort to discuss its merits and/or shortcomings. We ask for your comments whether they be in approval or disapproval of this pull request so we can determine the best way forward. Thank you, Michael V. Franklin merge it. but don't do unary inc/dec, as they are meant to be as atomic as possible.
RFC: Implementation of binary assignment operators (e.g s.x += 2) for @property functions
An implementation of binary assignment operators for @property functions has been submitted to the DMD pull request queue at https://github.com/dlang/dmd/pull/7079. It addresses the following issues: Issue 8006 - Implement proper in-place-modification for properties https://issues.dlang.org/show_bug.cgi?id=8006 -- This is the primary issue motivating the pull request. The pull request is only a partial resolution of this issue; it implements binary assignment operators (e.g. `s.x += 2`), but not unary assignment operators (e.g. `s.x++`). The plan is to implement unary assignment operators in a separate pull request after the fate of the binary assignment operators pull request is decided. Issue 18187 – std.bitmap fields should be lvalues https://issues.dlang.org/show_bug.cgi?id=16187 - This is a more real-world example where binary assignment operators would be beneficial, as bit fields are not individually addressable. Issue 15231 - opOpAssign allows assignment to rvalue https://issues.dlang.org/show_bug.cgi?id=15231 While the pull request does not actually resolve the error illustrated in this issue, it demonstrates how a user desired binary assignment operators for @property functions so much that (s)he attempted to implement them indirectly by modeling the value type as a struct and overloading its operators. Had binary assignment operators been implemented the user probably would not have had any need expend such effort. Like the other users that commented in the issues above, I was a bit dismayed to discover that binary assignment operators were not implemented for @property functions. When I submitted the pull request I was under the assumption that the only reason they weren’t implemented was because noone had gotten around to it yet. Walter has requested that I make this forum post to inform the community of this change in an effort to discuss its merits and/or shortcomings. We ask for your comments whether they be in approval or disapproval of this pull request so we can determine the best way forward. Thank you, Michael V. Franklin
Error: no property 'foo' for type 'main.Bar', did you mean 'foo'?
Awesome, now I understand the meaning of the life!
Re: Property access to a struct that contains struct
On Sunday, 26 February 2017 at 11:18:12 UTC, Mike Parker wrote: On Sunday, 26 February 2017 at 11:05:42 UTC, Guenter wrote: Hi, i do not understand where I am wrong in this code. I seems there is a missing constructor, but i have no idea where. @property A_t ext() { return fext; } Structs in D are value types, so you're returning a copy of fext here and that's what's getting updated with the new value. Try this: ref A_T ext() { return fext; } Thank you. Guenter
Re: Property access to a struct that contains struct
On Sunday, 26 February 2017 at 11:15:21 UTC, Eugene Wissner wrote: you return a copy of A_t and then change this copy instead of the real B_t member. Thank you. Guenter
Re: Property access to a struct that contains struct
On Sunday, 26 February 2017 at 11:05:42 UTC, Guenter wrote: Hi, i do not understand where I am wrong in this code. I seems there is a missing constructor, but i have no idea where. @property A_t ext() { return fext; } Structs in D are value types, so you're returning a copy of fext here and that's what's getting updated with the new value. Try this: ref A_T ext() { return fext; }
Re: Property access to a struct that contains struct
On Sunday, 26 February 2017 at 11:05:42 UTC, Guenter wrote: Hi, i do not understand where I am wrong in this code. I seems there is a missing constructor, but i have no idea where. module main; import std.stdio; struct A_t { int fvalue; A_t opCall() { return this; }; @property int value () { return fvalue; } @property void value (int avalue) { fvalue = avalue; } } struct B_t { A_t fext; int opCall() { return ext.value; }; @property A_t ext() { return fext; } @property void ext(A_t aext) { fext = aext; } } void main() { B_t test; test.ext.value = 9; int t = test(); assert ( t == 9); // t is always 0 instead of 9. readln(); } cu Guenter It should be: @property ref A_t ext() { return fext; } you return a copy of A_t and then change this copy instead of the real B_t member.
Property access to a struct that contains struct
Hi, i do not understand where I am wrong in this code. I seems there is a missing constructor, but i have no idea where. module main; import std.stdio; struct A_t { int fvalue; A_t opCall() { return this; }; @property int value () { return fvalue; } @property void value (int avalue) { fvalue = avalue; } } struct B_t { A_t fext; int opCall() { return ext.value; }; @property A_t ext() { return fext; } @property void ext(A_t aext) { fext = aext; } } void main() { B_t test; test.ext.value = 9; int t = test(); assert ( t == 9); // t is always 0 instead of 9. readln(); } cu Guenter
Re: Property-based testing
On Monday, 16 January 2017 at 14:15:16 UTC, Russel Winder wrote: Is anyone out there doing a property-based testing framework for D? https://github.com/atilaneves/unit-threaded/blob/master/source/unit_threaded/property/package.d Atila
Re: Property-based testing
On Monday, 16 January 2017 at 14:15:16 UTC, Russel Winder wrote: Is anyone out there doing a property-based testing framework for D? There have been several attempts to implement such a framework, e.g. [1]. If you run a search for "quickcheck" in the forums, you'll probably find them all. [1] https://github.com/mcandre/dashcheck
Property-based testing
Is anyone out there doing a property-based testing framework for D? -- Russel. = Dr Russel Winder t: +44 20 7585 2200 voip: sip:russel.win...@ekiga.net 41 Buckmaster Roadm: +44 7770 465 077 xmpp: rus...@winder.org.uk London SW11 1EN, UK w: www.russel.org.uk skype: russel_winder signature.asc Description: This is a digitally signed message part
Re: @property Incorrectly Implemented?
On Saturday, 17 September 2016 at 10:55:59 UTC, Ethan Watson wrote: On Friday, 16 September 2016 at 20:52:37 UTC, John wrote: Your comment was out of place, saying properties don't need to be changed is like saying @property shouldn't even be a D feature cause you can create the same functional program in C++, which does not have the property feature. Stop reading rubbish that isn't there. And pay attention. MSVC has the __declspec( property ) extension. MSVC != C++ I'm not going to pay attention to a feature that isn't standard and only Microsoft's compiler seems to have. Since you brought it up though, it's a good chance to look at how it behaves. struct Test { int p; int& prop() { return p; } __declspec(property(get = prop, put = prop)) int& magic; }; void main() { Test test; test.p = 10; if(&test.p == &test.magic) { std::cout << &test.p << '\n' << &test.magic << '\n' << "magic"; } } I'll give you a hint, it prints magic. Imagine that. You also made a reference to C#, which doesn't even allow you take address of And? Properties in C# are a massive example of a comparable feature where executed code is syntactically treated in some ways to a variable. Yes, you can't take the address of a property in C#, with or without unsafe on. So I don't know what you mean by that's how I want to play, when you instigated said argument. I indicated you're taking it personally. Which you are. I wasn't until you indicated that you were taking it personally with that statement. It's not really that important. What it allows is returning references. You can make a comparison to any other language that has properties it doesn't really matter. This is how D was implemented. If they wanted to be like every other language then it shouldn't have been allowed to even return a reference. But it is does, that's how it's implemented and odds are it probably won't change now to not allow it. D also has the "&" implemented, what I am discussing is whether it was implemented correctly or not. Honestly it is no implemented correctly. To the point I would actually rather they remove the functionality so that you can't take the address of a property. If they are not willing to change it to function in a different way. Taking the address of a property and getting a function type is important. Did you know that this C++ class: class SomeObject { virtual int getSomeValue() const; virtual int setSomeValue( int value ); }; Matches up exactly to this D class: extern( C++ ) class SomeObject { @property SomeValue() const; @property SomeValue( int value ); } You have "get" and "set" in the C++ function, so no it doesn't match it exactly. Semantics aside, you shouldn't be referencing behavior of properties in a language that doesn't even have properties. It's simply a way to emulate properties. If C++ had properties, I would imagine they would behave like the above MSVC implementation does. Shouldn't be held back by C++ for such a reason, you can easily take off those property attributes and that would probably be the saner solution. So that it actually functions the same, in that you need the use the paranethese to set and get the variable. That aside I doubt you ever take the pointer of those getters and setters in C++ either. Anyways a bitfield can't actually represent a single, there's no type for a bit. The smallest type is a byte, which is 8 bits. So even if it wasn't a property there's no way you can take the address of a bit. So that's the first issue, you are trying to use an example that doesn't make sense even outside the concept of properties. The second issue is, this is defined behavior. You can't take the address of a rvalue, there's an ideone link in my previous post show this if you missed it. So taking the address of a property would return an error if it didn't return a reference. What you're suggesting, and why I brought up the example, is to change the implementation details of properties for *one* use case. This has wide ranging implications that you've clearly not thought of. Like if I was to take the address of that property for the purposes of exposing a function to C++. You want to make it so I don't get that function? Or that there's some extra convoluted method of getting it solely because you think a property should be something that it's not? One use case is better than the zero use case it current holds.. And using it to identify whether a member is a property is
Re: @property Incorrectly Implemented?
On Friday, 16 September 2016 at 20:52:37 UTC, John wrote: Your comment was out of place, saying properties don't need to be changed is like saying @property shouldn't even be a D feature cause you can create the same functional program in C++, which does not have the property feature. Stop reading rubbish that isn't there. And pay attention. MSVC has the __declspec( property ) extension. You also made a reference to C#, which doesn't even allow you take address of And? Properties in C# are a massive example of a comparable feature where executed code is syntactically treated in some ways to a variable. So I don't know what you mean by that's how I want to play, when you instigated said argument. I indicated you're taking it personally. Which you are. It's not really that important. What it allows is returning references. You can make a comparison to any other language that has properties it doesn't really matter. This is how D was implemented. If they wanted to be like every other language then it shouldn't have been allowed to even return a reference. But it is does, that's how it's implemented and odds are it probably won't change now to not allow it. D also has the "&" implemented, what I am discussing is whether it was implemented correctly or not. Honestly it is no implemented correctly. To the point I would actually rather they remove the functionality so that you can't take the address of a property. If they are not willing to change it to function in a different way. Taking the address of a property and getting a function type is important. Did you know that this C++ class: class SomeObject { virtual int getSomeValue() const; virtual int setSomeValue( int value ); }; Matches up exactly to this D class: extern( C++ ) class SomeObject { @property SomeValue() const; @property SomeValue( int value ); } This has been brought up by someone else. I honestly don't understand why it's such a hard concept. Because your understanding of the technical details is limited... Maybe you don't come from C++ and thus don't use a language that provides a way to take the address of things. ...and you're assuming you know more than what I do on the subject. That's why it keeps being brought up. Calm down. Anyways a bitfield can't actually represent a single, there's no type for a bit. The smallest type is a byte, which is 8 bits. So even if it wasn't a property there's no way you can take the address of a bit. So that's the first issue, you are trying to use an example that doesn't make sense even outside the concept of properties. The second issue is, this is defined behavior. You can't take the address of a rvalue, there's an ideone link in my previous post show this if you missed it. So taking the address of a property would return an error if it didn't return a reference. What you're suggesting, and why I brought up the example, is to change the implementation details of properties for *one* use case. This has wide ranging implications that you've clearly not thought of. Like if I was to take the address of that property for the purposes of exposing a function to C++. You want to make it so I don't get that function? Or that there's some extra convoluted method of getting it solely because you think a property should be something that it's not? Well that's how it is currently implemented actually. struct S { @property int prop() { return 0; } } writeln(typeof(S.prop).stringof) // prints "int", not "delegate" Read further. I have suggested that the property resolution order gets changed so that this ambiguity goes away. blah blah blah Yeah I covered everything else already. Not helping your cause by stating your example that started this topic was *satirical*.
Re: @property Incorrectly Implemented?
On Fri, 16 Sep 2016 20:52:37 +, John wrote: > You also made a reference to C#, which doesn't even > allow you take address of So I don't know what you mean by that's how I > want to play, when you instigated said argument. C# allows you to use pointers and take the address of fields. You must compile your code with `/unsafe` and use an `unsafe {}` block to do it. It does not allow you to take the address of a property. It complains: "Cannot take the address of the given expression". > as far as I am aware there is no way to get the delegate for the setter. Let's consider the following type: struct Foo { @property int a() { return 1; } @property int a(int v) { return v; } } Given an instance `Foo f`, `f.a` is an overload set. It's a bundle of several functions that can be referred to using the same symbols and must be disambiguated. Most of the time, you disambiguate by calling the function with arguments. However, that is not the only way: when taking the address of a function, the compiler looks at the static type that the expression is expected to return. So the following works: int delegate(int) setter = &f.a; int delegate() getter = &f.a; But this doesn't: auto dg = &f.a; // Error: cannot infer type from overloaded function symbol &f.a The same principle applies for any overloaded functions. > The way you should check if a member is a property shouldn't be by > taking the address of it. Check if __traits(getOverloads) for the member name has at least one overload. Or __traits(getVirtualFunctions) and see if there's a matching name. Unfortunately, std.traits doesn't have anything already implemented to do this. You may want to test things out and check the specific compiler error messages before declaring that they don't work. They can be rather dense, though.
Re: @property Incorrectly Implemented?
On Sunday, 11 September 2016 at 12:02:29 UTC, Ethan Watson wrote: On Sunday, 11 September 2016 at 07:19:54 UTC, John wrote: You can't really take one sentence out of context, I didn't say it in the sense that it was completely broken to the point of being useless. There's nothing out of context about it. Would it have made you feel better had I quoted your entire message knowing that I wouldn't have changed a word of the response? But if that's how you want to play. Your comment was out of place, saying properties don't need to be changed is like saying @property shouldn't even be a D feature cause you can create the same functional program in C++, which does not have the property feature. You also made a reference to C#, which doesn't even allow you take address of So I don't know what you mean by that's how I want to play, when you instigated said argument. The part I'm asking to be changed, you probably didn't even ever use. C# is a managed language, I don't think you can even take the pointer of anything unless you enable the unsafe switch. You're not showing a good grasp at all as to what a property is. In C# and in D, a property has *never* guaranteed the existence of a variable. In both cases, they allow syntactic sugar for letting the getter/setter pattern established by C++ look like variables. This is important. No, really. Take std.bitmanip for an example of what I was talking about. It autogenerates properties for a bitfield. The types each property returns and lets you set are not at all indicative of the datatype underneath as it's literally just a bunch of bits. The property functions transform the data types given/return to/from a bitfield. What exactly do you suggest &property return if it was to return a char starting at bit 13 of a bitfield? It's not really that important. What it allows is returning references. You can make a comparison to any other language that has properties it doesn't really matter. This is how D was implemented. If they wanted to be like every other language then it shouldn't have been allowed to even return a reference. But it is does, that's how it's implemented and odds are it probably won't change now to not allow it. D also has the "&" implemented, what I am discussing is whether it was implemented correctly or not. Honestly it is no implemented correctly. To the point I would actually rather they remove the functionality so that you can't take the address of a property. If they are not willing to change it to function in a different way. This has been brought up by someone else. I honestly don't understand why it's such a hard concept. Maybe you don't come from C++ and thus don't use a language that provides a way to take the address of things. That's why it keeps being brought up. Anyways a bitfield can't actually represent a single, there's no type for a bit. The smallest type is a byte, which is 8 bits. So even if it wasn't a property there's no way you can take the address of a bit. So that's the first issue, you are trying to use an example that doesn't make sense even outside the concept of properties. The second issue is, this is defined behavior. You can't take the address of a rvalue, there's an ideone link in my previous post show this if you missed it. So taking the address of a property would return an error if it didn't return a reference. But we can go one further. __traits( allMembers, Type ) and __traits( getMember, Type ). Let's say you're writing an auto-serialisation library (or take std.json as an example). Assuming a property is a stand-in for another variable then what happens there when you're checking for the type of a member is the delegate type, and later on you'll get the actual variable. Now change it so that the type of a property returns the actual type. Now you're serialising a piece of data twice. But what if our @property function increments another variable inside a class whenever you access it? That's pretty dangerous if you start treating the property as an actual type instead of a function/delegate. Well that's how it is currently implemented actually. struct S { @property int prop() { return 0; } } writeln(typeof(S.prop).stringof) // prints "int", not "delegate" I'm only talking about taking the address of a property. That does no way infer that there shouldn't be some way to identify that it is a property at compile time. The way you should check if a member is a property shouldn't be by taking the address of it. That's not as clear as having a trait or other implementation such that you could do "isProperty". That is
Re: @property Incorrectly Implemented?
On Tuesday, 6 September 2016 at 19:18:11 UTC, John wrote: This is all you need to know: https://wiki.dlang.org/Property_Discussion_Wrap-up
Re: @property Incorrectly Implemented?
Your template will not change behavior if isSomeFunction returns true for properties. That's probably ok.
Re: @property Incorrectly Implemented?
On Monday, 12 September 2016 at 09:25:40 UTC, Kagamin wrote: You mean your serialization library will break if @property changes behavior? Any serialisation library can break if a property is indistinguishable from an ordinary type, as a property is explicitly code that returns a value and faces all the allowances and restrictions that normal functions have. In my case, it will break if this template fails: template IsVariable( X... ) if ( X.length == 1 ) { static if( is( X[ 0 ] == void ) || is( typeof( X[ 0 ] ) == void ) ) { enum IsVariable = false; } else static if ( !IsSomeType!( X[ 0 ] ) ) { static if( isSomeFunction!( X[ 0 ] ) ) { enum IsVariable = isFunctionPointer!( X[ 0 ] ) || isDelegate!( X[ 0 ] ); } else { enum IsVariable = is( typeof( X [ 0 ] ) ) && !is( typeof( X [ 0 ] ) == void ) && IsMutable!( typeof( X[ 0 ] ) ); } } else { enum IsVariable = false; } }
Re: @property Incorrectly Implemented?
On Sunday, 11 September 2016 at 12:02:29 UTC, Ethan Watson wrote: But what if our @property function increments another variable inside a class whenever you access it? That's pretty dangerous if you start treating the property as an actual type instead of a function/delegate. You mean your serialization library will break if @property changes behavior?
Re: @property Incorrectly Implemented?
On Sunday, 11 September 2016 at 23:31:54 UTC, Timon Gehr wrote: His property returns by ref. Irrelevant for the implementation details of properties. Ref in that context specifies a function property that makes the property function return by ref (wrap your head around that one). That entire post went in to detail about why treating properties as the functions they are is correct. You do realize that typeof(property) is the type of the return value, right? Also, it's easy. Add __traits(isVariable,...) or __traits(isProperty,...), or just use .tupleof. Furthermore you can even get the property accessor function overload set using (a hypothetical) __traits(getPropertyAccessors,...). You are correct. typeof( __traits( getMember, Type, PropertyName ) ) is the type of the return type of the function, since getMember forms a complete expression which evaluates down to the return type. Note that all of the __traits( isFunction ) return true correctly on these things though. This is one of the checks I have to make when parsing over a class to correctly determine what is and isn't actually a variable. I've even wrapped it all up in a trait called IsVariable. The std library has traits for checking types but nothing that straight up tells you if something is a variable or not. As such, who needs __traits( getPropertyAccessors ) when __traits( getOverloads ) already works? [Commentary on example] Actually, I take back what I said. Mostly because of typeof( t.x ). The thing that needs fixing is the property evaluation order so that ambiguities like all of this don't exist.
Re: @property Incorrectly Implemented?
On 11.09.2016 14:02, Ethan Watson wrote: On Sunday, 11 September 2016 at 07:19:54 UTC, John wrote: ... The part I'm asking to be changed, you probably didn't even ever use. C# is a managed language, I don't think you can even take the pointer of anything unless you enable the unsafe switch. ... In C# and in D, a property has *never* guaranteed the existence of a variable. In both cases, they allow syntactic sugar for letting the getter/setter pattern established by C++ look like variables. ... His property returns by ref. ... Take std.bitmanip for an example of what I was talking about. It autogenerates properties for a bitfield. The types each property returns and lets you set are not at all indicative of the datatype underneath as it's literally just a bunch of bits. The property functions transform the data types given/return to/from a bitfield. What exactly do you suggest &property return if it was to return a char starting at bit 13 of a bitfield? ... Not a delegate. In a sane world, it would give you a compile error because 'property' is an rvalue. But we can go one further. __traits( allMembers, Type ) and __traits( getMember, Type ). Let's say you're writing an auto-serialisation library (or take std.json as an example). Assuming a property is a stand-in for another variable then what happens there when you're checking for the type of a member is the delegate type, and later on you'll get the actual variable. Now change it so that the type of a property returns the actual type. Now you're serialising a piece of data twice. ... You do realize that typeof(property) is the type of the return value, right? Also, it's easy. Add __traits(isVariable,...) or __traits(isProperty,...), or just use .tupleof. Furthermore you can even get the property accessor function overload set using (a hypothetical) __traits(getPropertyAccessors,...). But what if our @property function increments another variable inside a class whenever you access it? That's pretty dangerous if you start treating the property as an actual type instead of a function/delegate. Thus, your example: &t.x // returns "ref int delegate()" &t.x() // ok returns "int*", but defeats purpose of @property &(t.j = 10) // shouldn't this return "ref int delegate(int)" ? First one I'd expect. Why? It's awful. Second one I'd expect. No, even more awful. typeof(t.x) is 'int'. You are not even supposed to be able to call an 'int'. The second one should be a compile error: "Error: function expected before (), not t.x of type int" Third one I'd expect results in int*. Agreed, that one is sane.
Re: @property Incorrectly Implemented?
On Sunday, 11 September 2016 at 07:19:54 UTC, John wrote: You can't really take one sentence out of context, I didn't say it in the sense that it was completely broken to the point of being useless. There's nothing out of context about it. Would it have made you feel better had I quoted your entire message knowing that I wouldn't have changed a word of the response? But if that's how you want to play. The part I'm asking to be changed, you probably didn't even ever use. C# is a managed language, I don't think you can even take the pointer of anything unless you enable the unsafe switch. You're not showing a good grasp at all as to what a property is. In C# and in D, a property has *never* guaranteed the existence of a variable. In both cases, they allow syntactic sugar for letting the getter/setter pattern established by C++ look like variables. This is important. No, really. Take std.bitmanip for an example of what I was talking about. It autogenerates properties for a bitfield. The types each property returns and lets you set are not at all indicative of the datatype underneath as it's literally just a bunch of bits. The property functions transform the data types given/return to/from a bitfield. What exactly do you suggest &property return if it was to return a char starting at bit 13 of a bitfield? But we can go one further. __traits( allMembers, Type ) and __traits( getMember, Type ). Let's say you're writing an auto-serialisation library (or take std.json as an example). Assuming a property is a stand-in for another variable then what happens there when you're checking for the type of a member is the delegate type, and later on you'll get the actual variable. Now change it so that the type of a property returns the actual type. Now you're serialising a piece of data twice. But what if our @property function increments another variable inside a class whenever you access it? That's pretty dangerous if you start treating the property as an actual type instead of a function/delegate. Thus, your example: &t.x // returns "ref int delegate()" &t.x() // ok returns "int*", but defeats purpose of @property &(t.j = 10) // shouldn't this return "ref int delegate(int)" ? First one I'd expect. Second one I'd expect. Third one I'd expect results in int*. You're getting the address of the results of the assign operation. Look at it this way: int val = (t.j = 10); You'd expect val and t.j to be 10, right? So why do you expect to get a ref int delegate(int) just because you ask for the address of it? Like I said. Disagree. There's nothing that needs fixing here.
Re: @property Incorrectly Implemented?
On Tuesday, 6 September 2016 at 19:37:26 UTC, Jonathan M Davis wrote: On Tuesday, September 06, 2016 19:18:11 John via Digitalmars-d wrote: Currently it seems that @property isn't implemented correctly. For some reason when you try to get the pointer of a property it returns a delegate for some reason. This just seems plain wrong, the whole purpose of a property is for a function to behave as if it weren't a function. There's also some inconsistencies in the behavior, "get" is implemented one way and then "set" is implemented another. http://ideone.com/ZgGT2G &t.x // returns "ref int delegate()" &t.x() // ok returns "int*", but defeats purpose of @property &(t.j = 10) // shouldn't this return "ref int delegate(int)" ? It would be nice to get this behavior fixed, so that it doesn't become set in stone. I think returning a delegate pointer is not what people would except nor is there really any use case for it. Okay. How would it work to safely get a pointer to anything but the @property function when taking its address? &t.x() is just going to give you the address of the return value - which in most cases, is going to be a temporary, so if that even compiles in most cases, it's a bit scary. Sure, if the @property function returns by ref, then it can work, but an @property function which returns by ref isn't worth much, since you're then giving direct access to the member variable which is what an @property function is usually meant to avoid. If you wanted to do that, you could just use a public member variable. So, given that most @property functions are not going to return by ref, how does it make any sense at all for taking the address of an @property function to do anything different than give you a delegate? Sure, that's not what happens when you take the address of a variable, but you're not dealing with a variable. You're dealing with an @property function which is just trying to emulate a variable. The reality of the matter is that an @property function is _not_ a variable. It's just trying to emulate one, and that abstraction falls apart _really_ fast once you try and do much beyond getting and setting the value - e.g. passing by ref falls flat on its face. We could do better than currently do (e.g. making += lower to code that uses both the getter and the setter when the getter doesn't return by ref), but there are some areas where a property function simply can't act like a variable, because it isn't one. There isn't even a guarantee that an @property function is backed by memory. It could be a completely calculated value, in which case, expecting to get an address of a variable when taking the address of the @property function makes even less sense. - Jonathan M Davis I don't see how that would be a problem, you can't take the address of an rvalue... The problem you describe would be true for functions as well. What's not true is that it is compilable (see: http://ideone.com/MXhkXC ). Any problem you can conjure up about references, temporary values and pointers, all of that would be true for a regular function as well. Obviously it is not a variable, but if you use a function and it returns a reference and you take the address of it. What you get is the address of the returned value not of the function. int v = obj.prop; if you look at that "prop" is a called function pretending to be a variable. If you take the address of a called function, you get the address of the returned variable, not the function. If you take the address of a variable, you get the address of the variable. On Wednesday, 7 September 2016 at 07:44:05 UTC, Ethan Watson wrote: On Tuesday, 6 September 2016 at 19:18:11 UTC, John wrote: It would be nice to get this behavior fixed. Disagree. I've used properties before in C# to transform to and from data sets required for network multiplayer. It works functionally the same way in D. Behaviour is as I would expect for the wider implications of how properties can work. You can't really take one sentence out of context, I didn't say it in the sense that it was completely broken to the point of being useless. The part I'm asking to be changed, you probably didn't even ever use. C# is a managed language, I don't think you can even take the pointer of anything unless you enable the unsafe switch. On Tuesday, 6 September 2016 at 19:34:59 UTC, ag0aep6g wrote: On 09/06/2016 09:18 PM, John wrote: &(t.j = 10) // shouldn't this return "ref int delegate(int)" ? `&t.j` should and does. With `= 10`, it's definitely a call, just like `&t.x()`. It would be nice to get this behavior fixed, so that it doesn't become set in stone
Re: @property Incorrectly Implemented?
On Wednesday, 7 September 2016 at 09:34:12 UTC, Jonathan M Davis wrote: But if you return the value by ref, then you pretty much circumvent all of that, because then someone can do something like take the address of the return value and procede to mutate it whenever they want without hitting your breakpoint or log messages or any of that. You can do a few things that can't be done with a public member variable, but on the whole, returning by ref defeats the purpose of having a property function. No, manipulation of the value can be only done after accessing it through the property, thus its mission is fulfilled. So, while some @property functions may return by ref, most won't, and it's arguably a bad idea in general. It's good when it allows easy refactoring. Stuff like assignment can be made to work, but something as simple as passing by ref falls simply cannot be done except in the case where the @property function returns by ref True. And for a large percentage of property functions, you don't want it to be the case that taking the address of the property function gives you a pointer to a member variable. It depends. Anything that would require an actual variable with an actual memory location isn't going to work unless the @property function returns by ref, and making taking the address of that kind of @property function give you the address of the variable would then not be consistent with any other @property function, which would create a different set of problems. Properties are meant to be inconsistent, i.e. to have different implementations. It's nice that we can have property syntax rather than having to have functions that start with get and set, but it really doesn't work to fully emulate variables. What you said is more like your preference to not pass values by ref. If you don't want it, don't do it, no problem.
Re: @property Incorrectly Implemented?
An easy way around this would be to disallow taking the address of a property at all. Sure it introduces a disparity between properties and real member variables, but that's surely worth all the confusion that might be caused otherwise. Is it even that common to take the address of a member variable of an aggregate outside low-level code?
Re: @property Incorrectly Implemented?
On Wednesday, 7 September 2016 at 09:34:12 UTC, Jonathan M Davis wrote: There are certainly some operations that we could better emulate with @property functions that currently don't work without returning by ref (like ++ or -=), but something like taking the address of the @property function simply isn't going to work in most cases, and neither is passing by ref. Basically, only stuff that can be lowered to calls to the getter and setter @property functions is going to work. It's nice that we can have property syntax rather than having to have functions that start with get and set, but it really doesn't work to fully emulate variables. - Jonathan M Davis BTW, some time ago, in another thread [1] about properties, we ended up writing this wrapper [2], which does a pretty good job at simulating fields. In the original thread you can also find other variants of it. [1] http://forum.dlang.org/thread/okmgnrhdoeciovrfj...@forum.dlang.org [2] http://pastebin.com/38n0fEtF
Re: @property Incorrectly Implemented?
On Wednesday, September 07, 2016 08:15:43 Kagamin via Digitalmars-d wrote: > On Tuesday, 6 September 2016 at 19:37:26 UTC, Jonathan M Davis > > wrote: > > but an @property function which returns by ref isn't worth > > much, since you're then giving direct access to the member > > variable which is what an @property function is usually meant > > to avoid. If you wanted to do that, you could just use a public > > member variable. > > It can do lazy initialization, allow to set a breakpoint, log > access etc. But if you return the value by ref, then you pretty much circumvent all of that, because then someone can do something like take the address of the return value and procede to mutate it whenever they want without hitting your breakpoint or log messages or any of that. You can do a few things that can't be done with a public member variable, but on the whole, returning by ref defeats the purpose of having a property function. And there are plenty of property functions that don't even refer to variables but instead are calculated, in which case there is no variable to return a ref to anyway. So, while some @property functions may return by ref, most won't, and it's arguably a bad idea in general. > > You're dealing with an @property function which is just trying > > to emulate a variable. > > That's the whole point. It's trying to emulate a variable, so why > not make it do it? Because aside from a few basic operations, it's not possible. Stuff like assignment can be made to work, but something as simple as passing by ref falls simply cannot be done except in the case where the @property function returns by ref - which is not the normal case. And for a large percentage of property functions, you don't want it to be the case that taking the address of the property function gives you a pointer to a member variable. There are certainly some operations that we could better emulate with @property functions that currently don't work without returning by ref (like ++ or -=), but something like taking the address of the @property function simply isn't going to work in most cases, and neither is passing by ref. Basically, only stuff that can be lowered to calls to the getter and setter @property functions is going to work. Anything that would require an actual variable with an actual memory location isn't going to work unless the @property function returns by ref, and making taking the address of that kind of @property function give you the address of the variable would then not be consistent with any other @property function, which would create a different set of problems. It's nice that we can have property syntax rather than having to have functions that start with get and set, but it really doesn't work to fully emulate variables. - Jonathan M Davis
Re: @property Incorrectly Implemented?
On Tuesday, 6 September 2016 at 19:37:26 UTC, Jonathan M Davis wrote: but an @property function which returns by ref isn't worth much, since you're then giving direct access to the member variable which is what an @property function is usually meant to avoid. If you wanted to do that, you could just use a public member variable. It can do lazy initialization, allow to set a breakpoint, log access etc. You're dealing with an @property function which is just trying to emulate a variable. That's the whole point. It's trying to emulate a variable, so why not make it do it?
Re: @property Incorrectly Implemented?
On Tuesday, 6 September 2016 at 19:18:11 UTC, John wrote: It would be nice to get this behavior fixed. Disagree. I've used properties before in C# to transform to and from data sets required for network multiplayer. It works functionally the same way in D. Behaviour is as I would expect for the wider implications of how properties can work.
Re: @property Incorrectly Implemented?
On 9/6/16 3:18 PM, John wrote: Currently it seems that @property isn't implemented correctly. For some reason when you try to get the pointer of a property it returns a delegate for some reason. This just seems plain wrong, the whole purpose of a property is for a function to behave as if it weren't a function. There's also some inconsistencies in the behavior, "get" is implemented one way and then "set" is implemented another. http://ideone.com/ZgGT2G &t.x // returns "ref int delegate()" &t.x() // ok returns "int*", but defeats purpose of @property &(t.j = 10) // shouldn't this return "ref int delegate(int)" ? It would be nice to get this behavior fixed, so that it doesn't become set in stone. I think returning a delegate pointer is not what people would except nor is there really any use case for it. Just FYI, at the moment I believe the only difference (aside from the defunct -property switch) between a @property function and a non-@property function is: int foo1() { return 1; } @property int foo2() { return 1; } pragma(msg, typeof(foo1)); // int function() pragma(msg, typeof(foo2)); // int That's it. typeof returns a different thing. All @property functions act just like normal functions when used in all other cases, and property syntax (assignment and getting) work on non-@property functions. This situation is less than ideal. But it's been battled about dozens of times on the forums (including the very reasonable points you are making). It hasn't been solved, and the cynic in me says it won't ever be. -Steve
Re: @property Incorrectly Implemented?
On Tuesday, 6 September 2016 at 19:18:11 UTC, John wrote: Currently it seems that @property isn't implemented correctly. For some reason when you try to get the pointer of a property it returns a delegate for some reason. This just seems plain wrong, the whole purpose of a property is for a function to behave as if it weren't a function. There's also some inconsistencies in the behavior, "get" is implemented one way and then "set" is implemented another. http://ideone.com/ZgGT2G &t.x // returns "ref int delegate()" &t.x() // ok returns "int*", but defeats purpose of @property &(t.j = 10) // shouldn't this return "ref int delegate(int)" ? It would be nice to get this behavior fixed, so that it doesn't become set in stone. I think returning a delegate pointer is not what people would except nor is there really any use case for it. With properties, the & operator is the only way to have the function itself and not it's return value. The reason is that the return value of a function is not necessarily an lvalue, so taking its address is not always correct. Imagine this: @property int x() { return 3; } As 3 is an rvalue, you cannot take its address. That's the difference between a true field and a computed one. The purpose of properties is the following: struct S { @property int x() { /* whatever */ } int y() { /* whatever */ } } writeln(typeof(S.x).stringof); // prints int writeln(typeof(S.y).stringof); // prints int delegate()
Re: @property Incorrectly Implemented?
On Tuesday, September 06, 2016 19:18:11 John via Digitalmars-d wrote: > Currently it seems that @property isn't implemented correctly. > For some reason when you try to get the pointer of a property it > returns a delegate for some reason. This just seems plain wrong, > the whole purpose of a property is for a function to behave as if > it weren't a function. There's also some inconsistencies in the > behavior, "get" is implemented one way and then "set" is > implemented another. > > http://ideone.com/ZgGT2G > > &t.x // returns "ref int delegate()" > &t.x() // ok returns "int*", but defeats purpose of > @property > &(t.j = 10) // shouldn't this return "ref int delegate(int)" > ? > > It would be nice to get this behavior fixed, so that it doesn't > become set in stone. I think returning a delegate pointer is not > what people would except nor is there really any use case for it. Okay. How would it work to safely get a pointer to anything but the @property function when taking its address? &t.x() is just going to give you the address of the return value - which in most cases, is going to be a temporary, so if that even compiles in most cases, it's a bit scary. Sure, if the @property function returns by ref, then it can work, but an @property function which returns by ref isn't worth much, since you're then giving direct access to the member variable which is what an @property function is usually meant to avoid. If you wanted to do that, you could just use a public member variable. So, given that most @property functions are not going to return by ref, how does it make any sense at all for taking the address of an @property function to do anything different than give you a delegate? Sure, that's not what happens when you take the address of a variable, but you're not dealing with a variable. You're dealing with an @property function which is just trying to emulate a variable. The reality of the matter is that an @property function is _not_ a variable. It's just trying to emulate one, and that abstraction falls apart _really_ fast once you try and do much beyond getting and setting the value - e.g. passing by ref falls flat on its face. We could do better than currently do (e.g. making += lower to code that uses both the getter and the setter when the getter doesn't return by ref), but there are some areas where a property function simply can't act like a variable, because it isn't one. There isn't even a guarantee that an @property function is backed by memory. It could be a completely calculated value, in which case, expecting to get an address of a variable when taking the address of the @property function makes even less sense. - Jonathan M Davis
Re: @property Incorrectly Implemented?
On 09/06/2016 09:18 PM, John wrote: &(t.j = 10) // shouldn't this return "ref int delegate(int)" ? `&t.j` should and does. With `= 10`, it's definitely a call, just like `&t.x()`. It would be nice to get this behavior fixed, so that it doesn't become set in stone. Unfortunately, it already kinda is. Just flipping the switch would break circa all D code in existence. That's deemed unacceptable by the leadership, as far as I know. If this can even be fixed, it must be done very carefully. The -property compiler switch is currently being deprecated. Maybe it can be repurposed later on to change behavior to your liking. But that's at least a couple releases in the future, i.e. months, maybe years.
@property Incorrectly Implemented?
Currently it seems that @property isn't implemented correctly. For some reason when you try to get the pointer of a property it returns a delegate for some reason. This just seems plain wrong, the whole purpose of a property is for a function to behave as if it weren't a function. There's also some inconsistencies in the behavior, "get" is implemented one way and then "set" is implemented another. http://ideone.com/ZgGT2G &t.x // returns "ref int delegate()" &t.x() // ok returns "int*", but defeats purpose of @property &(t.j = 10) // shouldn't this return "ref int delegate(int)" ? It would be nice to get this behavior fixed, so that it doesn't become set in stone. I think returning a delegate pointer is not what people would except nor is there really any use case for it.
Re: `examplevalues` property
On Monday, 3 August 2015 at 14:30:43 UTC, Andrea Fontana wrote: On Monday, 3 August 2015 at 13:54:51 UTC, HaraldZealot wrote: You have to write the same amount of code. It's just one line for each type... Something like: [...] Many thanks, it seems like good workaround for my personal use case. But have something like that in Phobos were great from my POV.
Re: `examplevalues` property
On Monday, 3 August 2015 at 13:54:51 UTC, HaraldZealot wrote: On Monday, 3 August 2015 at 13:13:55 UTC, Andrea Fontana wrote: Why don't you use templates? Something like: enum ValueType { Init, Min, Max } auto exampleValues(T)() { T[ValueType] retVal; retVal[ValueType.Init] = T.init; static if (__traits(compiles, T.min)) retVal[ValueType.Min] = T.min; static if (__traits(compiles, T.max)) retVal[ValueType.Max] = T.max; return retVal; } exampleValues!int.writeln; exampleValues!string.writeln; Good solution! But there is something that not perfect: it can be customizable only with template specialization as I see. I want not only standard values like `init` `max` or `min` but also some example value like 1, 2, 3, 4, 5 for `int`. In last case your template solution not so convenient as desired (introduction in language feature like `.testValue1` seems ridiculous, and without that only template specialization can provide customization, as I have said). But this seems interesting direction, and easy to implement in object.d (without library implementation, this feature have little benefit). You have to write the same amount of code. It's just one line for each type... Something like: import std.traits; enum ValueType { Init, Min, Max } auto exampleValues(T)() { T[ValueType] retVal; retVal[ValueType.Init] = T.init; static if (__traits(compiles, T.min)) retVal[ValueType.Min] = T.min; static if (__traits(compiles, T.max)) retVal[ValueType.Max] = T.max; static if(isIntegral!T) return tuple!("defaults", "customs")(retVal, [1,2,3,4,5]); else static if(isFloatingPoint!T) return tuple!("defaults", "customs")(retVal, [1.0,2.0,T.nan]); else static if(isSomeString!T) return tuple!("defaults", "customs")(retVal, ["hello", "world"]); else return tuple!("defaults", "customs")(retVal, T[].init); }
Re: `examplevalues` property
On Monday, 3 August 2015 at 13:13:55 UTC, Andrea Fontana wrote: Why don't you use templates? Something like: enum ValueType { Init, Min, Max } auto exampleValues(T)() { T[ValueType] retVal; retVal[ValueType.Init] = T.init; static if (__traits(compiles, T.min)) retVal[ValueType.Min] = T.min; static if (__traits(compiles, T.max)) retVal[ValueType.Max] = T.max; return retVal; } exampleValues!int.writeln; exampleValues!string.writeln; Good solution! But there is something that not perfect: it can be customizable only with template specialization as I see. I want not only standard values like `init` `max` or `min` but also some example value like 1, 2, 3, 4, 5 for `int`. In last case your template solution not so convenient as desired (introduction in language feature like `.testValue1` seems ridiculous, and without that only template specialization can provide customization, as I have said). But this seems interesting direction, and easy to implement in object.d (without library implementation, this feature have little benefit).
Re: `examplevalues` property
On Monday, 3 August 2015 at 12:13:15 UTC, HaraldZealot wrote: I found myself in situation that were good that all types support `.examplevalues` property in unittest version. This property will return array of predefined values for specified type (we can even have some convention like `examplevalues[0]` is `init`, `examplevalues[1]` is `min` (for numerical type) an so on). If custom types doesn't redefine this property the array consist only from `init`. The use case for this: templated struct or class with container-like semantics and internal unittest for method of such class. Thoughts? Why don't you use templates? Something like: enum ValueType { Init, Min, Max } auto exampleValues(T)() { T[ValueType] retVal; retVal[ValueType.Init] = T.init; static if (__traits(compiles, T.min)) retVal[ValueType.Min] = T.min; static if (__traits(compiles, T.max)) retVal[ValueType.Max] = T.max; return retVal; } exampleValues!int.writeln; exampleValues!string.writeln;
`examplevalues` property
I found myself in situation that were good that all types support `.examplevalues` property in unittest version. This property will return array of predefined values for specified type (we can even have some convention like `examplevalues[0]` is `init`, `examplevalues[1]` is `min` (for numerical type) an so on). If custom types doesn't redefine this property the array consist only from `init`. The use case for this: templated struct or class with container-like semantics and internal unittest for method of such class. Thoughts?
Re: What's the story with -property?
On Tue, 30 Jun 2015 08:03:00 -0400, Steven Schveighoffer wrote: > On 6/28/15 10:25 PM, ketmar wrote: >> and i found some invalid "front" usage in Phobos by the way (aka >> `front()`). > > Have you filed an issue for this? If not, please do. oops. sorry, i simply bolted a fixes in my branch and forgot about that (actually, noting "fill a bug later"). i'll go thru it in weekend to see what is left unfixed and will fill a PR. tnx for reminding me about that. signature.asc Description: PGP signature
Re: What's the story with -property?
"will open a ticket", i meant. ;-) signature.asc Description: PGP signature
Re: What's the story with -property?
On 6/28/15 10:25 PM, ketmar wrote: and i found some invalid "front" usage in Phobos by the way (aka `front()`). Have you filed an issue for this? If not, please do. -Steve
Re: What's the story with -property?
On Sun, 28 Jun 2015 00:36:41 +, Jonathan M Davis wrote: > Full property enforcement would fix these issues, but we're never going > to get it. i must admit that Kenji's patch (referred by OP) is the best solution i've seen. it fixes the most annoying thing with delegate properties, and it can be easily tuned to emit a warning or deprecation on calling properties with "()". i incorporated that patch in my fork and did exactly that: turned errors to warnings. and i must say that i'm still able to compile majority of D code without any problems. and i found some invalid "front" usage in Phobos by the way (aka `front()`). also, warning warns about "()()" on delegate property, or about "()" on delegate property, depending of module being marked as "modern" or not. so far i found zero problems with it. yet the patch seems to be rejected by W&A without any sane reason. ah, yes, the thing that *can* cause same havok was pointed by Kenji himself [1]. i hit it once or twice, and it's still solvable with warning and deprecation cycle. [1] https://github.com/D-Programming-Language/dmd/ pull/2305#issuecomment-20657962 signature.asc Description: PGP signature
Re: What's the story with -property?
On Saturday, 27 June 2015 at 22:55:48 UTC, Mike wrote: There's a regression involving `-property` at https://issues.dlang.org/show_bug.cgi?id=14564. In that issue, it's stated by a reputable source that `-property` is going away. It was also stated in IRC that it never worked anyway. So, what's the story on `-property`? Is it going away? Is the regression worth investing time in? There's also a DMD pull request that, unfortunately, was not followed through on: https://github.com/D-Programming-Language/dmd/pull/2305 Please advise. Thanks, Mike http://wiki.dlang.org/Property_Discussion_Wrap-up
Re: What's the story with -property?
On Sunday, 28 June 2015 at 00:25:47 UTC, Jonathan M Davis wrote: [snip] it's an open question as to whether any kind of property enforcement will ever be in I should probably note that a long term consequence of not having full property enforcement is that whether parens are used or not in generic code is going to be a problem. For, instance, template isInputRange(R) { enum bool isInputRange = is(typeof( (inout int = 0) { R r = R.init; // can define a range object if (r.empty) {} // can test for empty r.popFront(); // can invoke popFront() auto h = r.front; // can get the front of the range })); } requires that empty and front be called without parens, which means that front and empty can be enums or variables or anything else which is going to fit the syntax in the code above and not just functions. So, you can't _ever_ be calling front or empty with parens in generic code if you want your code to work with ranges in general rather than the small set of ranges that you might be using at the moment. But the compiler doesn't enforce that right now at all. It just enforces that the ranges themselves be such that front and empty be usable without parens. In addition, it requires that popFront be used _with_ parens, but the only case where it would break code if you didn't would be if someone had declared popFront as callable rather than a function, since using it without parens as a function would work - but not as callable. Now, realistically, pretty much no one is going to do that, but technically, according to the API requirements, it's perfectly legitimate to do so, and the compiler doesn't protect against anyone from writing code which calls popFront without parens. Full property enforcement would fix these issues, but we're never going to get it. So, we will always have to worry about generic code which uses parens where it shouldn't or doesn't use them where it should. How big an issue this will be is an open question, but being lax with syntax (like we are with parens on functions) doesn't jive well with generic code, so it's something that we're going to have to watch out for. - Jonathan M Davis
Re: What's the story with -property?
On Saturday, 27 June 2015 at 22:55:48 UTC, Mike wrote: There's a regression involving `-property` at https://issues.dlang.org/show_bug.cgi?id=14564. In that issue, it's stated by a reputable source that `-property` is going away. It was also stated in IRC that it never worked anyway. So, what's the story on `-property`? Is it going away? Is the regression worth investing time in? There's also a DMD pull request that, unfortunately, was not followed through on: https://github.com/D-Programming-Language/dmd/pull/2305 It was never intended that -property be kept. It was always intended to be temporary. The only question at this point is what behavior the compiler will have normally. Originally, property functions were inferred by the language. The compiler would treat any function with no arguments as a getter property and any function with a single argument as a setter, but this isn't particularly principled, and it allowed nonsense like writeln = 7; Also, you have the problem of a getter property which returns a delegate. What does this do? foo.delegProp(); It just calls delegProp and does nothing with the return value. If you want to actually call it, you have to use two sets of parens. foo.delegProp()(); And that pretty much destroys the ability to have property functions which return a delegate or other callable. So, @property was proposed to fix these issues. It would be what was used to indicate that a function was a property function, and we wouldn't have the compiler inferring property functions anymore. So, in theory, it would then be illegal to call an @property function with parens (thus ensuring that if parens were used, they were used on the return value), and it would be illegal to call a normal function without parens, since it wasn't a property function anymore. However, this was somewhat controversial (with some being _very_ much in favor of it and others not being very happy about it), and more importantly, it was a breaking change. So, when @property was introduced, it didn't do much of anything. It was going to at some point, but it didn't then. So, later, in order to combat the issue with breaking changes, -property was introduced with the idea that it would have property enforcement, and we'd have the chance to iron it all out there before making the compiler act that way all the time. However, -property did only partial property enforcement. It just made it so that you couldn't call a normal function with parens. It did nothing to ensure that an @property function was called without parens. And it was never completed, leaving @property as doing almost nothing normally and -property not really doing its job (@property does affect some aspects of compile-time introspection such as typeof but outside of -property, it has _no_ effect on how functions are called). And this controversial issue only got worse when we added UFCS to the language rather than just supporting the member call syntax with arrays, because then all of a sudden, folks were writing code like auto foo = range.map!(a => a % 100)(); And they thought that the extra parens on templated functions like map were ugly, so people started doing stuff like auto foo = range.map!(a => a %100); So, the idea that enforcing that non-property functions be called with parens became less and less popular - and remember that that's the only thing that -property actually checks right now. Also, arguments on @property never went anywhere useful, because there were folks on both sides of the argument (and several spots in between), and many felt very strongly on the issue. In addition, Andrei has never liked the idea of @property, so nothing really ever happened, and we've gotten less and less willing to break code as time has gone on, meaning that the willingness to switch to full property enforcement (or even partial property enforcement) has decreased as well. The _most_ that we could get at this point would be to have it enforced that @property functions be called without parens without requiring that non-property functions be called with parens (UFCS has simply made it too popular to leave off the parens) and possibly requiring that @property be used in order to use the property setter syntax. However, even that would break code, so it's questionable as to whether that would occur. It's almost a guarantee that @property will at some point affect functions which return callables and interpret their first set of parens as calling their return value, since without that, we can't treat functions which return callables as property functions, but beyond that, it's an open question as to whether any kind of property enforcement will ever be in place. Regardless, as it's a guarantee at this point that we're not going to require
Re: What's the story with -property?
On Saturday, 27 June 2015 at 22:55:48 UTC, Mike wrote: There's a regression involving `-property` at https://issues.dlang.org/show_bug.cgi?id=14564. In that issue, it's stated by a reputable source that `-property` is going away. It was also stated in IRC that it never worked anyway. So, what's the story on `-property`? Is it going away? Is the regression worth investing time in? There's also a DMD pull request that, unfortunately, was not followed through on: https://github.com/D-Programming-Language/dmd/pull/2305 Please advise. Thanks, Mike Definition of property is completely inconsistent. Definition of property with -property is also inconsistent. No desire to get toward a more consistent position from leadership. Having 2 definition for the thing is bad for the language as it create fragmentation. If I'd had to choose I'd keep the -property behavior, but it seems like a lost battle at this point :(
What's the story with -property?
There's a regression involving `-property` at https://issues.dlang.org/show_bug.cgi?id=14564. In that issue, it's stated by a reputable source that `-property` is going away. It was also stated in IRC that it never worked anyway. So, what's the story on `-property`? Is it going away? Is the regression worth investing time in? There's also a DMD pull request that, unfortunately, was not followed through on: https://github.com/D-Programming-Language/dmd/pull/2305 Please advise. Thanks, Mike
Re: Walter & Andrei: @property
On Thursday, 16 April 2015 at 14:40:38 UTC, John Colvin wrote: For cross-referencing purposes, an unpleasant consequence of the current situation: http://forum.dlang.org/post/rfrhuipeaoswqsunu...@forum.dlang.org struct Foo { bool registered = false; void register(bool x) @property { writeln("Registering ", x); register = true; } } Like this?
Re: Walter & Andrei: @property
On 4/16/15 7:40 AM, John Colvin wrote: On Tuesday, 14 April 2015 at 11:54:11 UTC, John Colvin wrote: This is a specific request to Walter and Andrei, not a call for yet another massive debate. I'm pretty sure every view has been heard already, many times over. Walter/Andrei, can you take a final decision on this? You put a lot of effort in to DIP23 and it's just sitting there. It's a subjective topic that's been beaten to death by the community multiple times; there will never be consensus so it's a job for leadership. P.S. I noticed something missing from DIP23: How do I take an alias of an @property function? Or a 0-arg member function? Or a 1-arg free function? Another way of putting it would be: is there a way to refer to the name of a function that doesn't require parens? Name as in pass-by-name. For cross-referencing purposes, an unpleasant consequence of the current situation: http://forum.dlang.org/post/rfrhuipeaoswqsunu...@forum.dlang.org Yah, saw that. It's an unforced error in the design of D. -- Andrei
Re: Walter & Andrei: @property
On Tuesday, 14 April 2015 at 11:54:11 UTC, John Colvin wrote: This is a specific request to Walter and Andrei, not a call for yet another massive debate. I'm pretty sure every view has been heard already, many times over. Walter/Andrei, can you take a final decision on this? You put a lot of effort in to DIP23 and it's just sitting there. It's a subjective topic that's been beaten to death by the community multiple times; there will never be consensus so it's a job for leadership. P.S. I noticed something missing from DIP23: How do I take an alias of an @property function? Or a 0-arg member function? Or a 1-arg free function? Another way of putting it would be: is there a way to refer to the name of a function that doesn't require parens? Name as in pass-by-name. For cross-referencing purposes, an unpleasant consequence of the current situation: http://forum.dlang.org/post/rfrhuipeaoswqsunu...@forum.dlang.org
Re: Walter & Andrei: @property
On 4/14/15 4:54 AM, John Colvin wrote: This is a specific request to Walter and Andrei, not a call for yet another massive debate. I'm pretty sure every view has been heard already, many times over. Walter/Andrei, can you take a final decision on this? You put a lot of effort in to DIP23 and it's just sitting there. It's a subjective topic that's been beaten to death by the community multiple times; there will never be consensus so it's a job for leadership. P.S. I noticed something missing from DIP23: How do I take an alias of an @property function? Or a 0-arg member function? Or a 1-arg free function? Another way of putting it would be: is there a way to refer to the name of a function that doesn't require parens? Name as in pass-by-name. Yah, I consider @property an unfinished affair that needs finishing. Maybe I'll work on it for the hackathon. -- Andrei
Walter & Andrei: @property
This is a specific request to Walter and Andrei, not a call for yet another massive debate. I'm pretty sure every view has been heard already, many times over. Walter/Andrei, can you take a final decision on this? You put a lot of effort in to DIP23 and it's just sitting there. It's a subjective topic that's been beaten to death by the community multiple times; there will never be consensus so it's a job for leadership. P.S. I noticed something missing from DIP23: How do I take an alias of an @property function? Or a 0-arg member function? Or a 1-arg free function? Another way of putting it would be: is there a way to refer to the name of a function that doesn't require parens? Name as in pass-by-name.
Re: Read-only property without @property
On 9/27/14 3:45 AM, Daniel Murphy wrote: "H. S. Teoh via Digitalmars-d" wrote in message news:mailman.1799.1411796077.5783.digitalmar...@puremagic.com... Argh, looks like another incompletely-implemented part of the compiler: void fun() @safe { union U { int p; int* q; } U u; u.p++; // compiles u.q = null; // compiles *u.q++; // x.d(9): Error: field U.q cannot be accessed in @safe code because > it overlaps with a pointer I think that this is equivalent to u.q++, since the ++ does not apply to the pointed-at variable, but at the pointer itself. Weird, my tests showed that this was allowed. More testing, I realize it's because it's a class variable. This code compiles and runs: class Foo { union { int x; int *p; } void foo() @safe {*p = 5;} } void main() @safe { auto f = new Foo; f.foo(); } Which is similar to this code that does not: void main() @safe { union U { int x; int *p; } U u; *u.p = 5; // error } Without unions, you can't create invalid pointers in @safe code. With unions, you can, but you can't access them. The above shows you can in some situations, but I think that is a bug. -Steve
Re: Read-only property without @property
"H. S. Teoh via Digitalmars-d" wrote in message news:mailman.1799.1411796077.5783.digitalmar...@puremagic.com... Argh, looks like another incompletely-implemented part of the compiler: void fun() @safe { union U { int p; int* q; } U u; u.p++; // compiles u.q = null; // compiles *u.q++; // x.d(9): Error: field U.q cannot be accessed in @safe code because > it overlaps with a pointer } This looks perfectly fine to me. Consider if you replaced all uses of the union with multiple variables and explicit casts: int p; int* q; p++; // fine, of course q++; // also fine p = 0; q = null; // both of these are fine, because they don't read anything from the union. // worst case, p was the last value assigned to *(*cast(int**)&p)++; // The cast can't be @safe Without unions, you can't create invalid pointers in @safe code. With unions, you can, but you can't access them.
Re: Read-only property without @property
On Sat, Sep 27, 2014 at 12:43:19AM -0400, Steven Schveighoffer via Digitalmars-d wrote: > On 9/26/14 9:26 PM, H. S. Teoh via Digitalmars-d wrote: > > >Not a bad start. Though I do note that *declaring* an unsafe union > >(according to the above definitions) is currently allowed in @safe > >code by the compiler, but attempts to access a union member that > >overlaps with a pointer is rejected. > > It makes sense that you can declare unsafe unions, because a > declaration itself isn't @safe, it's only code that is. > > But my attempts to test this haven't yielded an error. > > e.g.: > > class Foo > { > union { > private int _a; > public int *a; > } > > void setA(int x) @safe { *a = x;} > } > > no complaints... Argh, looks like another incompletely-implemented part of the compiler: void fun() @safe { union U { int p; int* q; } U u; u.p++; // compiles u.q = null; // compiles *u.q++; // x.d(9): Error: field U.q cannot be accessed in @safe code because it overlaps with a pointer } While it sorta makes sense in its own way that it's OK to mess around with the union as long as you don't actually try to dereference an overlapped pointer, the error message inspires no confidence that this was actually intentional. :-( On the contrary, it sounds like u.p++ and u.q = null was supposed to be rejected as well, but for some reason aren't. > >IOW, the compiler doesn't refuse definitions of potentially unsafe > >unions, as long as you don't actually try to do something unsafe with > >them. That might make unions more useful (they can be passed around > >in @safe code as long as certain operations are avoided), but > >probably also trickier to implement correctly. > > I think it *should* be that way, but I'm not convinced it is yet. [...] Apparently I hit jackpot in attempting to try dereferencing an overlapped pointer first. All the other cases seem to be unimplemented! I can't decide whether or not this should be filed as a bug or an enhancement request, because currently we have the paradoxical situation where @safe code isn't actually allowed to *dereference* an overlapped pointer, but it *can* stomp all over the pointer by writing garbage to overlapping fields so that @system callers can totally screw themselves over when they dereference it! T -- Knowledge is that area of ignorance that we arrange and classify. -- Ambrose Bierce
Re: Read-only property without @property
On 9/26/14 9:26 PM, H. S. Teoh via Digitalmars-d wrote: Not a bad start. Though I do note that *declaring* an unsafe union (according to the above definitions) is currently allowed in @safe code by the compiler, but attempts to access a union member that overlaps with a pointer is rejected. It makes sense that you can declare unsafe unions, because a declaration itself isn't @safe, it's only code that is. But my attempts to test this haven't yielded an error. e.g.: class Foo { union { private int _a; public int *a; } void setA(int x) @safe { *a = x;} } no complaints... > IOW, the compiler doesn't refuse definitions of potentially unsafe unions, as long as you don't actually try to do something unsafe with them. That might make unions more useful (they can be passed around in @safe code as long as certain operations are avoided), but probably also trickier to implement correctly. I think it *should* be that way, but I'm not convinced it is yet. -Steve
Re: Read-only property without @property
On Friday, 26 September 2014 at 19:47:15 UTC, Steven Schveighoffer wrote: I wanted to bring this over from D.learn, because I've never seen this before, and it's an interesting solution to creating a property without much boilerplate. So here it is: class Foo { union { private int _a; // accessible only in this module public const int a; // accessible from anywhere, but read only } } And it works now, probably has for a while. Thoughts? This can easily be boilerplated in something like roprop!(int, "a") I am really not sure what union does to compiler optimization or runtime concerns, if it has any significant drawbacks. From what I can tell, it's a valid solution. Credit to Mark Schütz for the idea. -Steve Thanks, I love this! There is actually a very important ABI difference, in all other "property" implementations in other languages(of which I'm aware), the ABI is changed to be a method rather than a member, for this reason I think we shouldn't refer to this feature as a "property", maybe "field/member" is more appropriate? Both properties and "access restricted fields" has their place depending on what one is trying to accomplish, but in most cases I find myself wanting this very feature and not normal properties. I couldn't resist trying this in C++, clang rejected it outright, GCC let it through with a warning.
Re: Read-only property without @property
On 9/26/14, 6:18 PM, Steven Schveighoffer wrote: 1. A union of any number of non-reference types with the same mutability throughout is @safe, even if the type varies. 2. A union of two non-reference types, in which one union member has some bytes defined as mutable, and another union member has those same bytes defined as immutable, is un-@safe. Const union members will not disqualify the union. 3. A union of any number of pointer types which point at the same type, but vary only by const, are @safe, unless at least one member is mutable and at least one member is immutable. 4. Everything else is un-@safe This may break some code, but I think it would define good starting rules to allow this in @safe code. Nice! We need a complete set of rules for this stuff. -- Andrei
Re: Read-only property without @property
On 9/26/14, 5:58 PM, H. S. Teoh via Digitalmars-d wrote: On Fri, Sep 26, 2014 at 07:32:49PM -0400, Steven Schveighoffer via Digitalmars-d wrote: On 9/26/14 6:32 PM, H. S. Teoh via Digitalmars-d wrote: Does the compiler infer it as @safe, though? Hm... good point, I'm not sure if unions are considered @safe. But I think that would be a decent enhancement request if not. [...] union U { int* ptr; long i; } void main() @safe { U u; u.i = 12345; *u.ptr = 54321; // this can't possibly be @safe } How would the compiler decide which union operations are @safe and which are not? Unions mixing pointers and integrals aren't safe. Those mixing e.g. a float and an int are. -- Andrei
Re: Read-only property without @property
On Friday, 26 September 2014 at 22:58:53 UTC, Cliff wrote: This is a clever syntax, but I can't say I particularly care for it since it aliases two names for the same location which differ only in their visibility, and this feels... wrong to me somehow. In C# this is a sufficiently common practice that the property syntax allows for it directly: class Foo { int A { get; private set; } } The compiler automatically creates a (hidden) backing property (this is an implementation detail of course), both internal and external customers use the same name, and there is no redundancy. If I were to compare the D way and the C# way, I would prefer to C# way for this trivial-property case. What I would NOT want is C#'s special handling of properties to go along with it - a D analog would preserve A's access methods and handling as if it were a field if that was the user's wish. That's my $0.02. C#'s way of declaring properties is something I've been missing in D for a long time. Using a mixin is just plain ugly and breaks tooling, yet this is such a common thing to have to do. It is quite disappointing that there's no shorthand for it, like '@property int a;' or '@property(readonly) int b'. (On that matter, I'm not a fan in general of properties being various methods glued together by an @property, but that's set in stone by now.)
Re: Read-only property without @property
On Fri, Sep 26, 2014 at 06:20:46PM -0700, H. S. Teoh via Digitalmars-d wrote: [...] > union U { > void delegate() @system sysDg; > void delegate() @safe safeDg; > } > > Is this union @safe or not? Technically, it should be, since there's no > possibility of getting an invalid pointer to delegate using U. However, > it also breaks @safe-ty if you assign U.sysDg and call U.safeDg. (This > is currently accepted by the compiler, btw. In @safe code.) https://issues.dlang.org/show_bug.cgi?id=13536 > And what of: > > union U { > immutable int x; > int y; > } > > ? This one breaks the type system. It's certainly @safe, but has other > issues. (The compiler happily accepts this one, BTW.) https://issues.dlang.org/show_bug.cgi?id=13537 T -- It is the quality rather than the quantity that matters. -- Lucius Annaeus Seneca
Re: Read-only property without @property
On Fri, Sep 26, 2014 at 09:18:28PM -0400, Steven Schveighoffer via Digitalmars-d wrote: > On 9/26/14 8:58 PM, H. S. Teoh via Digitalmars-d wrote: > >On Fri, Sep 26, 2014 at 07:32:49PM -0400, Steven Schveighoffer via > >Digitalmars-d wrote: > >>On 9/26/14 6:32 PM, H. S. Teoh via Digitalmars-d wrote: > >> > >>>Does the compiler infer it as @safe, though? > >> > >>Hm... good point, I'm not sure if unions are considered @safe. But I > >>think that would be a decent enhancement request if not. > >[...] > > > > union U { > > int* ptr; > > long i; > > } > > > > void main() @safe { > > U u; > > u.i = 12345; > > *u.ptr = 54321; // this can't possibly be @safe > > } > > > >How would the compiler decide which union operations are @safe and which > >are not? > > Well, if all unions members are of the same base type, and they only differ > by const (and by that I mean, const combined with either mutable or > immutable), then it should be safe. > > So generically, these are @safe: > > union > { >T t1; >const T t2; > } > > union > { >immutable T t1; >const T t2; > } > > This is not: > > union > { >T t1; >immutable T t2; > } > > checking current rules... > > looks like @safe code doesn't flag unions as unsafe anywhere. I was > even able to dereference pointers that were union'd with ints. > > But really, I think the most useful @safe rules would be: > > 1. A union of any number of non-reference types with the same > mutability throughout is @safe, even if the type varies. > 2. A union of two non-reference types, in which one union member has > some bytes defined as mutable, and another union member has those same > bytes defined as immutable, is un-@safe. Const union members will not > disqualify the union. > 3. A union of any number of pointer types which point at the same > type, but vary only by const, are @safe, unless at least one member is > mutable and at least one member is immutable. > 4. Everything else is un-@safe > > This may break some code, but I think it would define good starting > rules to allow this in @safe code. [...] Not a bad start. Though I do note that *declaring* an unsafe union (according to the above definitions) is currently allowed in @safe code by the compiler, but attempts to access a union member that overlaps with a pointer is rejected. IOW, the compiler doesn't refuse definitions of potentially unsafe unions, as long as you don't actually try to do something unsafe with them. That might make unions more useful (they can be passed around in @safe code as long as certain operations are avoided), but probably also trickier to implement correctly. T -- Music critic: "That's an imitation fugue!"
Re: Read-only property without @property
On Fri, Sep 26, 2014 at 05:35:20PM -0700, Andrei Alexandrescu via Digitalmars-d wrote: > On 9/26/14, 4:32 PM, Steven Schveighoffer wrote: > >On 9/26/14 6:32 PM, H. S. Teoh via Digitalmars-d wrote: > > > >>Does the compiler infer it as @safe, though? > > > >Hm... good point, I'm not sure if unions are considered @safe. But I > >think that would be a decent enhancement request if not. > > I'd say certain unions may be deemed safe. -- Andrei Hmm. I tried playing with the idea of unions being safe if all members have the same unqualified type, but quickly ran into some nasty cases: union U { void delegate() @system sysDg; void delegate() @safe safeDg; } Is this union @safe or not? Technically, it should be, since there's no possibility of getting an invalid pointer to delegate using U. However, it also breaks @safe-ty if you assign U.sysDg and call U.safeDg. (This is currently accepted by the compiler, btw. In @safe code.) And what of: union U { immutable int x; int y; } ? This one breaks the type system. It's certainly @safe, but has other issues. (The compiler happily accepts this one, BTW.) I think bug reports are in order. :-) There's also the question of what to do with class references: class Base {} class Derived : Base {} union U { Base b; Derived d; // fortunately, the compiler rejects this } I'm sure there are many more such tricky corner cases that people can dream up if they only use their imagination a little. 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.
Re: Read-only property without @property
On 9/26/14 8:58 PM, H. S. Teoh via Digitalmars-d wrote: On Fri, Sep 26, 2014 at 07:32:49PM -0400, Steven Schveighoffer via Digitalmars-d wrote: On 9/26/14 6:32 PM, H. S. Teoh via Digitalmars-d wrote: Does the compiler infer it as @safe, though? Hm... good point, I'm not sure if unions are considered @safe. But I think that would be a decent enhancement request if not. [...] union U { int* ptr; long i; } void main() @safe { U u; u.i = 12345; *u.ptr = 54321; // this can't possibly be @safe } How would the compiler decide which union operations are @safe and which are not? Well, if all unions members are of the same base type, and they only differ by const (and by that I mean, const combined with either mutable or immutable), then it should be safe. So generically, these are @safe: union { T t1; const T t2; } union { immutable T t1; const T t2; } This is not: union { T t1; immutable T t2; } checking current rules... looks like @safe code doesn't flag unions as unsafe anywhere. I was even able to dereference pointers that were union'd with ints. But really, I think the most useful @safe rules would be: 1. A union of any number of non-reference types with the same mutability throughout is @safe, even if the type varies. 2. A union of two non-reference types, in which one union member has some bytes defined as mutable, and another union member has those same bytes defined as immutable, is un-@safe. Const union members will not disqualify the union. 3. A union of any number of pointer types which point at the same type, but vary only by const, are @safe, unless at least one member is mutable and at least one member is immutable. 4. Everything else is un-@safe This may break some code, but I think it would define good starting rules to allow this in @safe code. -Steve
Re: Read-only property without @property
On Fri, Sep 26, 2014 at 07:32:49PM -0400, Steven Schveighoffer via Digitalmars-d wrote: > On 9/26/14 6:32 PM, H. S. Teoh via Digitalmars-d wrote: > > >Does the compiler infer it as @safe, though? > > Hm... good point, I'm not sure if unions are considered @safe. But I > think that would be a decent enhancement request if not. [...] union U { int* ptr; long i; } void main() @safe { U u; u.i = 12345; *u.ptr = 54321; // this can't possibly be @safe } How would the compiler decide which union operations are @safe and which are not? T -- He who laughs last thinks slowest.
Re: Read-only property without @property
On 9/26/14, 4:32 PM, Steven Schveighoffer wrote: On 9/26/14 6:32 PM, H. S. Teoh via Digitalmars-d wrote: Does the compiler infer it as @safe, though? Hm... good point, I'm not sure if unions are considered @safe. But I think that would be a decent enhancement request if not. I'd say certain unions may be deemed safe. -- Andrei
Re: Read-only property without @property
On 9/26/14 6:32 PM, H. S. Teoh via Digitalmars-d wrote: Does the compiler infer it as @safe, though? Hm... good point, I'm not sure if unions are considered @safe. But I think that would be a decent enhancement request if not. -Steve
Re: Read-only property without @property
On Friday, 26 September 2014 at 19:47:15 UTC, Steven Schveighoffer wrote: I wanted to bring this over from D.learn, because I've never seen this before, and it's an interesting solution to creating a property without much boilerplate. So here it is: class Foo { union { private int _a; // accessible only in this module public const int a; // accessible from anywhere, but read only } } And it works now, probably has for a while. Thoughts? This can easily be boilerplated in something like roprop!(int, "a") I am really not sure what union does to compiler optimization or runtime concerns, if it has any significant drawbacks. From what I can tell, it's a valid solution. Credit to Mark Schütz for the idea. -Steve This is a clever syntax, but I can't say I particularly care for it since it aliases two names for the same location which differ only in their visibility, and this feels... wrong to me somehow. In C# this is a sufficiently common practice that the property syntax allows for it directly: class Foo { int A { get; private set; } } The compiler automatically creates a (hidden) backing property (this is an implementation detail of course), both internal and external customers use the same name, and there is no redundancy. If I were to compare the D way and the C# way, I would prefer to C# way for this trivial-property case. What I would NOT want is C#'s special handling of properties to go along with it - a D analog would preserve A's access methods and handling as if it were a field if that was the user's wish. That's my $0.02.
Re: Read-only property without @property
On Fri, Sep 26, 2014 at 03:47:15PM -0400, Steven Schveighoffer via Digitalmars-d wrote: > I wanted to bring this over from D.learn, because I've never seen this > before, and it's an interesting solution to creating a property > without much boilerplate. > > So here it is: > > class Foo > { >union >{ > private int _a; // accessible only in this module > public const int a; // accessible from anywhere, but read only >} > } [...] Very clever use of union to mean "this variable has two interpretations: a public, read-only one, and a private, read-write one". I like it! Even ddocs for the const "aspect" of 'a' turn out exactly like a normal member! Does the compiler infer it as @safe, though? T -- "No, John. I want formats that are actually useful, rather than over-featured megaliths that address all questions by piling on ridiculous internal links in forms which are hideously over-complex." -- Simon St. Laurent on xml-dev
Re: Read-only property without @property
On Fri, 26 Sep 2014 15:47:15 -0400 Steven Schveighoffer via Digitalmars-d wrote: > Thoughts? This can easily be boilerplated in something like > roprop!(int, "a") interesting thing. yet i want third arg to roprop. ;-) signature.asc Description: PGP signature
Re: Read-only property without @property
On Fri, 26 Sep 2014 22:09:12 + John Colvin via Digitalmars-d wrote: > Are my fears misplaced? it should not incur any problems. and if such code faults, it's a bug in compiler which must be fixed. if we'll start to use such things, possible bugs will be ironed out. signature.asc Description: PGP signature
Re: Read-only property without @property
On Friday, 26 September 2014 at 19:47:15 UTC, Steven Schveighoffer wrote: I wanted to bring this over from D.learn, because I've never seen this before, and it's an interesting solution to creating a property without much boilerplate. So here it is: class Foo { union { private int _a; // accessible only in this module public const int a; // accessible from anywhere, but read only } } And it works now, probably has for a while. Thoughts? This can easily be boilerplated in something like roprop!(int, "a") I am really not sure what union does to compiler optimization or runtime concerns, if it has any significant drawbacks. From what I can tell, it's a valid solution. Credit to Mark Schütz for the idea. -Steve I've often thought of such approaches, but not used them for fear of causing some horrible undefined behaviour (whether intentional or via a compiler bug). Are my fears misplaced?
Re: Read-only property without @property
On 9/26/14, 12:47 PM, Steven Schveighoffer wrote: I wanted to bring this over from D.learn, because I've never seen this before, and it's an interesting solution to creating a property without much boilerplate. So here it is: class Foo { union { private int _a; // accessible only in this module public const int a; // accessible from anywhere, but read only } } And it works now, probably has for a while. Thoughts? This can easily be boilerplated in something like roprop!(int, "a") I am really not sure what union does to compiler optimization or runtime concerns, if it has any significant drawbacks. From what I can tell, it's a valid solution. Credit to Mark Schütz for the idea. Very interesting!! -- Andrei
Read-only property without @property
I wanted to bring this over from D.learn, because I've never seen this before, and it's an interesting solution to creating a property without much boilerplate. So here it is: class Foo { union { private int _a; // accessible only in this module public const int a; // accessible from anywhere, but read only } } And it works now, probably has for a while. Thoughts? This can easily be boilerplated in something like roprop!(int, "a") I am really not sure what union does to compiler optimization or runtime concerns, if it has any significant drawbacks. From what I can tell, it's a valid solution. Credit to Mark Schütz for the idea. -Steve
opDispatch apparently has SFINAE property
opDispatch behaves as though it has SFINAE. When something fails in the definition (like I am having now, some of the symbols I used in it hadn't been imported) there won't ever be an error message, I just get "Error: no property 'bar' for type 'Foo'" In one case I had to use static ifs and pragmas and static assert(0) to get error messages out of opDispatch because static assert messages were being suppressed. Often I just avoid opDispatch altogether (despite it being a killer feature otherwise) and just generate code with string mixins, because they are actually easier to debug (and they are not easy to debug). I found this https://issues.dlang.org/show_bug.cgi?id=8387 and cast a vote for it. 4 other people have, too, and the bug has 4 duplicates, and has been open since 2012.
Re: UFCS & overloaded property getters/setters
On 2014-06-13 20:16, H. S. Teoh via Digitalmars-d wrote: I think this is starting to show itself as an anti-pattern, or at least, one of those obscure dark corners of D infested with complex interactions between unexpected features and possible compiler quirks. Probably the best thing to do is to make both getter and setter final, and add an overloadable onPropSet() method that the derived class can use to customize the property. I don't think this is the case here. It is as Jonathan described it. A base class and a subclass have different overload sets [1]. [1] http://dlang.org/hijack.html search for "Derived Class Member Function Hijacking" -- /Jacob Carlborg
Re: UFCS & overloaded property getters/setters
On 2014-06-13 16:39:04 +, H. S. Teoh via Digitalmars-d said: Basically, once the derived class overrides the property setter, the (un-overridden) base class getter somehow becomes shadowed as well, and references to .prop will cause a compile error saying that Derived.prop can't be called without parameters. So, what's going on here? Should this code be accepted? Is this a compiler / language bug? A deliberate @property limitation? Or just more evidence @property should be taken out the back and shot? T I had absolutely no problems with the following code. Note where and how the alias for prop is located. import std.stdio; class Base { int propImpl; final @property int prop() { writefln("hihihi!"); return propImpl; } @property void prop(int newVal) { propImpl = newVal; } void someMethod() { auto x = prop; // OK, calls Base.prop() prop = x; // OK, calls Base.prop(int) } } class Derived : Base { alias prop = super.prop; override @property void prop(int newVal) { super.prop(newVal); writefln("Hello!"); } void someOtherMethod() { auto x = prop; // NG - compile error *** auto y = super.prop; // OK, calls Base.prop() prop = x; // OK, calls Derived.prop() } } void main() { auto foo = new Derived(); foo.someOtherMethod(); }
Re: UFCS & overloaded property getters/setters
On Friday, 13 June 2014 at 18:18:21 UTC, H. S. Teoh via Digitalmars-d wrote: Aliasing super.prop to .prop in the derived class didn't work, in fact, it made things worse; now I have an infinite loop because all occurrences of .prop get redirected back to the base class (including the setter), and there is no way to alias only the non-overridden getter overload, so a call to Derived.prop will end up in the base class method where it shouldn't. Works for me. Following code prints base getter base getter derived setter Am I missing something? import std.stdio; class Base { int propImpl; final @property int prop() { writeln("base getter"); return propImpl; } @property void prop(int newVal) { writeln("base setter"); propImpl = newVal; } } class Derived : Base { alias prop = super.prop; override @property void prop(int newVal) { writeln("derived setter"); //super.prop(newVal); //doSomethingElse(newVal); } void someOtherMethod() { auto x = prop; auto y = super.prop; prop = x; } } void main() { auto d = new Derived; d.someOtherMethod(); }
Re: UFCS & overloaded property getters/setters
Odd, I thought you weren't able to override only a single overload of a property? I might be imagining things, but I recall at least previously that you had to override all getters/setters if you wanted to override any for a property. Personally I think D made a significant mistake in the way properties are handled, with treating them as multiple methods tenuously tied together with sticking @property on (hopefully) all of them. I'd much rather it were a single property with getters/setters inside, similar to the way C# does it. Ideally something like: /// Documentation @property int foo() @safe pure nothrow { get() const { return _bar.foo; } set(int val) { _bar.foo = val; } } As opposed to /// Documentation @property int foo() const @safe pure nothrow { return _bar.foo; } /// ditto @property void foo(int val) @safe pure nothrow { _bar.foo = val; } Then you would actually have to override all or nothing, it would be treated as a single property not as multiple method overloads, etc.
Re: UFCS & overloaded property getters/setters
On Fri, Jun 13, 2014 at 10:53:38AM -0700, Jonathan M Davis via Digitalmars-d wrote: > On Fri, 13 Jun 2014 09:39:04 -0700 > "H. S. Teoh via Digitalmars-d" wrote: > > > I'm not sure if this is a bug, or an anti-pattern, or what, but I ran > > into this issue yesterday: > > > > class Base { > > int propImpl; > > final @property int prop() { return propImpl; } > > @property void prop(int newVal) { propImpl = newVal; } > > > > void someMethod() { > > auto x = prop; // OK, calls Base.prop() > > prop = x; // OK, calls Base.prop(int) > > } > > } > > > > class Derived : Base { > > override @property void prop(int newVal) { > > super.prop(newVal); > > doSomethingElse(newVal); > > } > > > > void someOtherMethod() { > > auto x = prop; // NG - compile error *** > > auto y = super.prop; // OK, calls Base.prop() > > prop = x; // OK, calls Derived.prop() > > } > > } > > > > Basically, once the derived class overrides the property setter, the > > (un-overridden) base class getter somehow becomes shadowed as well, > > and references to .prop will cause a compile error saying that > > Derived.prop can't be called without parameters. > > > > So, what's going on here? Should this code be accepted? Is this a > > compiler / language bug? A deliberate @property limitation? Or just > > more evidence @property should be taken out the back and shot? > > This is normal and has nothing to do with @property. When you override > a function in a derived class, you either have to override all its > overloads in the derived class or alias the base class symbols in the > derived class, or all the base class overloads which weren't > overridden are hidden. I believe that it's one of D's attempts to > avoid function hijacking. And I believe that it is discussed in the > language docs somewhere. [...] Aliasing super.prop to .prop in the derived class didn't work, in fact, it made things worse; now I have an infinite loop because all occurrences of .prop get redirected back to the base class (including the setter), and there is no way to alias only the non-overridden getter overload, so a call to Derived.prop will end up in the base class method where it shouldn't. I think this is starting to show itself as an anti-pattern, or at least, one of those obscure dark corners of D infested with complex interactions between unexpected features and possible compiler quirks. Probably the best thing to do is to make both getter and setter final, and add an overloadable onPropSet() method that the derived class can use to customize the property. T -- Why do conspiracy theories always come from the same people??
Re: UFCS & overloaded property getters/setters
On Fri, 13 Jun 2014 09:39:04 -0700 "H. S. Teoh via Digitalmars-d" wrote: > I'm not sure if this is a bug, or an anti-pattern, or what, but I ran > into this issue yesterday: > > class Base { > int propImpl; > final @property int prop() { return propImpl; } > @property void prop(int newVal) { propImpl = newVal; } > > void someMethod() { > auto x = prop; // OK, calls Base.prop() > prop = x; // OK, calls Base.prop(int) > } > } > > class Derived : Base { > override @property void prop(int newVal) { > super.prop(newVal); > doSomethingElse(newVal); > } > > void someOtherMethod() { > auto x = prop; // NG - compile error *** > auto y = super.prop; // OK, calls Base.prop() > prop = x; // OK, calls Derived.prop() > } > } > > Basically, once the derived class overrides the property setter, the > (un-overridden) base class getter somehow becomes shadowed as well, > and references to .prop will cause a compile error saying that > Derived.prop can't be called without parameters. > > So, what's going on here? Should this code be accepted? Is this a > compiler / language bug? A deliberate @property limitation? Or just > more evidence @property should be taken out the back and shot? This is normal and has nothing to do with @property. When you override a function in a derived class, you either have to override all its overloads in the derived class or alias the base class symbols in the derived class, or all the base class overloads which weren't overridden are hidden. I believe that it's one of D's attempts to avoid function hijacking. And I believe that it is discussed in the language docs somewhere. - Jonathan M Davis
UFCS & overloaded property getters/setters
I'm not sure if this is a bug, or an anti-pattern, or what, but I ran into this issue yesterday: class Base { int propImpl; final @property int prop() { return propImpl; } @property void prop(int newVal) { propImpl = newVal; } void someMethod() { auto x = prop; // OK, calls Base.prop() prop = x; // OK, calls Base.prop(int) } } class Derived : Base { override @property void prop(int newVal) { super.prop(newVal); doSomethingElse(newVal); } void someOtherMethod() { auto x = prop; // NG - compile error *** auto y = super.prop; // OK, calls Base.prop() prop = x; // OK, calls Derived.prop() } } Basically, once the derived class overrides the property setter, the (un-overridden) base class getter somehow becomes shadowed as well, and references to .prop will cause a compile error saying that Derived.prop can't be called without parameters. So, what's going on here? Should this code be accepted? Is this a compiler / language bug? A deliberate @property limitation? Or just more evidence @property should be taken out the back and shot? T -- This sentence is false.
Re: Why isn't the array lenght property an lvalue?
On 7 April 2014 22:18, MrSmith wrote: > On Monday, 7 April 2014 at 20:43:09 UTC, Steven Schveighoffer wrote: > >> On Mon, 07 Apr 2014 16:30:13 -0400, MrSmith wrote: >> >>> On Monday, 7 April 2014 at 19:58:21 UTC, Jeroen Bollen wrote: >>>> >>>> On Monday, 7 April 2014 at 19:56:38 UTC, MrSmith wrote: >>>>> >>>>> On Monday, 7 April 2014 at 19:23:45 UTC, Jeroen Bollen wrote: >>>>>> >>>>>> On Monday, 7 April 2014 at 19:13:31 UTC, Jeroen Bollen wrote: >>>>>>> >>>>>>> When I have myarray.length, why isn't that considered an lvalue, and >>>>>>> as a result, why cannot I get a pointer to it? >>>>>>> >>>>>>> It seems kinda dumb, I understand it cannot be changed manually, but >>>>>>> surely you should be able to get a const(type)* from it? >>>>>> >>>>>> >>>>>> Well type would be ulong, so const(ulong)* >>>>> >>>>> >>>>> Array length is size_t which is uint on x86 and ulong on x86_64. >>>> >>>> >>>> Alright, but why can't you get a pointer to it? >>> >>> >>> I've tried, but no luck here >>> http://dpaste.dzfl.pl/be526902ef4f >> >> > > Cool! So, it is not a property function but actual size_t? How would it grow > then? The compiler detects the pattern and invokes a runtime call to set the new array length. If the new size is greater than the current allocated pool for the array, then it's realloc'd on the GC.
Re: Why isn't the array lenght property an lvalue?
On Mon, 07 Apr 2014 17:18:09 -0400, MrSmith wrote: Cool! So, it is not a property function but actual size_t? How would it grow then? The array slice structure is a length followed by a pointer, your structure was a pointer followed by a length. It still is a property function to set the length. -Steve
Re: Why isn't the array lenght property an lvalue?
On Monday, 7 April 2014 at 20:43:09 UTC, Steven Schveighoffer wrote: On Mon, 07 Apr 2014 16:30:13 -0400, MrSmith wrote: On Monday, 7 April 2014 at 19:58:21 UTC, Jeroen Bollen wrote: On Monday, 7 April 2014 at 19:56:38 UTC, MrSmith wrote: On Monday, 7 April 2014 at 19:23:45 UTC, Jeroen Bollen wrote: On Monday, 7 April 2014 at 19:13:31 UTC, Jeroen Bollen wrote: When I have myarray.length, why isn't that considered an lvalue, and as a result, why cannot I get a pointer to it? It seems kinda dumb, I understand it cannot be changed manually, but surely you should be able to get a const(type)* from it? Well type would be ulong, so const(ulong)* Array length is size_t which is uint on x86 and ulong on x86_64. Alright, but why can't you get a pointer to it? I've tried, but no luck here http://dpaste.dzfl.pl/be526902ef4f Cool! So, it is not a property function but actual size_t? How would it grow then? You had the elements backwards: http://dpaste.dzfl.pl/8b5067aaf9d4 -Steve
Re: Why isn't the array lenght property an lvalue?
On Mon, 07 Apr 2014 16:30:13 -0400, MrSmith wrote: On Monday, 7 April 2014 at 19:58:21 UTC, Jeroen Bollen wrote: On Monday, 7 April 2014 at 19:56:38 UTC, MrSmith wrote: On Monday, 7 April 2014 at 19:23:45 UTC, Jeroen Bollen wrote: On Monday, 7 April 2014 at 19:13:31 UTC, Jeroen Bollen wrote: When I have myarray.length, why isn't that considered an lvalue, and as a result, why cannot I get a pointer to it? It seems kinda dumb, I understand it cannot be changed manually, but surely you should be able to get a const(type)* from it? Well type would be ulong, so const(ulong)* Array length is size_t which is uint on x86 and ulong on x86_64. Alright, but why can't you get a pointer to it? I've tried, but no luck here http://dpaste.dzfl.pl/be526902ef4f You had the elements backwards: http://dpaste.dzfl.pl/8b5067aaf9d4 -Steve
Re: Why isn't the array lenght property an lvalue?
On Monday, 7 April 2014 at 19:58:21 UTC, Jeroen Bollen wrote: On Monday, 7 April 2014 at 19:56:38 UTC, MrSmith wrote: On Monday, 7 April 2014 at 19:23:45 UTC, Jeroen Bollen wrote: On Monday, 7 April 2014 at 19:13:31 UTC, Jeroen Bollen wrote: When I have myarray.length, why isn't that considered an lvalue, and as a result, why cannot I get a pointer to it? It seems kinda dumb, I understand it cannot be changed manually, but surely you should be able to get a const(type)* from it? Well type would be ulong, so const(ulong)* Array length is size_t which is uint on x86 and ulong on x86_64. Alright, but why can't you get a pointer to it? I've tried, but no luck here http://dpaste.dzfl.pl/be526902ef4f
Re: Why isn't the array lenght property an lvalue?
On Monday, 7 April 2014 at 20:19:30 UTC, Justin Whear wrote: On Mon, 07 Apr 2014 20:14:13 +, Jeroen Bollen wrote: On Monday, 7 April 2014 at 20:12:48 UTC, Justin Whear wrote: On Mon, 07 Apr 2014 19:13:30 +, Jeroen Bollen wrote: When I have myarray.length, why isn't that considered an lvalue, and as a result, why cannot I get a pointer to it? It seems kinda dumb, I understand it cannot be changed manually, but surely you should be able to get a const(type)* from it? I believe `length` is implemented as a property function, though I can't find the source for the life of me. Then you still should be able to get a pointer of the result. I was also considering it to be a @property function, as indeed that'd explain this behaviour, but it still doesn't make sense to not allow it. After all, length is just a variable. Unless the length function returns by ref, the result is an rvalue and you won't be able to take a reference. Why doesn't it return by reference? Seems kinda dumb.
Re: Why isn't the array lenght property an lvalue?
On Mon, 07 Apr 2014 16:12:48 -0400, Justin Whear wrote: On Mon, 07 Apr 2014 19:13:30 +, Jeroen Bollen wrote: When I have myarray.length, why isn't that considered an lvalue, and as a result, why cannot I get a pointer to it? It seems kinda dumb, I understand it cannot be changed manually, but surely you should be able to get a const(type)* from it? I believe `length` is implemented as a property function, though I can't find the source for the life of me. It's a compiler builtin property. Reading simply returns the value from inside the array (does not map to a property). Setting calls one of these two depending on the array type: https://github.com/D-Programming-Language/druntime/blob/master/src/rt/lifetime.d#L1282 https://github.com/D-Programming-Language/druntime/blob/master/src/rt/lifetime.d#L1460 The reason you can't get a pointer to it is that it's not a simple variable. Note, unlike C++, D does not allow you to get a const reference or pointer to an Rvalue. -Steve
Re: Why isn't the array lenght property an lvalue?
On 4/7/14, 1:30 PM, MrSmith wrote: On Monday, 7 April 2014 at 19:58:21 UTC, Jeroen Bollen wrote: On Monday, 7 April 2014 at 19:56:38 UTC, MrSmith wrote: On Monday, 7 April 2014 at 19:23:45 UTC, Jeroen Bollen wrote: On Monday, 7 April 2014 at 19:13:31 UTC, Jeroen Bollen wrote: When I have myarray.length, why isn't that considered an lvalue, and as a result, why cannot I get a pointer to it? It seems kinda dumb, I understand it cannot be changed manually, but surely you should be able to get a const(type)* from it? Well type would be ulong, so const(ulong)* Array length is size_t which is uint on x86 and ulong on x86_64. Alright, but why can't you get a pointer to it? I've tried, but no luck here http://dpaste.dzfl.pl/be526902ef4f This stuff is best moved to the learn forum. -- Andrei
Re: Why isn't the array lenght property an lvalue?
On Mon, 07 Apr 2014 19:13:30 +, Jeroen Bollen wrote: > When I have myarray.length, why isn't that considered an lvalue, > and as a result, why cannot I get a pointer to it? > > It seems kinda dumb, I understand it cannot be changed manually, > but surely you should be able to get a const(type)* from it? I believe `length` is implemented as a property function, though I can't find the source for the life of me.