digitalmars.D - property needed or not needed?
- Rob T (24/24) Nov 18 2012 I can create a function that is located in a class/struct or
- Mike Parker (9/15) Nov 18 2012 I don't recall seeing anything about @property being deprecated.
- Jonathan M Davis (22/25) Nov 18 2012 It didn't used to be necessary, but there are ambiguities without it
- Andrei Alexandrescu (6/16) Nov 18 2012 I think we need to seriously revisit that. It's a corner case that hurts...
- Rob T (12/16) Nov 19 2012 I'm making good use out of UFCS functions that work like
- Jonathan M Davis (6/9) Nov 19 2012 Which completely violates the concept of a property in the first place. ...
- thedeemon (7/19) Nov 19 2012 I very much like the combination of UFCS, ranges and parens-free
- monarch_dodra (19/43) Nov 19 2012 I kind of agree with Jonathan here. @property really shines when
- Andrei Alexandrescu (6/8) Nov 19 2012 I kind of agree with him, too, but it would be a mistake to not reckon a...
- monarch_dodra (6/16) Nov 19 2012 One of the things that we may want to take into account, is that
- Dmitry Olshansky (14/30) Nov 19 2012 The major problem about @property enforcement as it stands is that it
- monarch_dodra (8/45) Nov 19 2012 Hum... Perhaps you meant:
- Dmitry Olshansky (7/47) Nov 19 2012 Hm.. being a while since I tried to use -property switch. I thought it
- Jonathan M Davis (43/76) Nov 19 2012 you
- Rob T (29/50) Nov 19 2012 That makes perfect sense to me if that's what the meaning of
- Jonathan M Davis (16/21) Nov 19 2012 Excep that i don't think that it's really a question of style. It's trea...
- Rob T (57/85) Nov 19 2012 I see what you are saying.
- Andrei Alexandrescu (9/10) Nov 19 2012 I agree. In particular I find it a specious argument to insist on
- =?UTF-8?B?U8O2bmtlIEx1ZHdpZw==?= (9/20) Nov 20 2012 Isn't it more that they seem like warts whenever a parameterless (or pse...
- deadalnix (4/16) Dec 01 2012 And what do you think about map!(x => x * x) = generator(x, y, z)
- Jonathan M Davis (6/8) Dec 01 2012 What's that even supposed to mean? map has been given no function argume...
- deadalnix (6/18) Dec 01 2012 I want to express that regular function are really different than
- Artur Skawina (18/26) Dec 02 2012 void main() {
- Rob T (29/29) Dec 02 2012 There's more than just @property that operate like variables.
- Regan Heath (9/13) Dec 02 2012 A variable assignment is in 99% of cases a simple operation. A function...
- Timon Gehr (3/14) Dec 02 2012 Costs are understood by profiling and/or detailed analysis, not by
- Regan Heath (13/30) Dec 04 2012 Exact costs, yes. But syntactic properties can, and have historically
- Rob T (5/17) Dec 05 2012 You can make functions and vars look different through a naming
- Regan Heath (5/23) Dec 05 2012 Yes!
- Rob T (29/29) Dec 02 2012 There's more than just @property that operate like variables.
- Artur Skawina (23/58) Dec 02 2012 Do you seriously think that there is no difference and would like
- Timon Gehr (5/32) Dec 02 2012 The first and last sentence are in mutual contradiction.
- Artur Skawina (24/63) Dec 03 2012 As long as nobody is (ab)using it.
- jerro (2/14) Jan 29 2013 I think having some kind of pipe operator would be a better
- jerro (2/4) Jan 29 2013 I'm sorry, I didn't realize I was replying to a two months old
- Andrei Alexandrescu (3/19) Dec 02 2012 I think that ought to be disallowed.
- Jacob Carlborg (21/26) Nov 20 2012 The return value doesn't have to be void. I always return the new value
- thedeemon (25/31) Nov 19 2012 This is just an old habit to see identifier with parens as a
- Andrei Alexandrescu (4/16) Nov 20 2012 A very good argument. Thanks!
- Jacob Carlborg (9/31) Nov 20 2012 In this particular case you can use a shorter form of the map call:
- deadalnix (2/32) Nov 20 2012
- Jacob Carlborg (4/5) Nov 20 2012 I said "fairly similar" not "exactly the same" :)
- deadalnix (4/7) Nov 21 2012 I don't understand why dropping () is that a big deal when
- Timon Gehr (2/10) Nov 21 2012 Relative frequencies. Amount of visual noise. People are used to it.
- Jacob Carlborg (5/7) Nov 21 2012 Now I'm really confused. What did you mean when you original wrote:
- deadalnix (14/21) Nov 21 2012 I meant that because of the fact that function isn't called
- deadalnix (3/11) Nov 19 2012 As aid bunch of time, I'm pretty sure we can have a clean semantic and
- Andrei Alexandrescu (4/17) Nov 19 2012 Could you please give more detail? On first sight this seems to
- deadalnix (12/30) Nov 19 2012 consider the following opDispatch :
- deadalnix (4/23) Nov 19 2012 With opDispatch and clear semantic, the following is doable :
- Rob T (25/33) Nov 19 2012 I know what you are saying, but I know that most people will
- sclytrack (5/5) Nov 19 2012 So is it official? We keep the d1 syntax for none property
- Jonathan M Davis (7/9) Nov 19 2012 No. It's not official. No decision has been made. For the moment, nothin...
- Minas Mina (11/11) Dec 04 2012 Isn't it possible to have parentheses optional only for UFCS?
- Nick Treleaven (3/14) Dec 04 2012 I expect it is, perhaps by disallowing calling a property function with
- Michael (5/16) Dec 04 2012 It's regular function called as property [getter] of module.
- Michael (5/16) Dec 04 2012 It's regular function called as property [getter] of module.
- Rob T (36/47) Dec 04 2012 module main;
- Araq (6/7) Dec 04 2012 This is exactly what Nimrod does. ;-) The () can also be omitted
- Rob T (10/21) Dec 04 2012 module main;
- Rob T (10/21) Dec 04 2012 module main;
- deadalnix (3/31) Dec 05 2012 It is also a ambiguity issue and the extra need of & to not call
- Rob T (10/21) Dec 04 2012 module main;
- Rob T (10/21) Dec 04 2012 module main;
- Rob T (10/21) Dec 04 2012 module main;
- Araq (6/7) Dec 04 2012 That's exactly what Nimrod does ;-). It also allows to leave out
- Mike Parker (4/15) Dec 04 2012 +1
- eles (10/15) Jan 29 2013 As I've been saying: make parens optional only if the function is
- Andrei Alexandrescu (5/6) Nov 18 2012 It's a mistake on top of another. We need to redesign it to such that
- Adam D. Ruppe (19/22) Nov 19 2012 There's a fairly easy way to do this, thanks to the @property
- Andrei Alexandrescu (4/9) Nov 19 2012 [snip]
- Adam D. Ruppe (18/19) Nov 19 2012 here it is:
- David Nadlinger (6/11) Nov 19 2012 Thanks a lot for doing this! It's a pity that the last bigger
- deadalnix (3/21) Nov 19 2012 This make it impossible to only define a getter only when one want to
- Jonathan M Davis (19/46) Nov 19 2012 early
- Adam D. Ruppe (8/10) Nov 20 2012 If there isn't a setter, you don't change things.
- Jacob Carlborg (7/25) Nov 20 2012 It would be really nice if we could implement property rewriting in the
- monarch_dodra (3/6) Nov 20 2012 Hell no!
- Regan Heath (7/12) Nov 20 2012 +1 I think this "feature" should just be removed, and @property
- Adam D. Ruppe (7/10) Nov 20 2012 Yes. We should *only* be changing the way @property is
- Regan Heath (9/18) Nov 20 2012 Usually I'd agree but this is a case of a wart we should just remove IMO...
- Adam D. Ruppe (13/16) Nov 20 2012 meh, I sometimes use it, but if overloading on @property works,
- Adam D. Ruppe (7/7) Nov 20 2012 BTW I've been pasting some of my posts into the wiki thing
- monarch_dodra (10/22) Nov 20 2012 That's a good point. If the property is a "setter", then both
- Timon Gehr (5/23) Nov 20 2012 Not really.
- deadalnix (3/32) Nov 20 2012 I conclude that @property should be limited to member function or UFCS
- Regan Heath (8/46) Nov 21 2012 d
- Rob T (70/80) Nov 20 2012 Here's another way to test if the idea is sound, by asking a few
- Adam D. Ruppe (9/9) Nov 20 2012 Just a quick thought... it's not like a = 10 has no way to
- monarch_dodra (9/11) Nov 20 2012 After thinking about it a bit more, I think there may be two
- Jonathan M Davis (15/26) Nov 20 2012 Yes, you basically have folks who want to have strictly defined properti...
- Adam D. Ruppe (14/18) Nov 20 2012 @property shouldn't be about enforcement. This is the fundamental
- Jonathan M Davis (7/31) Nov 20 2012 It's the same result. @property means that the function is treated as a
- deadalnix (3/22) Nov 20 2012 +1
- Andrej Mitrovic (6/10) Dec 01 2012 Here's a good reason why the latter isn't the best idea:
- Michel Fortin (10/16) Nov 19 2012 …or functions returning a type with an opCall.
- Andrei Alexandrescu (4/16) Nov 19 2012 Let's put all of these cases in a DIP so we can analyze them.
- Mehrdad (6/6) Nov 19 2012 Why don't we just outright disallow expression-statements?
- Era Scarecrow (19/25) Nov 19 2012 Hmmm I would say if it's const/immutable and pure then it would
- monarch_dodra (20/51) Nov 19 2012 ... wrong ;)
- Mehrdad (12/15) Nov 19 2012 That's EXACTLY what I'm saying.
- deadalnix (2/8) Nov 19 2012 It isn't the only ambiguous case.
- Andrei Alexandrescu (5/16) Nov 19 2012 That's why it's good to enumerate them all in
- deadalnix (5/22) Nov 19 2012 I'm not sure how it fit in the DIP but &funName is ambiguous when
- Adam D. Ruppe (5/7) Nov 20 2012 We can just define this away: &funName if it isn't a @property is
- deadalnix (4/11) Nov 20 2012 So this is impossible to get the address of the returned
- Timon Gehr (3/16) Nov 20 2012 +1.
- deadalnix (3/26) Nov 20 2012 So now funName and funName are not equivalent anymore. Special
- Jonathan M Davis (23/35) Dec 01 2012 I'd _love_ to make it illegal to call non-property functions without par...
- deadalnix (7/37) Dec 01 2012 As said before a lot of such usages can be made valid with a sane
- Andrej Mitrovic (3/6) Dec 02 2012 It requires a silly CamelCase style username. You can try and edit the
- Steven Schveighoffer (35/45) Jan 27 2013 Oh, shit. I missed another important @property discussion.
- Robert (24/84) Jan 28 2013 @property use:
- Jacob Carlborg (12/31) Jan 28 2013 I completely agree. I have created a struct called "attribute" only to
- Maxim Fomin (5/45) Jan 28 2013 Returning void instead of int in the example break assignment
- Dicebot (3/7) Jan 28 2013 It should not if evaluating the value of (b = c) will call getter
- Maxim Fomin (24/31) Jan 28 2013 Why getter and not setter? Expression a = b = c = d should call
- Dicebot (8/20) Jan 28 2013 "a = b" calls setter
- deadalnix (2/23) Jan 28 2013 It is not that obvious, as the result of a = b is also equal to b.
- Dicebot (4/6) Jan 28 2013 AFAIR it was defined strictly in C standard to be one two. Do not
- Maxim Fomin (8/29) Jan 28 2013 How it can call setter for a if b is not evaluated? This
- Maxim Fomin (2/21) Jan 28 2013 Correction: assuming b is a variable, not property.
- Dicebot (4/5) Jan 28 2013 That is exactly the problem. "a = b = c" should be rewritten as:
- Maxim Fomin (19/24) Jan 28 2013 From ISO C Assignment operators chapter: "An assignment operator
- Dicebot (8/14) Jan 28 2013 Quoting you (that was exactly part of standard I was referring
- Maxim Fomin (11/25) Jan 28 2013 You are mixing value of expression and expression itself. If
- Maxim Fomin (4/13) Jan 28 2013 Applying your logic:
- Dicebot (17/21) Jan 28 2013 Those are C rules, do not forget it. Thus value of (b = c) IS
- Maxim Fomin (49/72) Jan 28 2013 You are still breaking expression a = b = c and mixing terms of
- Robert (5/8) Jan 28 2013 They don't. If you want such behaviour, you would write your own setter
- Steven Schveighoffer (14/36) Jan 28 2013 This can be done without compiler help. But we need @property as a
- Jacob Carlborg (8/17) Jan 28 2013 This is how the semantics should be. This also shows a clear complete
- Steven Schveighoffer (5/16) Jan 29 2013 Like I said, the synthesizing of properties can be done via a library.
- Steven Schveighoffer (5/16) Jan 29 2013 Like I said, the synthesizing of properties can be done via a library.
- Jacob Carlborg (35/38) Jan 28 2013 No, the compiler should do a rewrite, as follows:
- Maxim Fomin (6/44) Jan 29 2013 No, it should be rewritten as foo.bar = 3, int a = 3 or int a =
- Jonathan M Davis (5/25) Jan 28 2013 Both should work. It's more efficient to chain assignments if the setter...
- Zach the Mystic (44/53) Jan 28 2013 This is a good point. Possibly since I'm the author of the
- Jonathan M Davis (5/7) Dec 02 2012 I agree, but those who think that seem to be outnumbered by those who do...
- kenji hara (69/69) Dec 02 2012 I had been trying to advance the phase to the next.
- sclytrack (2/18) Dec 03 2012 DIP21: Fixing @property
- Artur Skawina (25/87) Dec 06 2012 Reasonable middle-term compromise; can't really disallow ()-ess calls
I can create a function that is located in a class/struct or outside on its own without property. If the function has the signature of a property, i.e., void f( T x ) or T f(), I can use it as if it is a property. Example: // main module int g; // global in main module void p(int a) { g = a; } int p() { return g; } main() { p = 7; // OK int t = p; // OK, t = 7 } In the example, there's no class or struct, so I assume p() is considered to be a property of the module, which seems to make some sense. I also see that there's a compiler option "-property" that currently is not recognized, but is supposed to "enforce use of property on property functions". So what's up with property? Is it being depreciated for being redundant, or will it later be strictly enforced, or is it to be optionally enforced through a compiler switch? --rt
Nov 18 2012
On Monday, 19 November 2012 at 06:02:06 UTC, Rob T wrote:I also see that there's a compiler option "-property" that currently is not recognized, but is supposed to "enforce use of property on property functions". So what's up with property? Is it being depreciated for being redundant, or will it later be strictly enforced, or is it to be optionally enforced through a compiler switch?I don't recall seeing anything about property being deprecated. The intention of the -property switch is to, IIRC, ease the transition to the ultimate full-time enforcement of the property attribute. Enforcement is off by default. At some point, it will be turned on by default at which point the -property switch will no longer be necessary. I usually compile with -property and AFAIK it is functioning as intended. I've gotten errors in the past when it was enabled.
Nov 18 2012
On Monday, November 19, 2012 07:02:03 Rob T wrote:So what's up with property? Is it being depreciated for being redundant, or will it later be strictly enforced, or is it to be optionally enforced through a compiler switch?It didn't used to be necessary, but there are ambiguities without it (particularly with regards to property functions which return delegates), and a number of people don't like the laxness of practically any function with a particular sort of signature being able to be used as a property function rather than it being part of the API. So, property was introduced, but similar to override, it was decided that its enforcement would be phased in. -property was introduced so that the compiler's enforcement of it could be sorted out (it's still very buggy) and so that everyone would have time to adjust their code so that it used property correctly. Now, how strict the enforcement will ultimately be is up for some debate. It needs to be the case that any property function must be used as a property function in order to avoid the aforementioned ambiguities (so using parens will be illegal with property functions), but there's quite a lot of dissension surrounding whether non-property functions should be callable as property functions (i.e. whether non- property functions with the appropriate signature can be called without parens as is currently the case). Some of us consider it to be incredibly sloppy to allow it, whereas others find the idea of requiring parens to be extremely annoying (especially when dealing with UFCS). TDPL is somewhat ambiguous on the matter, and AFAIK, no official decision has been made. - Jonathan M Davis
Nov 18 2012
On 11/19/12 1:16 AM, Jonathan M Davis wrote:On Monday, November 19, 2012 07:02:03 Rob T wrote:I think we need to seriously revisit that. It's a corner case that hurts everyone everywhere.So what's up with property? Is it being depreciated for being redundant, or will it later be strictly enforced, or is it to be optionally enforced through a compiler switch?It didn't used to be necessary, but there are ambiguities without it (particularly with regards to property functions which return delegates),and a number of people don't like the laxness of practically any function with a particular sort of signature being able to be used as a property function rather than it being part of the API.I think UFCS changes the playfield quite a lot. Code using UFCS looks a whole lot crappier with a bunch of arbitrary extra parens. Andrei
Nov 18 2012
On Monday, 19 November 2012 at 06:53:46 UTC, Andrei Alexandrescu wrote:I think UFCS changes the playfield quite a lot. Code using UFCS looks a whole lot crappier with a bunch of arbitrary extra parens. AndreiI'm making good use out of UFCS functions that work like properties, so to remain consistent with struct/class calling syntax, I would expect to have the ability to define functions that have property semantics at the module level. I really think that modules should have properties anyway, and since I can do it, I am doing it, and it works great. My guess is that if property gets enforced, we'll see a lot of functions with empty parameter lists being defined as property for the sole reason to get rid of having to type in the (). --rt
Nov 19 2012
On Monday, November 19, 2012 09:16:29 Rob T wrote:My guess is that if property gets enforced, we'll see a lot of functions with empty parameter lists being defined as property for the sole reason to get rid of having to type in the ().Which completely violates the concept of a property in the first place. It's intended to be an abstraction for a variable. Using property just to get rid of parens would be like naming types with verbs instead of nouns. It's completely backwards. - Jonathan M Davis
Nov 19 2012
On Monday, 19 November 2012 at 08:23:43 UTC, Jonathan M Davis wrote:On Monday, November 19, 2012 09:16:29 Rob T wrote:I very much like the combination of UFCS, ranges and parens-free style which allows writing code like iota(0, 1000000).map!(to!string).retro.take(50).retro[10].writeln; So I like Andrei's idea to force property only for those functions where it's absolutely necessary to fight ambiguity.My guess is that if property gets enforced, we'll see a lot of functions with empty parameter lists being defined as property for the sole reason to get rid of having to type in the ().Which completely violates the concept of a property in the first place. It's intended to be an abstraction for a variable. Using property just to get rid of parens would be like naming types with verbs instead of nouns. It's completely backwards. - Jonathan M Davis
Nov 19 2012
On Monday, 19 November 2012 at 08:45:03 UTC, thedeemon wrote:On Monday, 19 November 2012 at 08:23:43 UTC, Jonathan M Davis wrote:I kind of agree with Jonathan here. property really shines when you want to "add" an attribute to a struct. array "front", for example, is a perfect example of this. RefCounted's "payload" (IMO), is also a good example. *Functions* that do actual operations, in particular, "retro", IMO, should not be properties. "byLines", for example, is a member function, and not property. How is: r.retro; any better than r.byLines() ? At best, it makes it look like r has a built-in retro attribute, which is miss-leading. -------- I'll admit I thought too it would be "convenient" to write ".retro" without the parens, but let's face it, that'd be incorrect usage...On Monday, November 19, 2012 09:16:29 Rob T wrote:I very much like the combination of UFCS, ranges and parens-free style which allows writing code like iota(0, 1000000).map!(to!string).retro.take(50).retro[10].writeln; So I like Andrei's idea to force property only for those functions where it's absolutely necessary to fight ambiguity.My guess is that if property gets enforced, we'll see a lot of functions with empty parameter lists being defined as property for the sole reason to get rid of having to type in the ().Which completely violates the concept of a property in the first place. It's intended to be an abstraction for a variable. Using property just to get rid of parens would be like naming types with verbs instead of nouns. It's completely backwards. - Jonathan M Davis
Nov 19 2012
On 11/19/12 4:01 AM, monarch_dodra wrote:I kind of agree with Jonathan here. property really shines when you want to "add" an attribute to a struct.I kind of agree with him, too, but it would be a mistake to not reckon a change in dynamics. UFCS makes all those extra parens just awkward, and people will vote with their code regardless whether some particular viewpoint from some particular angle considers the approach backwards. Andrei
Nov 19 2012
On Monday, 19 November 2012 at 14:58:29 UTC, Andrei Alexandrescu wrote:On 11/19/12 4:01 AM, monarch_dodra wrote:One of the things that we may want to take into account, is that -property prevents any existing function from migrating to/from property. For example, if we want to make "retro" a property, we can't without breaking any and all UFCS usage of retro.I kind of agree with Jonathan here. property really shines when you want to "add" an attribute to a struct.I kind of agree with him, too, but it would be a mistake to not reckon a change in dynamics. UFCS makes all those extra parens just awkward, and people will vote with their code regardless whether some particular viewpoint from some particular angle considers the approach backwards. Andrei
Nov 19 2012
11/19/2012 7:18 PM, monarch_dodra пишет:On Monday, 19 November 2012 at 14:58:29 UTC, Andrei Alexandrescu wrote:The major problem about property enforcement as it stands is that it breaks the duality of things like retro: a.retro vs retro(a) Both should be allowed as it's a matter of taste that shouldn't be enforced. A lot of new code uses a.retro and a lot of older code uses retro(a). If retro is property then only the first one compiles If retro is a function then only the second one compiles. Which obviously means property has to be reconsidered. -- Dmitry OlshanskyOn 11/19/12 4:01 AM, monarch_dodra wrote:One of the things that we may want to take into account, is that -property prevents any existing function from migrating to/from property. For example, if we want to make "retro" a property, we can't without breaking any and all UFCS usage of retro.I kind of agree with Jonathan here. property really shines when you want to "add" an attribute to a struct.I kind of agree with him, too, but it would be a mistake to not reckon a change in dynamics. UFCS makes all those extra parens just awkward, and people will vote with their code regardless whether some particular viewpoint from some particular angle considers the approach backwards. Andrei
Nov 19 2012
On Monday, 19 November 2012 at 17:42:28 UTC, Dmitry Olshansky wrote:11/19/2012 7:18 PM, monarch_dodra пишет:Hum... Perhaps you meant: a.retro vs a.retro() ??? Because "retro(a)" works regardless of the property.On Monday, 19 November 2012 at 14:58:29 UTC, Andrei Alexandrescu wrote:The major problem about property enforcement as it stands is that it breaks the duality of things like retro: a.retro vs retro(a) Both should be allowed as it's a matter of taste that shouldn't be enforced. A lot of new code uses a.retro and a lot of older code uses retro(a). If retro is property then only the first one compiles If retro is a function then only the second one compiles. Which obviously means property has to be reconsidered.On 11/19/12 4:01 AM, monarch_dodra wrote:One of the things that we may want to take into account, is that -property prevents any existing function from migrating to/from property. For example, if we want to make "retro" a property, we can't without breaking any and all UFCS usage of retro.I kind of agree with Jonathan here. property really shines when you want to "add" an attribute to a struct.I kind of agree with him, too, but it would be a mistake to not reckon a change in dynamics. UFCS makes all those extra parens just awkward, and people will vote with their code regardless whether some particular viewpoint from some particular angle considers the approach backwards. Andrei
Nov 19 2012
11/19/2012 9:58 PM, monarch_dodra пишет:On Monday, 19 November 2012 at 17:42:28 UTC, Dmitry Olshansky wrote:This one too.11/19/2012 7:18 PM, monarch_dodra пишет:Hum... Perhaps you meant: a.retro vs a.retro()On Monday, 19 November 2012 at 14:58:29 UTC, Andrei Alexandrescu wrote:The major problem about property enforcement as it stands is that it breaks the duality of things like retro: a.retro vs retro(a) Both should be allowed as it's a matter of taste that shouldn't be enforced. A lot of new code uses a.retro and a lot of older code uses retro(a). If retro is property then only the first one compiles If retro is a function then only the second one compiles. Which obviously means property has to be reconsidered.On 11/19/12 4:01 AM, monarch_dodra wrote:One of the things that we may want to take into account, is that -property prevents any existing function from migrating to/from property. For example, if we want to make "retro" a property, we can't without breaking any and all UFCS usage of retro.I kind of agree with Jonathan here. property really shines when you want to "add" an attribute to a struct.I kind of agree with him, too, but it would be a mistake to not reckon a change in dynamics. UFCS makes all those extra parens just awkward, and people will vote with their code regardless whether some particular viewpoint from some particular angle considers the approach backwards. AndreiBecause "retro(a)" works regardless of the property.Hm.. being a while since I tried to use -property switch. I thought it was also disallowed. Not so bad then I guess. Looking forward to DIP21. -- Dmitry Olshansky
Nov 19 2012
On Monday, November 19, 2012 21:42:25 Dmitry Olshansky wrote:11/19/2012 7:18 PM, monarch_dodra =D0=BF=D0=B8=D1=88=D0=B5=D1=82:ote:On Monday, 19 November 2012 at 14:58:29 UTC, Andrei Alexandrescu wr=youOn 11/19/12 4:01 AM, monarch_dodra wrote:I kind of agree with Jonathan here. property really shines when =ckonwant to "add" an attribute to a struct.=20 I kind of agree with him, too, but it would be a mistake to not re=rd,a change in dynamics. UFCS makes all those extra parens just awkwa=oachand people will vote with their code regardless whether some particular viewpoint from some particular angle considers the appr=n'tbackwards. =20 Andrei=20 One of the things that we may want to take into account, is that -property prevents any existing function from migrating to/from property. For example, if we want to make "retro" a property, we ca=without breaking any and all UFCS usage of retro.=20 The major problem about property enforcement as it stands is that it=breaks the duality of things like retro: a.retro vs retro(a) =20 Both should be allowed as it's a matter of taste that shouldn't be enforced. A lot of new code uses a.retro and a lot of older code uses=retro(a). =20 If retro is property then only the first one compiles If retro is a function then only the second one compiles. =20 Which obviously means property has to be reconsidered.The thing is that if property is really an abstraction for variables, = then it=20 _doesn't_ make sense to allow both, because it's _not_ a matter of tast= e.=20 Either it's a variable, or it's a function. Not both. And if it's a var= iable,=20 then obviously no parens should be used with it. And if it's a function= , then=20 obviously parens should be used with it. If you're viewing it as just a way to not have to use parens on functio= ns,=20 then that's something else entirely. And if that's what we're looking t= o=20 support, then using property for that makes no sense at all. Personally, I hate the fact it's legal to have any kind of optional par= ens. I=20 think that it's incredibly sloppy and goes against the abstractions of=20= variables and functions. I'm all for forcing the full set of parens in = a long=20 chain of UFCS. But clearly plenty of other folks don't agree. Because of all of those folks, it may make sense to make it so that par= ens are=20 optional on functions but are outright verboten on property functions.= That=20 way, anyone wanting to use property for actual properties can do so wi= th=20 proper enforcement, but those who want to just leave parens off of norm= al=20 function calls can. I really don't like the idea, but at this point, I = think=20 that it's fairly clear that there are a lot of people who _like_ the sl= oppy=20 nature of being able to leave parens off much as a number of the rest o= f us=20 hate it. - Jonathan M Davis
Nov 19 2012
On Monday, 19 November 2012 at 20:04:24 UTC, Jonathan M Davis wrote:The thing is that if property is really an abstraction for variables, then it _doesn't_ make sense to allow both, because it's _not_ a matter of taste. Either it's a variable, or it's a function. Not both. And if it's a variable, then obviously no parens should be used with it. And if it's a function, then obviously parens should be used with it.That makes perfect sense to me if that's what the meaning of property is supposed to be, and if so then it can constrain the usage to that of a variable, which currently is not the case.If you're viewing it as just a way to not have to use parens on functions, then that's something else entirely. And if that's what we're looking to support, then using property for that makes no sense at all.That makes sense to me as well, and indicates that the property topic is getting mixed up with another topic, which concerns the optional use of () for empty parameter lists. What may be forgotten, is that we currently have the ability to not only drop the (), but also to perform optional assignments, eg Foo = 23;, without defining a function Foo to be property. In one case we're talking about variable abstractions, and in another case we're talking about simply making () optional, these are two entirely separate topics that are mangled up together. I think you understand this already, but perhaps not everyone else does. To further complicate things, I find that when deciding to define a function as property or not is like trying to decide if Pluto is a planet or not, it's often not clear which way you should go, and that may be why I really did enjoy not having to specify property to make use of the semantics it (was supposed to) provide when and where I saw fit to do so.Personally, I hate the fact it's legal to have any kind of optional parens. I think that it's incredibly sloppy and goes against the abstractions of variables and functions. I'm all for forcing the full set of parens in a long chain of UFCS. But clearly plenty of other folks don't agree.I seriously don't think you should try to constrain coding style, instead it makes much more sense to provide the user with a means to constrain it themselves as they see fit. Look at languages that constrain coding style too much vs languages that don't, and consider the popularity among them. My two cents :) --rt
Nov 19 2012
On Monday, November 19, 2012 22:04:02 Rob T wrote:I seriously don't think you should try to constrain coding style, instead it makes much more sense to provide the user with a means to constrain it themselves as they see fit. Look at languages that constrain coding style too much vs languages that don't, and consider the popularity among them.Excep that i don't think that it's really a question of style. It's treating a function as if it were a variable, when it's not only not a variable, but it's not even acting like one. It's implying that the code has one set of semantics when it has another. Dropping parens when specifically creating a function which is intended to emulate a variable makes sense. But dropping parens just because you feel like it then makes a function look like a variable when it's not and not intended to even act like one. That violates the very difference between function and variable on even a conceptual level. It would be one thing to make a particular character or sequence of characters optional when doing so doesn't make it look like it's something else entirely (e.g. optional braces don't make anything look like anything else - they just drop some characters, and they don't introduce any ambiguities in the process). But it's quite another to make those characters optional when they make one language construct look like another. - Jonathan M Davis
Nov 19 2012
On Monday, 19 November 2012 at 21:44:35 UTC, Jonathan M Davis wrote:Excep that i don't think that it's really a question of style. It's treating a function as if it were a variable, when it's not only not a variable, but it's not even acting like one. It's implying that the code has one set of semantics when it has another. Dropping parens when specifically creating a function which is intended to emulate a variable makes sense. But dropping parens just because you feel like it then makes a function look like a variable when it's not and not intended to even act like one. That violates the very difference between function and variable on even a conceptual level. It would be one thing to make a particular character or sequence of characters optional when doing so doesn't make it look like it's something else entirely (e.g. optional braces don't make anything look like anything else - they just drop some characters, and they don't introduce any ambiguities in the process). But it's quite another to make those characters optional when they make one language construct look like another. - Jonathan M DavisI see what you are saying. Consider this: property allows a function to behave as if it were a variable, so in that case we're effectively creating an alternate set of language constructs for at least some functions. The enforcement through property however constrains it to only behave as if it were a variable and not a function, there's no ambiguity in this case, and it's clearly intentional, not a mistake. Without property, but allowing the programmer to decide if, when, and where, a function may emulate a variable, and when it will not, may confuse some people and may also confuse the compiler in some cases, but it does offer the programmer additional flexibility that may prove to be useful, although it may also prove to be a costly mistake, and if so it may be a matter of how good the programmer is. All I know at this point is that because property was not fully implemented as originally intended, I was able to experience the flexibility, and personally I found it to be OK for whatever reason, esp wrt UFCS. I would still be happy to have property perform constraints to enforce a function to emulate a variable or to resolve ambiguities, and certainly for any function no matter where it may be declared. I can definitely see the value in that and I can't see any reason for not supporting it. Side Note: In some cases you may want a setter but no getter for write only variable emulation, or a setter but no getter for read only emulation. What is not so clear, is if optional () should be allowed or not, but I do understand the argument that it makes the code look better in some cases which in that case is a question of style rather than anything to do with property. Also do not forget that we can not only drop the (), but also perform assignments to functions that take in one variable, but I'm not sure if the return must be void for that to work. It seems strange to allow arbitrarily dual function/variable constructs for functions, but being strange does not necessarily mean it is wrong. I do wonder however, if there's something much more fundamental or generalized going on with this that can settle the question in clear terms? I fully understand the variable emulation argument, and it's seems to be sound, however imagine reversing the argument and suggesting that all (or some) variables should be enforced to emulate function calls with function. We've seen this being done in C++, where I can initialize a variable in multiple emulated ways: // class constructor emulation int x(42); // function emulation int y; x = y(42); // regular variable form int x = 42; I don't have an answer, but there may be more to the picture than we think. --rt
Nov 19 2012
On 11/19/12 5:23 PM, Rob T wrote:I don't have an answer, but there may be more to the picture than we think.I agree. In particular I find it a specious argument to insist on religiously associating "()" with function calling and the lack thereof with variable access. I don't see myself, when seeing an expression like "generator(x, y, z).map!(x => x * x)()", going like "holy cow, good I saw those trailing parens, otherwise I would've sworn it was a variable". Trailing parens in UFCS chains are just warts, this is the reality. Let's deal with it. Andrei
Nov 19 2012
Am 20.11.2012 05:12, schrieb Andrei Alexandrescu:On 11/19/12 5:23 PM, Rob T wrote:Isn't it more that they seem like warts whenever a parameterless (or pseudo-parameterless in the case of UFCS) template function is called, because template instantiations already look a lot like function calls? Anyway, my take on this is, while I find it a bit sad, that there is no visual distinction between variables and functions for various reasons, in the presence of properties this distinction has already gone long time ago. So realistically this argument has no weight anymore. Personally, I started to like a partially relaxed approach like the one Adam Ruppe describes a lot, so a DIP would definitely be a great step.I don't have an answer, but there may be more to the picture than we think.I agree. In particular I find it a specious argument to insist on religiously associating "()" with function calling and the lack thereof with variable access. I don't see myself, when seeing an expression like "generator(x, y, z).map!(x => x * x)()", going like "holy cow, good I saw those trailing parens, otherwise I would've sworn it was a variable". Trailing parens in UFCS chains are just warts, this is the reality. Let's deal with it. Andrei
Nov 20 2012
On Tuesday, 20 November 2012 at 04:12:54 UTC, Andrei Alexandrescu wrote:On 11/19/12 5:23 PM, Rob T wrote:And what do you think about map!(x => x * x) = generator(x, y, z) ?I don't have an answer, but there may be more to the picture than we think.I agree. In particular I find it a specious argument to insist on religiously associating "()" with function calling and the lack thereof with variable access. I don't see myself, when seeing an expression like "generator(x, y, z).map!(x => x * x)()", going like "holy cow, good I saw those trailing parens, otherwise I would've sworn it was a variable". Trailing parens in UFCS chains are just warts, this is the reality. Let's deal with it. Andrei
Dec 01 2012
On Sunday, December 02, 2012 07:49:52 deadalnix wrote:And what do you think about map!(x => x * x) = generator(x, y, z) ?What's that even supposed to mean? map has been given no function argument either as UFCS or with a normal function call, so it's not being called. And even if it were, it wouldn't result in an lvalue, so putting it on the left of an assignment makes no sense. I have no idea what you're trying to do here. - Jonathan M Davis
Dec 01 2012
On Sunday, 2 December 2012 at 06:58:12 UTC, Jonathan M Davis wrote:On Sunday, December 02, 2012 07:49:52 deadalnix wrote:I want to express that regular function are really different than regular function calls. If map had to behave like a property, then the code above would be correct, and 100% equivalent to Andrei's snippet.And what do you think about map!(x => x * x) = generator(x, y, z) ?What's that even supposed to mean? map has been given no function argument either as UFCS or with a normal function call, so it's not being called. And even if it were, it wouldn't result in an lvalue, so putting it on the left of an assignment makes no sense. I have no idea what you're trying to do here.
Dec 01 2012
On 12/02/12 07:57, Jonathan M Davis wrote:On Sunday, December 02, 2012 07:49:52 deadalnix wrote:void main() { import std.stdio; writeln!string = "Hello World!"; } // The explicit "!string" is only needed because of no IFTI, if 'writeln' was // a function instead of a template you could just call it like "writeln = "blah". Allowing that /by default/ does much more harm than good, proper property enforcement is necessary. Function calls go via '()'. Programmer can override when he knows better. UFCS doesn't change things. [1] artur [1] If you think the required '()' in UFCS chains look ugly, you're right, but the right fix isn't to butcher the language. '()' carry important information. Having a mode where function calls are made w/o the parens would be a good idea, but it should be limited to an explicit scope. ie something like "auto r = function {generator(x, y, z).map!(x => x * x)};", except 'function' keyword can't be overloaded like that, it's too long, and ()-less calls isn't the only change that could be done.And what do you think about map!(x => x * x) = generator(x, y, z) ?What's that even supposed to mean? map has been given no function argument either as UFCS or with a normal function call, so it's not being called. And even if it were, it wouldn't result in an lvalue, so putting it on the left of an assignment makes no sense. I have no idea what you're trying to do here.
Dec 02 2012
There's more than just property that operate like variables. Should we restrict this as well? struct stdio { void opAssign(T)( T a_arg ) { writeln( a_arg ); } } main() { stdio writeln; writeln = "hellow world"; } Conceptually, I don't see why we have to impose a difference between how variables are assigned and how functions are called. A variable "=" assignment is simply a special case of a function call that is written for you by the compiler. The example of opAssign shows that for some time now, there's been pressure to eliminate the difference in at least some cases, and allow the programmer to implement their own version of the assignment function call. If you want to remove inconsistencies, then the way functions and variables are manipulated should be unified. If someone can honestly demonstrate a non-subjective reason why there must be a difference between function call and variable assignments, please show it. So far I've only seen arguments that boil down to "I don't like it". --rt
Dec 02 2012
On Sun, 02 Dec 2012 18:47:26 -0000, Rob T <rob ucora.com> wrote:If someone can honestly demonstrate a non-subjective reason why there must be a difference between function call and variable assignments, please show it. So far I've only seen arguments that boil down to "I don't like it".A variable assignment is in 99% of cases a simple operation. A function call is in 99% of cases a more complex operation. Being able to immediately "see" those costs is useful. A language which allows you to make variable assignments costly will be inherently harder to understand in terms of cost, than a language which does not. R -- Using Opera's revolutionary email client: http://www.opera.com/mail/
Dec 02 2012
On 12/02/2012 09:19 PM, Regan Heath wrote:On Sun, 02 Dec 2012 18:47:26 -0000, Rob T <rob ucora.com> wrote:Costs are understood by profiling and/or detailed analysis, not by looking at trivial syntactic properties.If someone can honestly demonstrate a non-subjective reason why there must be a difference between function call and variable assignments, please show it. So far I've only seen arguments that boil down to "I don't like it".A variable assignment is in 99% of cases a simple operation. A function call is in 99% of cases a more complex operation. Being able to immediately "see" those costs is useful. A language which allows you to make variable assignments costly will be inherently harder to understand in terms of cost, than a language which does not. R
Dec 02 2012
On Mon, 03 Dec 2012 04:02:15 -0000, Timon Gehr <timon.gehr gmx.ch> wrote:On 12/02/2012 09:19 PM, Regan Heath wrote:Exact costs, yes. But syntactic properties can, and have historically also given a good indication of costs and this is useful. Removing that, is less than useful and potentially surprising. Compare that to what you gain from this change.. nothing useful that I can see. Making variable assignments and function calls look the same buys you nothing, you're trying to make apples and oranges look like oranges and hide all the nice, useful, detail and distinction you get from having both assignments (oranges) and function calls (apples) and all that they imply. R -- Using Opera's revolutionary email client: http://www.opera.com/mail/On Sun, 02 Dec 2012 18:47:26 -0000, Rob T <rob ucora.com> wrote:Costs are understood by profiling and/or detailed analysis, not by looking at trivial syntactic properties.If someone can honestly demonstrate a non-subjective reason why there must be a difference between function call and variable assignments, please show it. So far I've only seen arguments that boil down to "I don't like it".A variable assignment is in 99% of cases a simple operation. A function call is in 99% of cases a more complex operation. Being able to immediately "see" those costs is useful. A language which allows you to make variable assignments costly will be inherently harder to understand in terms of cost, than a language which does not. R
Dec 04 2012
On Tuesday, 4 December 2012 at 21:58:49 UTC, Regan Heath wrote:Exact costs, yes. But syntactic properties can, and have historically also given a good indication of costs and this is useful. Removing that, is less than useful and potentially surprising. Compare that to what you gain from this change.. nothing useful that I can see. Making variable assignments and function calls look the same buys you nothing, you're trying to make apples and oranges look like oranges and hide all the nice, useful, detail and distinction you get from having both assignments (oranges) and function calls (apples) and all that they imply. RYou can make functions and vars look different through a naming convention, and do even more if you choose. The enforcement of the empty () as essentially an enforced naming convention. --rt
Dec 05 2012
On Wed, 05 Dec 2012 16:49:22 -0000, Rob T <rob ucora.com> wrote:On Tuesday, 4 December 2012 at 21:58:49 UTC, Regan Heath wrote:Yes! R -- Using Opera's revolutionary email client: http://www.opera.com/mail/Exact costs, yes. But syntactic properties can, and have historically also given a good indication of costs and this is useful. Removing that, is less than useful and potentially surprising. Compare that to what you gain from this change.. nothing useful that I can see. Making variable assignments and function calls look the same buys you nothing, you're trying to make apples and oranges look like oranges and hide all the nice, useful, detail and distinction you get from having both assignments (oranges) and function calls (apples) and all that they imply. RYou can make functions and vars look different through a naming convention, and do even more if you choose. The enforcement of the empty () as essentially an enforced naming convention.
Dec 05 2012
There's more than just property that operate like variables. Should we restrict this as well? struct stdio { void opAssign(T)( T a_arg ) { writeln( a_arg ); } } main() { stdio writeln; writeln = "hellow world"; } Conceptually, I don't see why we have to impose a difference between how variables are assigned and how functions are called. A variable "=" assignment is simply a special case of a function call that is written for you by the compiler. The example of opAssign shows that for some time now, there's been pressure to eliminate the difference in at least some cases, and allow the programmer to implement their own version of the assignment function call. If you want to remove inconsistencies, then the way functions and variables are manipulated should be unified. If someone can honestly demonstrate a non-subjective reason why there must be a difference between function call and variable assignments, please show it. So far I've only seen arguments that boil down to "I don't like it". --rt
Dec 02 2012
On 12/02/12 19:48, Rob T wrote:There's more than just property that operate like variables. Should we restrict this as well? struct stdio { void opAssign(T)( T a_arg ) { writeln( a_arg ); } } main() { stdio writeln; writeln = "hellow world"; } Conceptually, I don't see why we have to impose a difference between how variables are assigned and how functions are called. A variable "=" assignment is simply a special case of a function call that is written for you by the compiler. The example of opAssign shows that for some time now, there's been pressure to eliminate the difference in at least some cases, and allow the programmer to implement their own version of the assignment function call. If you want to remove inconsistencies, then the way functions and variables are manipulated should be unified. If someone can honestly demonstrate a non-subjective reason why there must be a difference between function call and variable assignments, please show it. So far I've only seen arguments that boil down to "I don't like it".Do you seriously think that there is no difference and would like to have to decypher code like void main() { import std.stdio, std.math; writeln(sqrt=81); } ? Having assignments act as calls for every random function is insane. It can be done and is ok where the programmers decides this makes sense. Your above stdio example is not such a case. [1] artur [1] But thanks for sharing it, I would have probably never thought of using a static opAssign otherwise... struct stdout { static void opAssign(T...)(T args) { import std.stdio; writeln(args); } } void main() { stdout = "It's a strange world"; }
Dec 02 2012
On 12/02/2012 12:36 PM, Artur Skawina wrote:On 12/02/12 07:57, Jonathan M Davis wrote:It does neither harm nor good.On Sunday, December 02, 2012 07:49:52 deadalnix wrote:void main() { import std.stdio; writeln!string = "Hello World!"; } // The explicit "!string" is only needed because of no IFTI, if 'writeln' was // a function instead of a template you could just call it like "writeln = "blah". Allowing that /by default/ does much more harm than good,And what do you think about map!(x => x * x) = generator(x, y, z) ?What's that even supposed to mean? map has been given no function argument either as UFCS or with a normal function call, so it's not being called. And even if it were, it wouldn't result in an lvalue, so putting it on the left of an assignment makes no sense. I have no idea what you're trying to do here.proper property enforcement is necessary. Function calls go via '()'. Programmer can override when he knows better.The first and last sentence are in mutual contradiction.UFCS doesn't change things. [1] artur [1] If you think the required '()' in UFCS chains look ugly, you're right, but the right fix isn't to butcher the language. '()' carry important information.They do not, otherwise compilation could not succeed.Having a mode where function calls are made w/o the parens would be a good idea, but it should be limited to an explicit scope. ie something like "auto r = function {generator(x, y, z).map!(x => x * x)};", except 'function' keyword can't be overloaded like that, it's too long, and ()-less calls isn't the only change that could be done.That is terrible.
Dec 02 2012
On 12/03/12 05:10, Timon Gehr wrote:On 12/02/2012 12:36 PM, Artur Skawina wrote:As long as nobody is (ab)using it. int f(int a) { return sqrt = a; } is not much different from abusing op overloading and is an equally bad idea. It shouldn't be allowed by /default/, which not enforcing property will lead to. Somebody reading that 'f()' definition should be able to rely on sqrt being a variable, possibly of a user defined type, even with an overloaded assignment operator, which could have side effects. Assuming that the type designer made sensible choices is relatively safe, assuming that every user will do the right thing won't work. What would be the rationale for allowing this syntax for calling every random function? Other than not having to declare it as a property when required.On 12/02/12 07:57, Jonathan M Davis wrote:It does neither harm nor good.On Sunday, December 02, 2012 07:49:52 deadalnix wrote:void main() { import std.stdio; writeln!string = "Hello World!"; } // The explicit "!string" is only needed because of no IFTI, if 'writeln' was // a function instead of a template you could just call it like "writeln = "blah". Allowing that /by default/ does much more harm than good,And what do you think about map!(x => x * x) = generator(x, y, z) ?What's that even supposed to mean? map has been given no function argument either as UFCS or with a normal function call, so it's not being called. And even if it were, it wouldn't result in an lvalue, so putting it on the left of an assignment makes no sense. I have no idea what you're trying to do here.No, they are not, because enforcement is a requirement for control. And that has to be with the producer, not the consumer (ie determined by the function declaration, not individually at every call site).proper property enforcement is necessary. Function calls go via '()'. Programmer can override when he knows better.The first and last sentence are in mutual contradiction.not required != unimportant. The compiler could for example in many cases figure out by itself that a missing (const) cast is necessary for some code to compile. That does not mean that it should insert them implicitly, w/o making sure doing so is both harmless and won't cause confusion.[1] If you think the required '()' in UFCS chains look ugly, you're right, but the right fix isn't to butcher the language. '()' carry important information.They do not, otherwise compilation could not succeed.Yes, it *is* terrible - the point was that it can be done differently and this could be a start for discussion. That kind of semi-dsl also allows for locally lifting other restrictions like order of evaluation etc w/o butchering the rest of the language. arturHaving a mode where function calls are made w/o the parens would be a good idea, but it should be limited to an explicit scope. ie something like "auto r = function {generator(x, y, z).map!(x => x * x)};", except 'function' keyword can't be overloaded like that, it's too long, and ()-less calls isn't the only change that could be done.That is terrible.
Dec 03 2012
[1] If you think the required '()' in UFCS chains look ugly, you're right, but the right fix isn't to butcher the language. '()' carry important information. Having a mode where function calls are made w/o the parens would be a good idea, but it should be limited to an explicit scope. ie something like "auto r = function {generator(x, y, z).map!(x => x * x)};", except 'function' keyword can't be overloaded like that, it's too long, and ()-less calls isn't the only change that could be done.I think having some kind of pipe operator would be a better solution. But it's probably too late to add any of those now.
Jan 29 2013
I think having some kind of pipe operator would be a better solution. But it's probably too late to add any of those now.I'm sorry, I didn't realize I was replying to a two months old post.
Jan 29 2013
On 12/2/12 1:49 AM, deadalnix wrote:On Tuesday, 20 November 2012 at 04:12:54 UTC, Andrei Alexandrescu wrote:I think that ought to be disallowed. AndreiOn 11/19/12 5:23 PM, Rob T wrote:And what do you think about map!(x => x * x) = generator(x, y, z) ?I don't have an answer, but there may be more to the picture than we think.I agree. In particular I find it a specious argument to insist on religiously associating "()" with function calling and the lack thereof with variable access. I don't see myself, when seeing an expression like "generator(x, y, z).map!(x => x * x)()", going like "holy cow, good I saw those trailing parens, otherwise I would've sworn it was a variable". Trailing parens in UFCS chains are just warts, this is the reality. Let's deal with it. Andrei
Dec 02 2012
On 2012-11-19 23:23, Rob T wrote:Also do not forget that we can not only drop the (), but also perform assignments to functions that take in one variable, but I'm not sure if the return must be void for that to work. It seems strange to allow arbitrarily dual function/variable constructs for functions, but being strange does not necessarily mean it is wrong.The return value doesn't have to be void. I always return the new value from my setters, to allow chained assignments. If chained assignment can't be used the property hasn't emulated a variable properly. class Foo { private int bar_; property int bar () { return bar_; } property int bar (int value) { return bar_ = value; } } auto foo = new Foo; int a = foo.bar = 3; Of course the correct solution would be to implement a form of property rewrite in the compiler. Transforming the following code: int a = foo.bar = 3; To: foo.bar = 3; int a = foo.bar; If "foo.bar" is a method/ property. -- /Jacob Carlborg
Nov 20 2012
On Monday, 19 November 2012 at 21:44:35 UTC, Jonathan M Davis wrote:Excep that i don't think that it's really a question of style. It's treating a function as if it were a variable, when it's not only not a variable, but it's not even acting like one. It's implying that the code has one set of semantics when it has another.This is just an old habit to see identifier with parens as a function call and identifier without parens as a variable, so calling functions without parens seem too unconventional to you. However there are many languages which dropped this tradition and they are known for being expressive and concise, that's why people love them. Recently we saw an article from Walter about component programming which one could say was really about function composition. It's really convenient to write code in conveyor-style, this is what we see often in functional languages, as well as some dynamic OO ones. For example, the task of reversing words in a string may look like: "one two three".split.map{|s| s.reverse}.join(' ') in Ruby print . unwords . map reverse . words $ "one two three" in Haskell "one two three" |> split " " |> List.map reverse |> String.join " " |> print_string in OCaml and something similar and even without dots in Scala. Ease of chaining functions together is one of the things that make those languages so pleasant to work with. I love to have the same in current D and it would be a pity to lose it due to a clash with some old-fashioned tradition.
Nov 19 2012
On 11/20/12 2:48 AM, thedeemon wrote: [snip]"one two three".split.map{|s| s.reverse}.join(' ') in Ruby print . unwords . map reverse . words $ "one two three" in Haskell "one two three" |> split " " |> List.map reverse |> String.join " " |> print_string in OCaml and something similar and even without dots in Scala. Ease of chaining functions together is one of the things that make those languages so pleasant to work with. I love to have the same in current D and it would be a pity to lose it due to a clash with some old-fashioned tradition.A very good argument. Thanks! Andrei
Nov 20 2012
On 2012-11-20 08:48, thedeemon wrote:This is just an old habit to see identifier with parens as a function call and identifier without parens as a variable, so calling functions without parens seem too unconventional to you. However there are many languages which dropped this tradition and they are known for being expressive and concise, that's why people love them. Recently we saw an article from Walter about component programming which one could say was really about function composition. It's really convenient to write code in conveyor-style, this is what we see often in functional languages, as well as some dynamic OO ones. For example, the task of reversing words in a string may look like:I completely agree."one two three".split.map{|s| s.reverse}.join(' ') in RubyIn this particular case you can use a shorter form of the map call: "one two three".split.map(&:reverse).join(' ')print . unwords . map reverse . words $ "one two three" in Haskell "one two three" |> split " " |> List.map reverse |> String.join " " |> print_string in OCaml and something similar and even without dots in Scala.Wouldn't the Scala syntax look fairly similar to Ruby: "one two three".split.map(reverse).join(' ')Ease of chaining functions together is one of the things that make those languages so pleasant to work with. I love to have the same in current D and it would be a pity to lose it due to a clash with some old-fashioned tradition.I completely agree again. -- /Jacob Carlborg
Nov 20 2012
Le 20/11/2012 04:33, Jacob Carlborg a écrit :On 2012-11-20 08:48, thedeemon wrote:Note the map(reverse) and not map(&reverse)This is just an old habit to see identifier with parens as a function call and identifier without parens as a variable, so calling functions without parens seem too unconventional to you. However there are many languages which dropped this tradition and they are known for being expressive and concise, that's why people love them. Recently we saw an article from Walter about component programming which one could say was really about function composition. It's really convenient to write code in conveyor-style, this is what we see often in functional languages, as well as some dynamic OO ones. For example, the task of reversing words in a string may look like:I completely agree."one two three".split.map{|s| s.reverse}.join(' ') in RubyIn this particular case you can use a shorter form of the map call: "one two three".split.map(&:reverse).join(' ')print . unwords . map reverse . words $ "one two three" in Haskell "one two three" |> split " " |> List.map reverse |> String.join " " |> print_string in OCaml and something similar and even without dots in Scala.Wouldn't the Scala syntax look fairly similar to Ruby: "one two three".split.map(reverse).join(' ')Ease of chaining functions together is one of the things that make those languages so pleasant to work with. I love to have the same in current D and it would be a pity to lose it due to a clash with some old-fashioned tradition.I completely agree again.
Nov 20 2012
On 2012-11-21 07:55, deadalnix wrote:Note the map(reverse) and not map(&reverse)I said "fairly similar" not "exactly the same" :) -- /Jacob Carlborg
Nov 20 2012
On Wednesday, 21 November 2012 at 07:44:36 UTC, Jacob Carlborg wrote:On 2012-11-21 07:55, deadalnix wrote:I don't understand why dropping () is that a big deal when dropping & isn't.Note the map(reverse) and not map(&reverse)I said "fairly similar" not "exactly the same" :)
Nov 21 2012
On 11/21/2012 06:53 PM, deadalnix wrote:On Wednesday, 21 November 2012 at 07:44:36 UTC, Jacob Carlborg wrote:Relative frequencies. Amount of visual noise. People are used to it.On 2012-11-21 07:55, deadalnix wrote:I don't understand why dropping () is that a big deal when dropping & isn't.Note the map(reverse) and not map(&reverse)I said "fairly similar" not "exactly the same" :)
Nov 21 2012
On 2012-11-21 18:53, deadalnix wrote:I don't understand why dropping () is that a big deal when dropping & isn't.Now I'm really confused. What did you mean when you original wrote: "Note the map(reverse) and not map(&reverse)" -- /Jacob Carlborg
Nov 21 2012
On Wednesday, 21 November 2012 at 18:07:42 UTC, Jacob Carlborg wrote:On 2012-11-21 18:53, deadalnix wrote:I meant that because of the fact that function isn't called implicitly, it is possible to pass it directly without having the & . The & is a source of noise as the () are and introduce really complicated rules in the language to know if funName have to be executed or not. Scala's design is consistent on this point. D's isn't because we pursue conflicting goals. Those have been conflated in a messy implementation defined behavior ATM. We have to accept to break some code here or to stick with current implementation and accept that is is inconsistent and messy (and sometime leading to very weird possibilities like Timon Gehr demonstrated).I don't understand why dropping () is that a big deal when dropping & isn't.Now I'm really confused. What did you mean when you original wrote: "Note the map(reverse) and not map(&reverse)"
Nov 21 2012
Le 19/11/2012 06:58, Andrei Alexandrescu a écrit :On 11/19/12 4:01 AM, monarch_dodra wrote:As aid bunch of time, I'm pretty sure we can have a clean semantic and still allow mosts use of parenthsesless call using opDispatch .I kind of agree with Jonathan here. property really shines when you want to "add" an attribute to a struct.I kind of agree with him, too, but it would be a mistake to not reckon a change in dynamics. UFCS makes all those extra parens just awkward, and people will vote with their code regardless whether some particular viewpoint from some particular angle considers the approach backwards. Andrei
Nov 19 2012
On 11/20/12 12:24 AM, deadalnix wrote:Le 19/11/2012 06:58, Andrei Alexandrescu a écrit :Could you please give more detail? On first sight this seems to complicate the majority case for the benefit of a few. AndreiOn 11/19/12 4:01 AM, monarch_dodra wrote:As aid bunch of time, I'm pretty sure we can have a clean semantic and still allow mosts use of parenthsesless call using opDispatch .I kind of agree with Jonathan here. property really shines when you want to "add" an attribute to a struct.I kind of agree with him, too, but it would be a mistake to not reckon a change in dynamics. UFCS makes all those extra parens just awkward, and people will vote with their code regardless whether some particular viewpoint from some particular angle considers the approach backwards. Andrei
Nov 19 2012
Le 19/11/2012 21:53, Andrei Alexandrescu a écrit :On 11/20/12 12:24 AM, deadalnix wrote:consider the following opDispatch : auto opDispatch(string name, T, U...)(T function() t, U args) { return mixin("t()." ~ name ~ "(args)"); } I ommited to support delegates and to do the right checks in order to make the example obvious. With such opDispatch, it is easy to get an autoevaluation for chained functions call via UFCS. () is only required on the last one. I don't see how it can complicate the current situation. The current situation is like crazy complicated, and nobody is sure of what can be expected to be the correct behavior in many corner cases.Le 19/11/2012 06:58, Andrei Alexandrescu a écrit :Could you please give more detail? On first sight this seems to complicate the majority case for the benefit of a few. AndreiOn 11/19/12 4:01 AM, monarch_dodra wrote:As aid bunch of time, I'm pretty sure we can have a clean semantic and still allow mosts use of parenthsesless call using opDispatch .I kind of agree with Jonathan here. property really shines when you want to "add" an attribute to a struct.I kind of agree with him, too, but it would be a mistake to not reckon a change in dynamics. UFCS makes all those extra parens just awkward, and people will vote with their code regardless whether some particular viewpoint from some particular angle considers the approach backwards. Andrei
Nov 19 2012
Le 19/11/2012 00:45, thedeemon a écrit :On Monday, 19 November 2012 at 08:23:43 UTC, Jonathan M Davis wrote:With opDispatch and clear semantic, the following is doable : iota(0, 1000000).map!(to!string).retro.take(50).retro[10].writeln(); No need for an ambiguous situation where function get called implicitly.On Monday, November 19, 2012 09:16:29 Rob T wrote:I very much like the combination of UFCS, ranges and parens-free style which allows writing code like iota(0, 1000000).map!(to!string).retro.take(50).retro[10].writeln; So I like Andrei's idea to force property only for those functions where it's absolutely necessary to fight ambiguity.My guess is that if property gets enforced, we'll see a lot of functions with empty parameter lists being defined as property for the sole reason to get rid of having to type in the ().Which completely violates the concept of a property in the first place. It's intended to be an abstraction for a variable. Using property just to get rid of parens would be like naming types with verbs instead of nouns. It's completely backwards. - Jonathan M Davis
Nov 19 2012
On Monday, 19 November 2012 at 08:23:43 UTC, Jonathan M Davis wrote:Which completely violates the concept of a property in the first place. It's intended to be an abstraction for a variable. Using property just to get rid of parens would be like naming types with verbs instead of nouns. It's completely backwards. - Jonathan M DavisI know what you are saying, but I know that most people will usually follow the path of least resistance, so if a lot of people really dislike typing in () all over the place and are given a way out, then they'll likely take it, so long as it won't matter in any significant way in terms of practicality. Another case that I would say violates the property concept, is a getter property function that returns a non-const ref, and reusing the same property function as a setter (for cases where there's nothing to be done when setting). It is less work when you can get away with defining one property function that looks like two, even though it may be bad in some way, I expect it will be done often. I suppose with property enforcement in place, the compiler can be adjusted to prevent non-const ref return values for property getters. That would also make it a bit more difficult to specify property just to get rid of typing (). The big question is what do we gain and what do we lose from enforcements like this? It has to be worth doing, or it should not be done, Personally, I think we're much better off not attempting to enforce coding style through restrictions that could be viewed as unnecessary. --rt
Nov 19 2012
So is it official? We keep the d1 syntax for none property functions? Even the assignment? So for the dynamic stuff opDispatch only (for properties and methods)? The ()() syntax remains for the dynamic delegate properties.
Nov 19 2012
On Monday, November 19, 2012 12:31:02 sclytrack wrote:So is it official? We keep the d1 syntax for none property functions? Even the assignment?No. It's not official. No decision has been made. For the moment, nothing has changed about property. It may very well change, but nothing has happened but some discussion on the matter, and while Andrei is suggesting may very well be what happens, not everyone agrees with his assessment. We'll have to wait and see. - Jonathan M Davis
Nov 19 2012
Isn't it possible to have parentheses optional only for UFCS? E.g. Allow: I 5.writeln Dissallow: void f() { writeln("hi"); } f; // this currently works I don't know if this is possible to implement.
Dec 04 2012
On 04/12/2012 16:24, Minas Mina wrote:Isn't it possible to have parentheses optional only for UFCS? E.g. Allow: I 5.writeln Dissallow: void f() { writeln("hi"); } f; // this currently works I don't know if this is possible to implement.I expect it is, perhaps by disallowing calling a property function with no arguments.
Dec 04 2012
It's regular function called as property [getter] of module. without () only to property. function without () - property - for simple tasks. function/procedure/action with () - for resource-intensive tasks.void f() { writeln("hi"); } f; // this currently works I don't know if this is possible to implement.I expect it is, perhaps by disallowing calling a property function with no arguments.
Dec 04 2012
It's regular function called as property [getter] of module. without () only to property. function without () - property - for simple tasks. function/procedure/action with () - for resource-intensive tasks.void f() { writeln("hi"); } f; // this currently works I don't know if this is possible to implement.I expect it is, perhaps by disallowing calling a property function with no arguments.
Dec 04 2012
On Tuesday, 4 December 2012 at 16:24:27 UTC, Minas Mina wrote:Isn't it possible to have parentheses optional only for UFCS? E.g. Allow: I 5.writeln Dissallow: void f() { writeln("hi"); } f; // this currently works I don't know if this is possible to implement.module main; void f() { writeln("hi"); } main.f; // OK or not? If we're to make the empty braces optional, we have to ask this question: What will enforcing the empty braces buy you? Based on the comments so far, all that it does is tell you at a glance that the symbol is a function call. Without the braces you'll have to dig a little deeper into the code to figure it out. So the () effectively serves the purpose of a naming convention for functions. However as was pointed out in this thread, there are a few real situations where even with () enforcement, you still won't necessarily know what the symbol represents without digging into the code, for example if property is enforced. There are arguments in favor of property enforcement, which is to encourage the programmer to think in terms of making a function behave like a variable and nothing else. It also discourages dropping the () elsewhere. The argument against property enforcement, is that it enforces a coding style on the programmer, which may be subjective, and not providing any real gain. What "bad" thing does () enforcement do? Based the comments, it seems that a lot of people really dislike the empty braces when chaining together multiple function calls, i.e., it looks ugly and is more effort for apparently no real gain, so it does not matter if they are UFCS calls or not, it's just ugly when chaining. The arguments against dropping the () when chaining, is that you loose the ability to see at a glance what is a function call and what is not, although with the exception of enforced property functions. I think the above sums up the arguments for and against, but maybe not. --rt
Dec 04 2012
On Tuesday, 4 December 2012 at 16:24:27 UTC, Minas Mina wrote:Isn't it possible to have parentheses optional only for UFCS?This is exactly what Nimrod does. ;-) The () can also be omitted in calls used as a statement (not as an expression). BTW Nimrod calls it "method call syntax"; there is hardly anything "uniform" in having the first argument in a special position...
Dec 04 2012
On Tuesday, 4 December 2012 at 16:24:27 UTC, Minas Mina wrote:Isn't it possible to have parentheses optional only for UFCS? E.g. Allow: I 5.writeln Dissallow: void f() { writeln("hi"); } f; // this currently works I don't know if this is possible to implement.module main; void f() { writeln("hi"); } main.f; // OK or not? I think the argument for vs against is simply a coding style issue, some like dropping empty braces, some do not. --rt
Dec 04 2012
On Tuesday, 4 December 2012 at 16:24:27 UTC, Minas Mina wrote:Isn't it possible to have parentheses optional only for UFCS? E.g. Allow: I 5.writeln Dissallow: void f() { writeln("hi"); } f; // this currently works I don't know if this is possible to implement.module main; void f() { writeln("hi"); } main.f; // OK or not? I think the argument for vs against is simply a coding style issue, some like dropping empty braces, some do not. --rt
Dec 04 2012
On Tuesday, 4 December 2012 at 18:28:55 UTC, Rob T wrote:On Tuesday, 4 December 2012 at 16:24:27 UTC, Minas Mina wrote:It is also a ambiguity issue and the extra need of & to not call the function (which also introduce ambiguity).Isn't it possible to have parentheses optional only for UFCS? E.g. Allow: I 5.writeln Dissallow: void f() { writeln("hi"); } f; // this currently works I don't know if this is possible to implement.module main; void f() { writeln("hi"); } main.f; // OK or not? I think the argument for vs against is simply a coding style issue, some like dropping empty braces, some do not. --rt
Dec 05 2012
On Wednesday, 5 December 2012 at 18:32:16 UTC, deadalnix wrote:The () acts like a naming convention, and with or without enforcement you are free to choose whatever naming convention you desire, thus reducing ambiguity.I think the argument for vs against is simply a coding style issue, some like dropping empty braces, some do not. --rtIt is also a ambiguity issueand the extra need of & to not call the function (which also introduce ambiguity).If you dislike it, rather than use &, I suppose you can add on the () instead. In fact you can specify () everywhere if you prefer. --rt
Dec 05 2012
On Wednesday, 5 December 2012 at 20:27:18 UTC, Rob T wrote:On Wednesday, 5 December 2012 at 18:32:16 UTC, deadalnix wrote:I'll do like I've not read anything and let you rethink about that.The () acts like a naming convention, and with or without enforcement you are free to choose whatever naming convention you desire, thus reducing ambiguity.I think the argument for vs against is simply a coding style issue, some like dropping empty braces, some do not. --rtIt is also a ambiguity issueand the extra need of & to not call the function (which also introduce ambiguity).If you dislike it, rather than use &, I suppose you can add on the () instead. In fact you can specify () everywhere if you prefer.
Dec 05 2012
On Tuesday, 4 December 2012 at 16:24:27 UTC, Minas Mina wrote:Isn't it possible to have parentheses optional only for UFCS? E.g. Allow: I 5.writeln Dissallow: void f() { writeln("hi"); } f; // this currently works I don't know if this is possible to implement.module main; void f() { writeln("hi"); } main.f; // OK or not? I think the argument for vs against is simply a coding style issue, some like dropping empty braces, some do not. --rt
Dec 04 2012
On Tuesday, 4 December 2012 at 16:24:27 UTC, Minas Mina wrote:Isn't it possible to have parentheses optional only for UFCS? E.g. Allow: I 5.writeln Dissallow: void f() { writeln("hi"); } f; // this currently works I don't know if this is possible to implement.module main; void f() { writeln("hi"); } main.f; // OK or not? I think the argument for vs against is simply a coding style issue, some like dropping empty braces, some do not. --rt
Dec 04 2012
On Tuesday, 4 December 2012 at 16:24:27 UTC, Minas Mina wrote:Isn't it possible to have parentheses optional only for UFCS? E.g. Allow: I 5.writeln Dissallow: void f() { writeln("hi"); } f; // this currently works I don't know if this is possible to implement.module main; void f() { writeln("hi"); } main.f; // OK or not? I think the argument for vs against is simply a coding style issue, some like dropping empty braces, some do not. --rt
Dec 04 2012
On Tuesday, 4 December 2012 at 16:24:27 UTC, Minas Mina wrote:Isn't it possible to have parentheses optional only for UFCS?That's exactly what Nimrod does ;-). It also allows to leave out the () for calls used as a statement (not as an expression). BTW Nimrod calls it "method call syntax" as there is hardly anything "uniform" about putting the first argument in a special position.
Dec 04 2012
On Tuesday, 4 December 2012 at 16:24:27 UTC, Minas Mina wrote:Isn't it possible to have parentheses optional only for UFCS? E.g. Allow: I 5.writeln Dissallow: void f() { writeln("hi"); } f; // this currently works I don't know if this is possible to implement.+1 5.writeln is going to be translated by the compiler as writeln(5) anyway, so I think this is a great compromise.
Dec 04 2012
On Monday, 19 November 2012 at 06:53:46 UTC, Andrei Alexandrescu wrote:On 11/19/12 1:16 AM, Jonathan M Davis wrote:As I've been saying: make parens optional only if the function is followed by a dot. Otherwise, make parens compulsory for functions: function1.function2.function3(); //allowed function1(); //allowed function1; // forbidden property-ies should be forbidden to use paranthesis, no matter the context.On Monday, November 19, 2012 07:02:03 Rob T wrote:I think UFCS changes the playfield quite a lot. Code using UFCS looks a whole lot crappier with a bunch of arbitrary extra parens.
Jan 29 2013
On 11/19/12 1:02 AM, Rob T wrote:So what's up with property?It's a mistake on top of another. We need to redesign it to such that the keyword ' property' is only required in cases that otherwise would be ambiguous (functions returning functions). Andrei
Nov 18 2012
On Monday, 19 November 2012 at 06:52:11 UTC, Andrei Alexandrescu wrote:We need to redesign it to such that the keyword ' property' is only required in cases that otherwise would be ambiguous (functions returning functions).There's a fairly easy way to do this, thanks to the property word: 1) Any function without property remains exactly the same as it is now. Parens are *not* required on them. 2) Any function with property is rewritten into a call immediately. Therefore, putting () is naturally an error or delegate call because of the return value. property int foo() {} foo; // rewritten into foo() transparently foo(); // since foo is already foo(), this becomes foo()() - an error because you cannot call an int like a function The only potential for code breakage here is on stuff marked property, which if you have been marking it on semantic properties already (NOT on places where you just wanted appease the -property switch's idiotic rules), should be fine. If in doubt, leave property off. That leaves things exactly as they are.
Nov 19 2012
On 11/19/12 8:18 AM, Adam D. Ruppe wrote:On Monday, 19 November 2012 at 06:52:11 UTC, Andrei Alexandrescu wrote:[snip] Would you please start a DIP with a paste of this idea? AndreiWe need to redesign it to such that the keyword ' property' is only required in cases that otherwise would be ambiguous (functions returning functions).There's a fairly easy way to do this, thanks to the property word:
Nov 19 2012
On Monday, 19 November 2012 at 15:01:36 UTC, Andrei Alexandrescu wrote:Would you please start a DIP with a paste of this idea?here it is: http://www.prowiki.org/wiki4d/wiki.cgi?LanguageDevel/DIPs/DIP21 I tried to implement this a while ago and hit some pain after some early success. The pain was trying to get assignments to work without breaking other cases like returning ref. My plan was to make any reference to a property change to a CallExp or whatever. But if you do that and it is on the left hand side of an assignment, you do the wrong thing. foo = foo + 1; should generally become: foo(foo() + 1); but if there isn't a setter, we should leave it as foo() = foo() + 1; and finding the setter is a bit of a pain. Then, of course, we ideally want foo += 1 to work too.. Maybe someone who knows the compiler better than me will make it look easy though.
Nov 19 2012
On Monday, 19 November 2012 at 18:02:06 UTC, Adam D. Ruppe wrote:On Monday, 19 November 2012 at 15:01:36 UTC, Andrei Alexandrescu wrote:Thanks a lot for doing this! It's a pity that the last bigger discussion didn't lead anywhere, I don't think there was much disagreement. Hopefully, having a DIP to discuss will catalyze the process a bit. DavidWould you please start a DIP with a paste of this idea?here it is: http://www.prowiki.org/wiki4d/wiki.cgi?LanguageDevel/DIPs/DIP21
Nov 19 2012
Le 19/11/2012 10:02, Adam D. Ruppe a écrit :On Monday, 19 November 2012 at 15:01:36 UTC, Andrei Alexandrescu wrote:This make it impossible to only define a getter only when one want to return by reference.Would you please start a DIP with a paste of this idea?here it is: http://www.prowiki.org/wiki4d/wiki.cgi?LanguageDevel/DIPs/DIP21 I tried to implement this a while ago and hit some pain after some early success. The pain was trying to get assignments to work without breaking other cases like returning ref. My plan was to make any reference to a property change to a CallExp or whatever. But if you do that and it is on the left hand side of an assignment, you do the wrong thing. foo = foo + 1; should generally become: foo(foo() + 1); but if there isn't a setter, we should leave it as foo() = foo() + 1; and finding the setter is a bit of a pain. Then, of course, we ideally want foo += 1 to work too..Maybe someone who knows the compiler better than me will make it look easy though.
Nov 19 2012
On Monday, November 19, 2012 21:31:09 deadalnix wrote:Le 19/11/2012 10:02, Adam D. Ruppe a =C3=A9crit :ote:On Monday, 19 November 2012 at 15:01:36 UTC, Andrei Alexandrescu wr=earlyWould you please start a DIP with a paste of this idea?=20 here it is: http://www.prowiki.org/wiki4d/wiki.cgi?LanguageDevel/DIPs/DIP21 =20 I tried to implement this a while ago and hit some pain after some =akingsuccess. The pain was trying to get assignments to work without bre=p orother cases like returning ref. =20 My plan was to make any reference to a property change to a CallEx=+ 1;whatever. But if you do that and it is on the left hand side of an assignment, you do the wrong thing. =20 foo =3D foo + 1; =20 should generally become: =20 foo(foo() + 1); =20 but if there isn't a setter, we should leave it as foo() =3D foo() =llyand finding the setter is a bit of a pain. Then, of course, we idea=want foo +=3D 1 to work too..=20 This make it impossible to only define a getter only when one want to=return by reference.Returning by reference generally already defeats the purpose of definin= g a=20 property function in the first place. Certainly, if you return by ref, = it=20 _definitely_ defeats the purpose of only defining a getter. By returnin= g by ref=20 from a getter, you've not only implicitly declared a setter, but you've= made=20 it impossible to verify anything about what's being set, because it's g= oing=20 through the ref rather than through an actual setter. - Jonathan M Davis
Nov 19 2012
On Tuesday, 20 November 2012 at 05:31:09 UTC, deadalnix wrote:This make it impossible to only define a getter only when one want to return by reference.If there isn't a setter, you don't change things. If setter is present: foo = foo + 1; // becomes: foo(foo() + 1); If setter is not present: foo = foo + 1; // becomes: foo() = foo() + 1; If foo returns an rvalue, this is a natural error. If it returns ref, it works fine.
Nov 20 2012
On 2012-11-19 19:02, Adam D. Ruppe wrote:On Monday, 19 November 2012 at 15:01:36 UTC, Andrei Alexandrescu wrote:It would be really nice if we could implement property rewriting in the compiler.Would you please start a DIP with a paste of this idea?here it is: http://www.prowiki.org/wiki4d/wiki.cgi?LanguageDevel/DIPs/DIP21 I tried to implement this a while ago and hit some pain after some early success. The pain was trying to get assignments to work without breaking other cases like returning ref. My plan was to make any reference to a property change to a CallExp or whatever. But if you do that and it is on the left hand side of an assignment, you do the wrong thing. foo = foo + 1; should generally become: foo(foo() + 1); but if there isn't a setter, we should leave it as foo() = foo() + 1; and finding the setter is a bit of a pain. Then, of course, we ideally want foo += 1 to work too..Maybe someone who knows the compiler better than me will make it look easy though.Should this be allowed for functions that isn't marked with property: foo = 3; -- /Jacob Carlborg
Nov 20 2012
On Tuesday, 20 November 2012 at 12:44:44 UTC, Jacob Carlborg wrote:Should this be allowed for functions that isn't marked with property: foo = 3;Hell no!
Nov 20 2012
On Tue, 20 Nov 2012 13:20:10 -0000, monarch_dodra <monarchdodra gmail.com> wrote:On Tuesday, 20 November 2012 at 12:44:44 UTC, Jacob Carlborg wrote:+1 I think this "feature" should just be removed, and property implemented fully/correctly. R -- Using Opera's revolutionary email client: http://www.opera.com/mail/Should this be allowed for functions that isn't marked with property: foo = 3;Hell no!
Nov 20 2012
On Tuesday, 20 November 2012 at 12:44:44 UTC, Jacob Carlborg wrote:Should this be allowed for functions that isn't marked with property: foo = 3;Yes. We should *only* be changing the way property is implemented. (Namely, actually implementing it!) Don't want to break existing code. The new changes must be opt in. If there's both an property setter and a regular function, the property should be used here.
Nov 20 2012
On Tue, 20 Nov 2012 13:26:15 -0000, Adam D. Ruppe <destructionator gmail.com> wrote:On Tuesday, 20 November 2012 at 12:44:44 UTC, Jacob Carlborg wrote:Usually I'd agree but this is a case of a wart we should just remove IMO. The fix for breaking cases is simple, add property.Should this be allowed for functions that isn't marked with property: foo = 3;Yes. We should *only* be changing the way property is implemented. (Namely, actually implementing it!) Don't want to break existing code. The new changes must be opt in.If there's both an property setter and a regular function, the property should be used here.Agreed. But it's waay clearer whats going on if property is required to call functions using this syntax. R -- Using Opera's revolutionary email client: http://www.opera.com/mail/
Nov 20 2012
On Tuesday, 20 November 2012 at 13:50:10 UTC, Regan Heath wrote:Usually I'd agree but this is a case of a wart we should just remove IMO. The fix for breaking cases is simple, add property.meh, I sometimes use it, but if overloading on property works, that's easy enough to allow both ways. I use it in some big chaining things: Element.make("div").className("foo").value = "bar"; vs auto element = Element.make("div"); element.className = "foo"; element.value = "bar"; Using one or the other depending on if I have a variable name there anyway. This would be arguably *better* with separation, but I don't have the level of hatred for one function used both ways (on setter nor getter) the way a lot of people do.
Nov 20 2012
BTW I've been pasting some of my posts into the wiki thing http://prowiki.org/wiki4d/wiki.cgi?LanguageDevel/DIPs/DIP21#section4 Kinda sloppy to just paste, but this way everything on my mind is in one place so we don't have to reread the thread to get it together. Of course, being a wiki, feel free to do the same with anything you want to note.
Nov 20 2012
On Tuesday, 20 November 2012 at 14:13:51 UTC, Adam D. Ruppe wrote:On Tuesday, 20 November 2012 at 13:50:10 UTC, Regan Heath wrote:That's a good point. If the property is a "setter", then both "value = bla" and "value(bla)" is legal. If the property is a getter, then only "=" works. But I think it would be fine if "value(bla)" were tanslated to "value = bla" in that case. However, if you allow "foo = rhs" => "foo(rhs)" on a non-propety, then code like this becomes legal: writeln = 5; And that's bullshit.Usually I'd agree but this is a case of a wart we should just remove IMO. The fix for breaking cases is simple, add property.meh, I sometimes use it, but if overloading on property works, that's easy enough to allow both ways. I use it in some big chaining things: Element.make("div").className("foo").value = "bar"; vs auto element = Element.make("div"); element.className = "foo"; element.value = "bar";
Nov 20 2012
On 11/20/2012 02:49 PM, Regan Heath wrote:On Tue, 20 Nov 2012 13:26:15 -0000, Adam D. Ruppe <destructionator gmail.com> wrote:Not really. property T front(T)(T[] arr) { return arr[0]; } [1,2,3,4].front; front = [1,2,3,4];On Tuesday, 20 November 2012 at 12:44:44 UTC, Jacob Carlborg wrote:Usually I'd agree but this is a case of a wart we should just remove IMO. The fix for breaking cases is simple, add property.Should this be allowed for functions that isn't marked with property: foo = 3;Yes. We should *only* be changing the way property is implemented. (Namely, actually implementing it!) Don't want to break existing code. The new changes must be opt in.If there's both an property setter and a regular function, the property should be used here.Agreed. But it's waay clearer whats going on if property is required to call functions using this syntax. R
Nov 20 2012
Le 20/11/2012 12:18, Timon Gehr a écrit :On 11/20/2012 02:49 PM, Regan Heath wrote:I conclude that property should be limited to member function or UFCS calls. Otherwize, we get really weird stuffs going on.On Tue, 20 Nov 2012 13:26:15 -0000, Adam D. Ruppe <destructionator gmail.com> wrote:Not really. property T front(T)(T[] arr) { return arr[0]; } [1,2,3,4].front; front = [1,2,3,4];On Tuesday, 20 November 2012 at 12:44:44 UTC, Jacob Carlborg wrote:Usually I'd agree but this is a case of a wart we should just remove IMO. The fix for breaking cases is simple, add property.Should this be allowed for functions that isn't marked with property: foo = 3;Yes. We should *only* be changing the way property is implemented. (Namely, actually implementing it!) Don't want to break existing code. The new changes must be opt in.If there's both an property setter and a regular function, the property should be used here.Agreed. But it's waay clearer whats going on if property is required to call functions using this syntax. R
Nov 20 2012
On Wed, 21 Nov 2012 06:07:51 -0000, deadalnix <deadalnix gmail.com> wrot= e:Le 20/11/2012 12:18, Timon Gehr a =E9crit :On 11/20/2012 02:49 PM, Regan Heath wrote:On Tue, 20 Nov 2012 13:26:15 -0000, Adam D. Ruppe <destructionator gmail.com> wrote:On Tuesday, 20 November 2012 at 12:44:44 UTC, Jacob Carlborg wrote:=Should this be allowed for functions that isn't marked with =property: foo =3D 3;Yes. We should *only* be changing the way property is implemented.=(Namely, actually implementing it!) Don't want to break existing code. The new changes must be opt in.Usually I'd agree but this is a case of a wart we should just remove=dIMO. The fix for breaking cases is simple, add property.If there's both an property setter and a regular function, the property should be used here.Agreed. But it's waay clearer whats going on if property is require==I conclude that property should be limited to member function or UFCS=to call functions using this syntax. RNot really. property T front(T)(T[] arr) { return arr[0]; } [1,2,3,4].front; front =3D [1,2,3,4];calls. Otherwize, we get really weird stuffs going on.Such was my assumption in this case :p R -- = Using Opera's revolutionary email client: http://www.opera.com/mail/
Nov 21 2012
On Tuesday, 20 November 2012 at 13:26:17 UTC, Adam D. Ruppe wrote:On Tuesday, 20 November 2012 at 12:44:44 UTC, Jacob Carlborg wrote:Here's another way to test if the idea is sound, by asking a few questions: For some time, we've had the unrestricted ability to drop empty "()" and perform assignments to any function with appropriate sig. Has there been a chorus of complaints about having it? Any flood of problems caused by it? More importantly, how many of us are now making good use out of it without even a seconds thought? How many of us would really miss it if taken out? I still think there's a lot more to the picture, but I cannot yet pin it down well enough to say what it is. I'll try and share my thoughts, so that maybe someone more knowledgeable than me can figure it out. What is really bugging me, is that I know there's something more generalized going on here that we may have an opportunity to take advantage of, before things get cast in "unbreakable" stone, so to speak. I've been asking myself some questions, off the wall stuff, not necessarily possible for D due to practical limitations, but perhaps possible for E: 1) Why must a variable operate as it does and why must a function operate as it does? Are the two "things" really all that much different? I can successfully imagine that a variable is a function wrapper around a data store. 2) We're allowing only some functions to operate like variables, and this is because not all functions are allowed to operate in this way due to their parameter signature. Specifically, if the function has more than one parameter, it cannot be used as if it were a variable. Example: // We can do this void Foo( int ){ ... }; int Foo(){ ... }; Foo = 5; int Y = Foo; // so why not something like this? void Foo( int, string, float ){ ... }; ( int, string, float )Foo(){ ... }; Foo = { 1, "test", 3.456 }; { someint, somestring, sonefloat } = Foo; Why must we be limited to a single return and a single assignment value? (I recall this topic was brought up before, and I know we can use struct to emulate a similar effect) 3) If some functions can operate like variables, then why must no variable be able to operate like some functions? This is not allowed in D: int x, y; x(1); y = x(); y(x()); Why must this be so? 4) Which syntax or constructs are easier to understand, and which are not, given the context they are used in? If we had choice, will the context prefer one syntax over another in terms of clarity? If we don't have choice, then the context may enforce poor clarity in some cases. 5) We really enjoy the power we get from generic templates, yet the generic abilities of templates may possibly be lessened considerably because of the incompatibility between variables and functions, and I would also say classes and structs, although with UFCS the situation has improved (which may be why we like having them so much). 6) What advantage do we get by making variables and functions incompatible with each other (in terms with how they are manipulated or operated on), and what advantages could we get if we made them fully compatible (or at least more compatible). Hopefully some of these questions will provide food for some thought on the property matter. --rtShould this be allowed for functions that isn't marked with property: foo = 3;Yes. We should *only* be changing the way property is implemented. (Namely, actually implementing it!) Don't want to break existing code. The new changes must be opt in.
Nov 20 2012
Just a quick thought... it's not like a = 10 has no way to trigger a function anyway. opAssign does it. Is that evil? This discussion kinda reminds me of some of the C++ arguments over operator overloading. They argue overloaded operators are evil because they don't look like function calls... but I think most of us agree that is generally useful. D's properties of course aren't exactly the same but I think there's some similarities there that matter.
Nov 20 2012
On Tuesday, 20 November 2012 at 18:06:22 UTC, Rob T wrote:Here's another way to test if the idea is sound, by asking a few questions:After thinking about it a bit more, I think there may be two conflicting notions: a) The use of optional parenthesis. b) The property switch, which allows a function to emulate an attribute, namelly, allow writting "bla = a.foo;" or "a.foo = 5;", when "foo" isn't actually an attribute of a. I *could* see parenthesis being optional, but I'll never accept "a.foo = 5" calling "a.foo(5)" if "foo" isn't attribute qualified.
Nov 20 2012
On Tuesday, November 20, 2012 19:48:01 monarch_dodra wrote:On Tuesday, 20 November 2012 at 18:06:22 UTC, Rob T wrote:Yes, you basically have folks who want to have strictly defined properties simply want to leave off parens (especially when they're using UFCS and already forced to provide a template argument - e.g. with map or filter or whatnot). On some level, they can coexist, and on some level, they're conflicting notions. Given the fact that this subject is extremely devisive, I suspect that the best that we can hope for at this point is for lax property enforcement - that is that it's enforced that property functions are used as properties but there is no enforcement that non- property functions be called with parens. We might be able to further restrict them so that they can't be used with the setter syntax (making it so that they must be property for that to work), but with UFCS and the use of templated functions taking predicates, dropping parens is way too popular to disallow it, much as I personally hate the idea. - Jonathan M DavisHere's another way to test if the idea is sound, by asking afew questions:After thinking about it a bit more, I think there may be two conflicting notions: a) The use of optional parenthesis. b) The property switch, which allows a function to emulate an attribute, namelly, allow writting "bla = a.foo;" or "a.foo = 5;", when "foo" isn't actually an attribute of a.
Nov 20 2012
On Tuesday, 20 November 2012 at 19:06:22 UTC, Jonathan M Davis wrote:Given the fact that this subject is extremely devisive, I suspect that the best that we can hope for at this point is for lax property enforcementproperty shouldn't be about enforcement. This is the fundamental flaw in the -property switch. While I think you and I are talking about the same goal, this is an important distinction to make: the fix isn't syntax. It is a semantic rewrite. After referencing a property is rewritten to be a call, the syntax will just work: property int foo() {} int a = foo(); // the error here is NOT "you must not use () on properties". It is "type int is not callable" This is something that's bothered me about the property debate since day one: we spend all this time talking about syntax.... but that's a side effect, not the core question.
Nov 20 2012
On Tuesday, November 20, 2012 20:12:56 Adam D. Ruppe wrote:On Tuesday, 20 November 2012 at 19:06:22 UTC, Jonathan M Davis wrote:It's the same result. property means that the function is treated as a variable, so it doesn't make sense that parens be used. If the error treats it like a variable to the point that it complains about trying to use parens on the variable rather than the fact that you tried to use parens on an property function, all the better. - Jonathan M DavisGiven the fact that this subject is extremely devisive, I suspect that the best that we can hope for at this point is for lax property enforcementproperty shouldn't be about enforcement. This is the fundamental flaw in the -property switch. While I think you and I are talking about the same goal, this is an important distinction to make: the fix isn't syntax. It is a semantic rewrite. After referencing a property is rewritten to be a call, the syntax will just work: property int foo() {} int a = foo(); // the error here is NOT "you must not use () on properties". It is "type int is not callable" This is something that's bothered me about the property debate since day one: we spend all this time talking about syntax.... but that's a side effect, not the core question.
Nov 20 2012
On Tuesday, 20 November 2012 at 19:12:58 UTC, Adam D. Ruppe wrote:On Tuesday, 20 November 2012 at 19:06:22 UTC, Jonathan M Davis wrote:YesGiven the fact that this subject is extremely devisive, I suspect that the best that we can hope for at this point is for lax property enforcementproperty shouldn't be about enforcement. This is the fundamental flaw in the -property switch. While I think you and I are talking about the same goal, this is an important distinction to make: the fix isn't syntax. It is a semantic rewrite. After referencing a property is rewritten to be a call, the syntax will just work: property int foo() {} int a = foo(); // the error here is NOT "you must not use () on properties". It is "type int is not callable"This is something that's bothered me about the property debate since day one: we spend all this time talking about syntax.... but that's a side effect, not the core question.+1
Nov 20 2012
On 11/20/12, Jonathan M Davis <jmdavisProg gmx.com> wrote:I suspect that the best that we can hope for at this point is for lax property enforcement - that is that it's enforced that property functions are used as properties but there is no enforcement that non- property functions be called with parens.Here's a good reason why the latter isn't the best idea: http://d.puremagic.com/issues/show_bug.cgi?id=2159 The reporter made the mistake of issuing a function call instead of taking an address of a function, which in turn invoked a different function overload with the temporary result.
Dec 01 2012
On 2012-11-19 06:52:11 +0000, Andrei Alexandrescu <SeeWebsiteForEmail erdani.org> said:On 11/19/12 1:02 AM, Rob T wrote:…or functions returning a type with an opCall. What about template functions with a parametrized return type that will sometime be ambiguous and sometime not depending on the template parameters? -- Michel Fortin michel.fortin michelf.ca http://michelf.ca/So what's up with property?It's a mistake on top of another. We need to redesign it to such that the keyword ' property' is only required in cases that otherwise would be ambiguous (functions returning functions).
Nov 19 2012
On 11/19/12 12:30 PM, Michel Fortin wrote:On 2012-11-19 06:52:11 +0000, Andrei Alexandrescu <SeeWebsiteForEmail erdani.org> said:Let's put all of these cases in a DIP so we can analyze them. Thanks, AndreiOn 11/19/12 1:02 AM, Rob T wrote:…or functions returning a type with an opCall. What about template functions with a parametrized return type that will sometime be ambiguous and sometime not depending on the template parameters?So what's up with property?It's a mistake on top of another. We need to redesign it to such that the keyword ' property' is only required in cases that otherwise would be ambiguous (functions returning functions).
Nov 19 2012
Why don't we just outright disallow expression-statements? After all, 2 + 3; should not be a valid statement, and so foo.property; should not be, either.
Nov 19 2012
On Monday, 19 November 2012 at 18:21:55 UTC, Mehrdad wrote:Why don't we just outright disallow expression-statements? After all, 2 + 3; should not be a valid statement, and so foo.property; should not be, either.Hmmm I would say if it's const/immutable and pure then it would be an error (Side effects considered after all), otherwise popFront may not work (it is a property I believe...right?). So let's assume I make some struct to call the PC Speaker (for whatever reason) then the following would break. struct PCSpeaker { int dingsCalled; void ding() property { dingsCalled++; //some low level calls } } However if it was... void ding() property const pure We know there's no side effects (and it can't modify the struct), which then 'ding' could be an error on it's own (Although without a return value that would make the signature completely useless).
Nov 19 2012
On Monday, 19 November 2012 at 18:58:21 UTC, Era Scarecrow wrote:On Monday, 19 November 2012 at 18:21:55 UTC, Mehrdad wrote:... wrong ;) front is a property. popFront is a method.Why don't we just outright disallow expression-statements? After all, 2 + 3; should not be a valid statement, and so foo.property; should not be, either.Hmmm I would say if it's const/immutable and pure then it would be an error (Side effects considered after all), otherwise popFront may not work (it is a property I believe...right?).So let's assume I make some struct to call the PC Speaker (for whatever reason) then the following would break. struct PCSpeaker { int dingsCalled; void ding() property { dingsCalled++; //some low level calls } } However if it was... void ding() property const pure We know there's no side effects (and it can't modify the struct), which then 'ding' could be an error on it's own (Although without a return value that would make the signature completely useless).You could argue that since a property-function is meant to emulate an attribute, that calling one and doing nothing is *always* wrong, regardless of side effect. I mean, in the sense that doing the side effect would make no sense if there is no consumer for the side effect in question. Back to retro: I think that it actually could be an attribute. In that case, when you write: a.retro; then there is no consumer, and it creates a compile error. After thinking about more, I think a great definition of property would be "a function that returns a value that *must* be consumed". This would give it more power than the mere parenthesis, no-parenthesis status: Imagine "chain" property-attributed. In that case: chain(a, b); This would fail to compile, because there is no consumer for chain, regardless of side effect...
Nov 19 2012
On Monday, 19 November 2012 at 20:00:27 UTC, monarch_dodra wrote:You could argue that since a property-function is meant to emulate an attribute, that calling one and doing nothing is *always* wrong, regardless of side effect.That's EXACTLY what I'm saying. foo.property; is ALWAYS wrong semantically speaking, regardless of what it _could_ or _happens_ to do if it was/is defined. So even if popFront() was a property, my point would be that it should not be a property in the first place. It's like saying you should be able to add integers and function pointers just because they're both integers underneath. Sure, the machine can do it, but we disallow it because it makes no sense. Ditto here.
Nov 19 2012
Le 18/11/2012 22:52, Andrei Alexandrescu a écrit :On 11/19/12 1:02 AM, Rob T wrote:It isn't the only ambiguous case.So what's up with property?It's a mistake on top of another. We need to redesign it to such that the keyword ' property' is only required in cases that otherwise would be ambiguous (functions returning functions). Andrei
Nov 19 2012
On 11/20/12 12:28 AM, deadalnix wrote:Le 18/11/2012 22:52, Andrei Alexandrescu a écrit :That's why it's good to enumerate them all in http://www.prowiki.org/wiki4d/wiki.cgi?LanguageDevel/DIPs/DIP21. Thanks, AndreiOn 11/19/12 1:02 AM, Rob T wrote:It isn't the only ambiguous case.So what's up with property?It's a mistake on top of another. We need to redesign it to such that the keyword ' property' is only required in cases that otherwise would be ambiguous (functions returning functions). Andrei
Nov 19 2012
Le 19/11/2012 21:55, Andrei Alexandrescu a écrit :On 11/20/12 12:28 AM, deadalnix wrote:I'm not sure how it fit in the DIP but &funName is ambiguous when funName return a reference. In general, mixes of returning callables or references, properties, auto calling functions and &syntax does a really bad mix.Le 18/11/2012 22:52, Andrei Alexandrescu a écrit :That's why it's good to enumerate them all in http://www.prowiki.org/wiki4d/wiki.cgi?LanguageDevel/DIPs/DIP21. Thanks, AndreiOn 11/19/12 1:02 AM, Rob T wrote:It isn't the only ambiguous case.So what's up with property?It's a mistake on top of another. We need to redesign it to such that the keyword ' property' is only required in cases that otherwise would be ambiguous (functions returning functions). Andrei
Nov 19 2012
On Tuesday, 20 November 2012 at 06:06:21 UTC, deadalnix wrote:I'm not sure how it fit in the DIP but &funName is ambiguous when funName return a reference.We can just define this away: &funName if it isn't a property is the address of the function. If it is a property, ALL operations work on the return value, so it is rewritten as &(funName()).
Nov 20 2012
On Tuesday, 20 November 2012 at 13:35:14 UTC, Adam D. Ruppe wrote:On Tuesday, 20 November 2012 at 06:06:21 UTC, deadalnix wrote:So this is impossible to get the address of the returned reference.I'm not sure how it fit in the DIP but &funName is ambiguous when funName return a reference.We can just define this away: &funName if it isn't a property is the address of the function.If it is a property, ALL operations work on the return value, so it is rewritten as &(funName()).I agree that this is ho it should work.
Nov 20 2012
On 11/20/2012 09:56 PM, deadalnix wrote:On Tuesday, 20 November 2012 at 13:35:14 UTC, Adam D. Ruppe wrote:&funName()On Tuesday, 20 November 2012 at 06:06:21 UTC, deadalnix wrote:So this is impossible to get the address of the returned reference.I'm not sure how it fit in the DIP but &funName is ambiguous when funName return a reference.We can just define this away: &funName if it isn't a property is the address of the function.+1.If it is a property, ALL operations work on the return value, so it is rewritten as &(funName()).I agree that this is ho it should work.
Nov 20 2012
On Tuesday, 20 November 2012 at 21:19:20 UTC, Timon Gehr wrote:On 11/20/2012 09:56 PM, deadalnix wrote:So now funName and funName are not equivalent anymore. Special cases should be removed, not added.On Tuesday, 20 November 2012 at 13:35:14 UTC, Adam D. Ruppe wrote:&funName()On Tuesday, 20 November 2012 at 06:06:21 UTC, deadalnix wrote:So this is impossible to get the address of the returned reference.I'm not sure how it fit in the DIP but &funName is ambiguous when funName return a reference.We can just define this away: &funName if it isn't a property is the address of the function.+1.If it is a property, ALL operations work on the return value, so it is rewritten as &(funName()).I agree that this is ho it should work.
Nov 20 2012
On Sunday, December 02, 2012 01:16:40 Andrej Mitrovic wrote:On 11/20/12, Jonathan M Davis <jmdavisProg gmx.com> wrote:I'd _love_ to make it illegal to call non-property functions without parens, and there are definitely folks around here who agree with me, including some on the Phobos dev team (e.g. Steven has always agreed with me when this has come up), but there are enough folks around here here who like to call functions without parens - especially with UFCS and templated functions like map or filter - that I don't think that that's going to fly at this point. Maybe if Andrei agreed it could happen, but he's hated the idea of property practically from the get-go, and when you combine that with the facts that strengthening property enforcement as originally intended would break a lot of code at this point and that Walter absolutely hates breaking people's code for pratically any reason whatsoever, I expect that Walter would be against it too. And with both of them against it, it just wouldn't happen. The workaround for the bug in question is to not overload functions that take function pointers with an overload that takes something other than a function pointer or delegate. Even that's not perfect, because a function could return a function pointer or delegate, but at this point, I just don't see Andrei and Walter agreeing to the level of property enforcement required to stop it, even if they had agreed to it in the past. UFCS seems to be the feature that puts the nail in the coffin of that idea, because people don't want to do stuff like range.filter!(a => a.func() < 2)() but would rather do range.filter!(a => a.func() < 2). - Jonathan M DavisI suspect that the best that we can hope for at this point is for lax property enforcement - that is that it's enforced that property functions are used as properties but there is no enforcement that non- property functions be called with parens.Here's a good reason why the latter isn't the best idea: http://d.puremagic.com/issues/show_bug.cgi?id=2159 The reporter made the mistake of issuing a function call instead of taking an address of a function, which in turn invoked a different function overload with the temporary result.
Dec 01 2012
On Sunday, 2 December 2012 at 01:04:03 UTC, Jonathan M Davis wrote:On Sunday, December 02, 2012 01:16:40 Andrej Mitrovic wrote:As said before a lot of such usages can be made valid with a sane semantic using opDispatch. BTW, I can't edit in the wiki? When I try to do so, it says me that deadalnix is an invalid username. If I need to register, I didn't found out how.On 11/20/12, Jonathan M Davis <jmdavisProg gmx.com> wrote:I'd _love_ to make it illegal to call non-property functions without parens, and there are definitely folks around here who agree with me, including some on the Phobos dev team (e.g. Steven has always agreed with me when this has come up), but there are enough folks around here here who like to call functions without parens - especially with UFCS and templated functions like map or filter - that I don't think that that's going to fly at this point.I suspect that the best that we can hope for at this point is for lax property enforcement - that is that it's enforced that property functions are used as properties but there is no enforcement that non- property functions be called with parens.Here's a good reason why the latter isn't the best idea: http://d.puremagic.com/issues/show_bug.cgi?id=2159 The reporter made the mistake of issuing a function call instead of taking an address of a function, which in turn invoked a different function overload with the temporary result.
Dec 01 2012
On 12/2/12, deadalnix <deadalnix gmail.com> wrote:BTW, I can't edit in the wiki? When I try to do so, it says me that deadalnix is an invalid username. If I need to register, I didn't found out how.It requires a silly CamelCase style username. You can try and edit the new wiki though: http://dwiki.kimsufi.thecybershadow.net/Main_Page
Dec 02 2012
On Sat, 01 Dec 2012 20:03:21 -0500, Jonathan M Davis <jmdavisProg gmx.com> wrote:I'd _love_ to make it illegal to call non-property functions without parens, and there are definitely folks around here who agree with me, including some on the Phobos dev team (e.g. Steven has always agreed with me when this has come up), but there are enough folks around here here who like to call functions without parens - especially with UFCS and templated functions like map or filter - that I don't think that that's going to fly at this point.Oh, shit. I missed another important property discussion. OK, I will say my peace: The issue I have with not implementing this is takes power away from the designer. There are three intentions when creating a function w/ regards to properties: 1. You intend the function to be called without parentheses to clarify it is a property. 2. You intend the function to be only called with parentheses to clarify it is a function. 3. You don't care whether it's called with parentheses or not, because the name of the function is clearly a property or a function. These distinctions are important because of the human meaning of the function. i.e. x.read() vs. x.read. The former looks to me like "read using x", the latter looks like "is x read." With property, the idea was to implement 1 and 2, and leave nothing for Things like map or filter, which clearly aren't properties by their name/usage. I had a compromise that void parameterless functions could be unambiguously called without parentheses. For example, if x.read() doesn't return a value, then the statement: x.read; Can't really be misinterpreted as "is x read" because the code isn't using the (implied) result. So that is why I always thought, make non-property functions require parentheses. But here we are almost 4? years later and still have the same situation. I give. As long as we can't call arbitrary functions as setters, I think the other failures of allowing the choice of removing parentheses are far The proposed DIP does not look bad, I say do it. -Steve
Jan 27 2013
property use: I'd like to point out, that regardless of the "with parens/without parens" stuff, marking properties with property makes sense. So that tools and frameworks can recognize them as such. This also implies that fields that are meant as properties should be declared property and the compiler should generate getter/setter so it behaves exactly like a manually created property. May I add this to DIP21? Having the compiler lower the following: property int a; to private int __a; property int a() { return __a; } property int a(int new_a) { __a=new_a; return __a; } would make properties and property declared fields really exchangeable, namely you can no longer take the reference of an property field, just like you can't take the address of a property with get/set. Best regards, Robert On Sun, 2013-01-27 at 22:24 -0500, Steven Schveighoffer wrote:On Sat, 01 Dec 2012 20:03:21 -0500, Jonathan M Davis <jmdavisProg gmx.com> wrote:I'd _love_ to make it illegal to call non-property functions without parens, and there are definitely folks around here who agree with me, including some on the Phobos dev team (e.g. Steven has always agreed with me when this has come up), but there are enough folks around here here who like to call functions without parens - especially with UFCS and templated functions like map or filter - that I don't think that that's going to fly at this point.Oh, shit. I missed another important property discussion. OK, I will say my peace: The issue I have with not implementing this is takes power away from the designer. There are three intentions when creating a function w/ regards to properties: 1. You intend the function to be called without parentheses to clarify it is a property. 2. You intend the function to be only called with parentheses to clarify it is a function. 3. You don't care whether it's called with parentheses or not, because the name of the function is clearly a property or a function. These distinctions are important because of the human meaning of the function. i.e. x.read() vs. x.read. The former looks to me like "read using x", the latter looks like "is x read." With property, the idea was to implement 1 and 2, and leave nothing for Things like map or filter, which clearly aren't properties by their name/usage. I had a compromise that void parameterless functions could be unambiguously called without parentheses. For example, if x.read() doesn't return a value, then the statement: x.read; Can't really be misinterpreted as "is x read" because the code isn't using the (implied) result. So that is why I always thought, make non-property functions require parentheses. But here we are almost 4? years later and still have the same situation. I give. As long as we can't call arbitrary functions as setters, I think the other failures of allowing the choice of removing parentheses are far The proposed DIP does not look bad, I say do it. -Steve
Jan 28 2013
On 2013-01-28 12:44, Robert wrote:property use: I'd like to point out, that regardless of the "with parens/without parens" stuff, marking properties with property makes sense. So that tools and frameworks can recognize them as such.I completely agree. I have created a struct called "attribute" only to be used as an attribute for other types that should only be attributes: struct attribute {} attribute struct foo {} Even though attribute in this case doesn't to anything it shows the intent clearly. Same thing why I like explicit interfaces and abstract classes compared with C++.This also implies that fields that are meant as properties should be declared property and the compiler should generate getter/setter so it behaves exactly like a manually created property. May I add this to DIP21? Having the compiler lower the following: property int a; to private int __a; property int a() { return __a; } property int a(int new_a) { __a=new_a; return __a; }I would love that. But the setter should return void and the compiler should to property rewrites. -- /Jacob Carlborg
Jan 28 2013
On Monday, 28 January 2013 at 12:31:35 UTC, Jacob Carlborg wrote:On 2013-01-28 12:44, Robert wrote:Returning void instead of int in the example break assignment chaining a = b = c. Besides, how such implicitly defined functions may call user defined code (check input validity, call events, etc.)?property use: I'd like to point out, that regardless of the "with parens/without parens" stuff, marking properties with property makes sense. So that tools and frameworks can recognize them as such.I completely agree. I have created a struct called "attribute" only to be used as an attribute for other types that should only be attributes: struct attribute {} attribute struct foo {} Even though attribute in this case doesn't to anything it shows the intent clearly. Same thing why I like explicit interfaces and abstract classes compared with C++.This also implies that fields that are meant as properties should be declared property and the compiler should generate getter/setter so it behaves exactly like a manually created property. May I add this to DIP21? Having the compiler lower the following: property int a; to private int __a; property int a() { return __a; } property int a(int new_a) { __a=new_a; return __a; }I would love that. But the setter should return void and the compiler should to property rewrites.
Jan 28 2013
On Monday, 28 January 2013 at 14:00:16 UTC, Maxim Fomin wrote:Returning void instead of int in the example break assignment chaining a = b = c. Besides, how such implicitly defined functions may call user defined code (check input validity, call events, etc.)?It should not if evaluating the value of (b = c) will call getter for b.
Jan 28 2013
On Monday, 28 January 2013 at 14:09:20 UTC, Dicebot wrote:On Monday, 28 January 2013 at 14:00:16 UTC, Maxim Fomin wrote:Why getter and not setter? Expression a = b = c = d should call getter for d and setter for rest of them. And if c setter returns void the chain breaks. struct S { int _priv; property void /*int*/foo(int i) //uncommment to fix { _priv = i; //return i; } property int foo() { return _priv; } } void main() { int a, b, c; a = b = c; S s1, s2, s3; s1.foo = s2.foo = s3.foo = 1; }Returning void instead of int in the example break assignment chaining a = b = c. Besides, how such implicitly defined functions may call user defined code (check input validity, call events, etc.)?It should not if evaluating the value of (b = c) will call getter for b.
Jan 28 2013
On Monday, 28 January 2013 at 14:28:30 UTC, Maxim Fomin wrote:On Monday, 28 January 2013 at 14:09:20 UTC, Dicebot wrote:"a = b" calls setter "(a = b)" calls setter first, getter second "x = b = c" is same as "x = (b = c)" thus calls setter, then getter and then setter again I don't know how it is done know, but that is quite logical C-like approach based on the fact that result of expression (a = b) is equal to a.On Monday, 28 January 2013 at 14:00:16 UTC, Maxim Fomin wrote:Why getter and not setter? Expression a = b = c = d should call getter for d and setter for rest of them. And if c setter returns void the chain breaks.Returning void instead of int in the example break assignment chaining a = b = c. Besides, how such implicitly defined functions may call user defined code (check input validity, call events, etc.)?It should not if evaluating the value of (b = c) will call getter for b.
Jan 28 2013
On Monday, 28 January 2013 at 14:38:19 UTC, Dicebot wrote:On Monday, 28 January 2013 at 14:28:30 UTC, Maxim Fomin wrote:It is not that obvious, as the result of a = b is also equal to b.On Monday, 28 January 2013 at 14:09:20 UTC, Dicebot wrote:"a = b" calls setter "(a = b)" calls setter first, getter second "x = b = c" is same as "x = (b = c)" thus calls setter, then getter and then setter again I don't know how it is done know, but that is quite logical C-like approach based on the fact that result of expression (a = b) is equal to a.On Monday, 28 January 2013 at 14:00:16 UTC, Maxim Fomin wrote:Why getter and not setter? Expression a = b = c = d should call getter for d and setter for rest of them. And if c setter returns void the chain breaks.Returning void instead of int in the example break assignment chaining a = b = c. Besides, how such implicitly defined functions may call user defined code (check input validity, call events, etc.)?It should not if evaluating the value of (b = c) will call getter for b.
Jan 28 2013
On Monday, 28 January 2013 at 14:44:15 UTC, deadalnix wrote:It is not that obvious, as the result of a = b is also equal to b.AFAIR it was defined strictly in C standard to be one two. Do not remember which one and do not have my trustful standard pdf nearby.
Jan 28 2013
On Monday, 28 January 2013 at 14:38:19 UTC, Dicebot wrote:On Monday, 28 January 2013 at 14:28:30 UTC, Maxim Fomin wrote:Agree.On Monday, 28 January 2013 at 14:09:20 UTC, Dicebot wrote:"a = b" calls setterOn Monday, 28 January 2013 at 14:00:16 UTC, Maxim Fomin wrote:Why getter and not setter? Expression a = b = c = d should call getter for d and setter for rest of them. And if c setter returns void the chain breaks.Returning void instead of int in the example break assignment chaining a = b = c. Besides, how such implicitly defined functions may call user defined code (check input validity, call events, etc.)?It should not if evaluating the value of (b = c) will call getter for b."(a = b)" calls setter first, getter secondHow it can call setter for a if b is not evaluated? This expression is rewritten to setter function call with argument that getter provides."x = b = c" is same as "x = (b = c)" thus calls setter, then getter and then setter againIt should be rewritten to a.setter(b.setter(c.getter()))I don't know how it is done know, but that is quite logical C-like approach based on the fact that result of expression (a = b) is equal to a.Yes, that is why if setter for "a" defaults to void and not to typeof(b) assignment chaining is broken.
Jan 28 2013
On Monday, 28 January 2013 at 15:05:21 UTC, Maxim Fomin wrote:On Monday, 28 January 2013 at 14:38:19 UTC, Dicebot wrote:Correction: assuming b is a variable, not property.On Monday, 28 January 2013 at 14:28:30 UTC, Maxim Fomin wrote:Agree.On Monday, 28 January 2013 at 14:09:20 UTC, Dicebot wrote:"a = b" calls setterOn Monday, 28 January 2013 at 14:00:16 UTC, Maxim Fomin wrote:Why getter and not setter? Expression a = b = c = d should call getter for d and setter for rest of them. And if c setter returns void the chain breaks.Returning void instead of int in the example break assignment chaining a = b = c. Besides, how such implicitly defined functions may call user defined code (check input validity, call events, etc.)?It should not if evaluating the value of (b = c) will call getter for b.
Jan 28 2013
On Monday, 28 January 2013 at 15:05:21 UTC, Maxim Fomin wrote:It should be rewritten to a.setter(b.setter(c.getter()))That is exactly the problem. "a = b = c" should be rewritten as: b.set(c.get()); a.set(b.get()); // or a.set(c.get()); do not remember C rules
Jan 28 2013
On Monday, 28 January 2013 at 15:31:48 UTC, Dicebot wrote:On Monday, 28 January 2013 at 15:05:21 UTC, Maxim Fomin wrote:From ISO C Assignment operators chapter: "An assignment operator stores a value in the object designated by the left operand. An assignment expression has the value of the left operand after the assignment,111) but is not an lvalue. The type of an assignment expression is the type the left operand would have after lvalue conversion. The side effect of updating the stored value of the left operand is sequenced after the value computations of the left and right operands. The evaluations of the operands are unsequenced.". So, in right-associative expression a = b = c, at first subexpression b = c is evaluated to b.set(c.get). Than value of this expression (note, that evaluated expression is not b, it is b = c) is assigned to a. How it can be done if b.set() returns void? Than expression a = (b = c) is evaluated to a.set( b = c) which is (a.setter(b.setter(c.getter)) c, b = c which is not a = b = c in the presence of properties.It should be rewritten to a.setter(b.setter(c.getter()))That is exactly the problem. "a = b = c" should be rewritten as: b.set(c.get()); a.set(b.get()); // or a.set(c.get()); do not remember C rules
Jan 28 2013
On Monday, 28 January 2013 at 16:50:37 UTC, Maxim Fomin wrote:Than value of this expression (note, that evaluated expression is not b, it is b = c) is assigned to a.Quoting you (that was exactly part of standard I was referring too): "assignment expression has the value of the left operand" Left operand for (b = c) is b. Thus (b = c) has value of b. Value of b is b.getter(). Thus compiler is re-writing it wrong if we copy C rules.b.setter cannot be called prior to b.getter as in your example expression a = c, b = c which is not a = b = c in the presence of properties.What sequence rules are you speaking about?
Jan 28 2013
On Monday, 28 January 2013 at 16:55:40 UTC, Dicebot wrote:On Monday, 28 January 2013 at 16:50:37 UTC, Maxim Fomin wrote:You are mixing value of expression and expression itself. If assignment expression has value of right operand, it does not mean that in complex assignment like a = b = c , right part of second assignment disappears and it becomes a = b. It is still a = b = c , and a is assigned to value of the whole expression b = c, not just value of b. This means it is a.setter((b = c)) = > a.setter(b.setter(c.getter)). Note, that original program does exactly what is required by ISO C.Than value of this expression (note, that evaluated expression is not b, it is b = c) is assigned to a.Quoting you (that was exactly part of standard I was referring too): "assignment expression has the value of the left operand" Left operand for (b = c) is b. Thus (b = c) has value of b. Value of b is b.getter(). Thus compiler is re-writing it wrong if we copy C rules.About that side effects are sequenced after evaluation, but it is actually irrelevant, because b.getter is not called.b.setter cannot be called prior to b.getter as in your example expression a = c, b = c which is not a = b = c in the presence of properties.What sequence rules are you speaking about?
Jan 28 2013
On Monday, 28 January 2013 at 16:55:40 UTC, Dicebot wrote:On Monday, 28 January 2013 at 16:50:37 UTC, Maxim Fomin wrote:Applying your logic: Left operand for a = (b = c) is a. Thus a has value of (b = c). Value of b = c is b.setter(c.getter()).Than value of this expression (note, that evaluated expression is not b, it is b = c) is assigned to a.Quoting you (that was exactly part of standard I was referring too): "assignment expression has the value of the left operand" Left operand for (b = c) is b. Thus (b = c) has value of b. Value of b is b.getter(). Thus compiler is re-writing it wrong if we copy C rules.
Jan 28 2013
On Monday, 28 January 2013 at 17:20:13 UTC, Maxim Fomin wrote:...Those are C rules, do not forget it. Thus value of (b = c) IS equivalent to value of b when lvalues are considered. And you are perfectly allowed to forget about c and do a = b after b = c was evaluated. It is plain old data, after all, if b = c is not interchangeable with b, something is wrong. At least I see nothing in standard that proves your statement.Applying your logic: Left operand for a = (b = c) is a. Thus a has value of (b = c). Value of b = c is b.setter(c.getter()).You are applying it wrong. Thing of it as of recursion. 1) evaluate "a = b = c" 2) evaluate a.set( (b = c).get() ), result of 1 will be a.get() ( if needed ) 3) evaluate "b = c" 4) evaluate b.set( c.get() ), result of 3 will be b.get() ( if needed ) 5) combine: a.set( b.set( c.get() ), b.get() ) Note that evaluation order for comma expression is defined, so "c.get() ), b.get()" is valid and correct code.
Jan 28 2013
On Monday, 28 January 2013 at 17:41:07 UTC, Dicebot wrote:On Monday, 28 January 2013 at 17:20:13 UTC, Maxim Fomin wrote:You are still breaking expression a = b = c and mixing terms of value of expression and expression itself....Those are C rules, do not forget it. Thus value of (b = c) IS equivalent to value of b when lvalues are considered. And you are perfectly allowed to forget about c and do a = b after b = c was evaluated. It is plain old data, after all, if b = c is not interchangeable with b, something is wrong. At least I see nothing in standard that proves your statement.I applied exactly as you did.Applying your logic: Left operand for a = (b = c) is a. Thus a has value of (b = c). Value of b = c is b.setter(c.getter()).You are applying it wrong. Thing of it as of recursion.1) evaluate "a = b = c" 2) evaluate a.set( (b = c).get() ), result of 1 will be a.get() ( if needed ).get() is wrong here. Expression is a = b = c, not a = ( (b = c).get ))3) evaluate "b = c" 4) evaluate b.set( c.get() ), result of 3 will be b.get() ( if needed ) 5) combine: a.set( b.set( c.get() ), b.get() )This breaks requirement from quoted paragraph that side effects are sequenced after value computations on both operands: computing value of b (b.get) happened after updating value (b.set). In Bugzilla there were close to this case like following (do not struct S { int a; int b; int c; } ... S s1, s2; s1 = { 1, s1.a 2 } Compiler was wrongly applied side effects before evaluating s1.a (it should be zero, not 1).Note that evaluation order for comma expression is defined, so "c.get() ), b.get()" is valid and correct code.Well, discussion went repetitive - I still insists that a = b = c should be evaluated as it is currently a.set(b=c) = > program also behaves as I understand rules: using System; using System.Collections.Generic; using System.Linq; using System.Text; class S { int _i; public int i { get { Console.WriteLine("getter"); return _i; } set { Console.WriteLine("setter"); _i = value; } } } namespace ConsoleApplication1 { class Program { static void Main(string[] args) { S s1 = new S() , s2 = new S(), s3 = new S(); s1.i = s2.i = s3.i; } } } getter setter setter
Jan 28 2013
They don't. If you want such behaviour, you would write your own setter getter, with property attribute, just like you do now. Best regards, Robert On Mon, 2013-01-28 at 15:00 +0100, Maxim Fomin wrote:Besides, how such implicitly defined functions may call user defined code (check input validity, call events, etc.)?
Jan 28 2013
On Mon, 28 Jan 2013 09:00:15 -0500, Maxim Fomin <maxim maxim-fomin.ru> wrote:On Monday, 28 January 2013 at 12:31:35 UTC, Jacob Carlborg wrote:This can be done without compiler help. But we need property as a primitive to allow it.On 2013-01-28 12:44, Robert wrote:Having the compiler lower the following: property int a; to private int __a; property int a() { return __a; } property int a(int new_a) { __a=new_a; return __a; }I think Jacob's point is that a = b = c would lower to: b = c; a = b; But I think it would be wasteful in the given case. __a is already in the register, I think actually the return __a is a noop. In other cases, where the property value may be a large struct or whatnot, not returning the new value from a setter would make sense. It would be nice if the compiler made the right choice depending on whether you returned a value from the property or not. -SteveI would love that. But the setter should return void and the compiler should to property rewrites.Returning void instead of int in the example break assignment chaining a = b = c. Besides, how such implicitly defined functions may call user defined code (check input validity, call events, etc.)?
Jan 28 2013
On 2013-01-28 17:21, Steven Schveighoffer wrote:I think Jacob's point is that a = b = c would lower to: b = c; a = b;This is how the semantics should be. This also shows a clear complete example: http://forum.dlang.org/thread/uxhgbxdsselokcdkvltx forum.dlang.org?page=14#post-ke6l44:242mfh:241:40digitalmars.comBut I think it would be wasteful in the given case. __a is already in the register, I think actually the return __a is a noop. In other cases, where the property value may be a large struct or whatnot, not returning the new value from a setter would make sense. It would be nice if the compiler made the right choice depending on whether you returned a value from the property or not.Then it's up to the compiler to implement them, I don't need to know the details in the optimizations it can do. -- /Jacob Carlborg
Jan 28 2013
On Mon, 28 Jan 2013 15:00:41 -0500, Jacob Carlborg <doob me.com> wrote:On 2013-01-28 17:21, Steven Schveighoffer wrote:Like I said, the synthesizing of properties can be done via a library. The compiler simply needs to call the getter when the setter returns void, or return the setter's return value when it returns a value. -SteveBut I think it would be wasteful in the given case. __a is already in the register, I think actually the return __a is a noop. In other cases, where the property value may be a large struct or whatnot, not returning the new value from a setter would make sense. It would be nice if the compiler made the right choice depending on whether you returned a value from the property or not.Then it's up to the compiler to implement them, I don't need to know the details in the optimizations it can do.
Jan 29 2013
On Mon, 28 Jan 2013 15:00:41 -0500, Jacob Carlborg <doob me.com> wrote:On 2013-01-28 17:21, Steven Schveighoffer wrote:Like I said, the synthesizing of properties can be done via a library. The compiler simply needs to call the getter when the setter returns void, or return the setter's return value when it returns a value. -SteveBut I think it would be wasteful in the given case. __a is already in the register, I think actually the return __a is a noop. In other cases, where the property value may be a large struct or whatnot, not returning the new value from a setter would make sense. It would be nice if the compiler made the right choice depending on whether you returned a value from the property or not.Then it's up to the compiler to implement them, I don't need to know the details in the optimizations it can do.
Jan 29 2013
On 2013-01-28 15:00, Maxim Fomin wrote:Returning void instead of int in the example break assignment chaining a = b = c. Besides, how such implicitly defined functions may call user defined code (check input validity, call events, etc.)?No, the compiler should do a rewrite, as follows: class Foo { int bar_; property int bar () { return bar_; } property void bar (int value) { bar_ = value; } } auto foo = new Foo; int a = foo.bar = 3; The above line should be rewritten as: foo.bar = 3; int a = foo.bar; The compiler also need to rewrite the following: struct Bar { int a; } class Foo { Bar bar_; property Bar bar () { return bar_; } property void bar (Bar value) { bar_ = value; } } auto foo = new Foo; foo.bar.a = 3; The above line should be rewritten to: auto __tmp = foo.bar; __tmp.a = 3; foo.bar = __tmp; If not, the value of "foo.bar.a" hasn't really changed since you returned a copy by value. If you instead return by reference you can bypass the setter using the getter. -- /Jacob Carlborg
Jan 28 2013
On Monday, 28 January 2013 at 19:55:48 UTC, Jacob Carlborg wrote:On 2013-01-28 15:00, Maxim Fomin wrote:No, it should be rewritten as foo.bar = 3, int a = 3 or int a = foo.bar._set(3). Your example calls getter, which breaks C and D as was said in this thread in previous posts.Returning void instead of int in the example break assignment chaining a = b = c. Besides, how such implicitly defined functions may call user defined code (check input validity, call events, etc.)?No, the compiler should do a rewrite, as follows: class Foo { int bar_; property int bar () { return bar_; } property void bar (int value) { bar_ = value; } } auto foo = new Foo; int a = foo.bar = 3; The above line should be rewritten as: foo.bar = 3; int a = foo.bar;The compiler also need to rewrite the following: struct Bar { int a; } class Foo { Bar bar_; property Bar bar () { return bar_; } property void bar (Bar value) { bar_ = value; } } auto foo = new Foo; foo.bar.a = 3; The above line should be rewritten to: auto __tmp = foo.bar; __tmp.a = 3; foo.bar = __tmp; If not, the value of "foo.bar.a" hasn't really changed since you returned a copy by value. If you instead return by reference you can bypass the setter using the getter.This is reasonable.
Jan 29 2013
On Monday, January 28, 2013 13:31:34 Jacob Carlborg wrote:Both should work. It's more efficient to chain assignments if the setter returns a value, but chaining should still work if it returns void. It would just be lowered differently in that case. - Jonathan M DavisHaving the compiler lower the following: property int a; to private int __a; property int a() { return __a; } property int a(int new_a) { __a=new_a; return __a; }I would love that. But the setter should return void and the compiler should to property rewrites.
Jan 28 2013
On Monday, 28 January 2013 at 03:24:09 UTC, Steven Schveighoffer wrote:There are three intentions when creating a function w/ regards to properties: 1. You intend the function to be called without parentheses to clarify it is a property. 2. You intend the function to be only called with parentheses to clarify it is a function. 3. You don't care whether it's called with parentheses or not, because the name of the function is clearly a property or a function.This is a good point. Possibly since I'm the author of the following proposal, but also because I hope it will garner greater consideration than it has so far, this is how you would do these with my suggested language features single-instance structs and opGet: The new syntax changes: struct __foo {} __foo foo; to: foo struct {} This makes single-instance structs as easy to write as lambda functions. Combining them with two new operator definitions opGet and... let me see... opDo should cover it... it would look like this: struct Goo { int _n; foo struct { int opGet() { return _n; } // Exactly like opCall, but may not be used with parentheses } } Goo g; g.foo(); // Error A struct may have exactly one of opGet, opCall, and opDo. foo struct { int opGet() { ... } int opDo() { ... } // Error: a struct may not have both opGet and opDo } opDo does exactly the opposite of opGet: it mandates the uses of parentheses instead of prohibits them. opCall, on the other hand, permits either one freely. foo struct { int opDo() { return 4; } } foo; // Error: foo must be called with parentheses Note how the single-instance struct does not store data of its own, but is used for its value as a namespace and its ability to overload variables. That doesn't mean you *can't* store data in it. It's just like any other struct except that is has what I was thinking of calling a Highlander type: There can be only one!
Jan 28 2013
On Sunday, December 02, 2012 12:36:53 Artur Skawina wrote:[1] If you think the required '()' in UFCS chains look ugly, you're right, but the right fix isn't to butcher the language.I agree, but those who think that seem to be outnumbered by those who don't want to have to use the parens - particularly with functions which already require a template argument. - Jonathan M Davis
Dec 02 2012
I had been trying to advance the phase to the next. Now, an experimental pull request is here. https://github.com/D-Programming-Language/dmd/pull/1311 ---- This change can distinguish almost usages between property and non-property syntax int func() { return 1; } void func(int n) { } property int prop() { return 2; } property void prop(int n) { } void main() { // Without -property switch, all lines can compile. // With -property switch: func(); // OK -> OK func(1); // OK -> OK func; // OK -> OK [*] func = 1; // OK -> NG (fixed!) prop(); // OK -> NG (fixed!) prop(1); // OK -> NG (fixed!) prop; // OK -> OK prop = 1; // OK -> OK } First exception is [*], keeping the line is necessary to allow UFCS chain without redundant parentheses (e.g. r.map!(a=>a*2).array). It is acceptable to me, at least. ---- I also implemented that calling function pointer which returned by property function. property foo(){ return (int n) => n * 2; } auto n = foo(10); // `foo` is resolved to property function call in advance assert(n == 20); But, we cannot support it immediately, because it will *always* introduce breaking of existing code. - If enable always this feature, propfunc() is implicitly translated to (propfunc())(), then much existing correct code without "-property" switch will break. - If enable this only when -property switch is specified, a code propfunc() will have _two_ meanings. When propfunc returns a function pointer, * If -property is on, propfunc() is translated to propfunc()(), then call returned function pointer and returns its result. * If -property is off, propfunc() is jsut call property function, then returns function pointer. Changing compilation behavior by compile switch is bad. Then it is the second exception. ---- The third exception is in AddressExpression (&exp). In current, both &func and &propfunc return their function pointers. Some peoples argues that the latter should return an address of the returned value of propfunc after implementing more property enforcement, but I'm difficult to accept that. The root cause is: AddressExpression is just only one built-in feature for getting an exact type of property function (Note that typeof(propfunc) returns the type of propfunc result). If compiler will always translate the code &propfunc to &(propfunc()), we will lost a way to get an exact type of propfunc, and then std.traits.FunctionTypeOf will never work for propfunc. To resolve the issue, I have proposed a small enhancement for AddressExpression. http://d.puremagic.com/issues/show_bug.cgi?id=9062 It will distinguish &propfunc and &(propfunc), the former returns a function poiinter of propfunc, and the latter returns an address of propfunc result. The real example about that is here. https://github.com/D-Programming-Language/phobos/pull/968/files#L0L1136 ---- How about that? Kenji Hara
Dec 02 2012
int func() { return 1; } void func(int n) { } property int prop() { return 2; } property void prop(int n) { } void main() { // Without -property switch, all lines can compile. // With -property switch: func(); // OK -> OK func(1); // OK -> OK func; // OK -> OK [*] func = 1; // OK -> NG (fixed!) prop(); // OK -> NG (fixed!) prop(1); // OK -> NG (fixed!) prop; // OK -> OK prop = 1; // OK -> OK }DIP21: Fixing property Nice but DIP21 does not discuss dynamic D.
Dec 03 2012
On 12/03/12 03:23, kenji hara wrote:I had been trying to advance the phase to the next. Now, an experimental pull request is here. https://github.com/D-Programming-Language/dmd/pull/1311 ---- This change can distinguish almost usages between property and non-property syntax int func() { return 1; } void func(int n) { } property int prop() { return 2; } property void prop(int n) { } void main() { // Without -property switch, all lines can compile. // With -property switch: func(); // OK -> OK func(1); // OK -> OK func; // OK -> OK [*] func = 1; // OK -> NG (fixed!) prop(); // OK -> NG (fixed!) prop(1); // OK -> NG (fixed!) prop; // OK -> OK prop = 1; // OK -> OK } First exception is [*], keeping the line is necessary to allow UFCS chain without redundant parentheses (e.g. r.map!(a=>a*2).array). It is acceptable to me, at least.Reasonable middle-term compromise; can't really disallow ()-ess calls w/o something else to migrate to, which doesn't exist yet.I also implemented that calling function pointer which returned by property function. property foo(){ return (int n) => n * 2; } auto n = foo(10); // `foo` is resolved to property function call in advance assert(n == 20); But, we cannot support it immediately, because it will *always* introduce breaking of existing code. - If enable always this feature, propfunc() is implicitly translated to (propfunc())(), then much existing correct code without "-property" switch will break. - If enable this only when -property switch is specified, a code propfunc() will have _two_ meanings. When propfunc returns a function pointer, * If -property is on, propfunc() is translated to propfunc()(), then call returned function pointer and returns its result. * If -property is off, propfunc() is jsut call property function, then returns function pointer. Changing compilation behavior by compile switch is bad.'Bad' doesn't begin to describe it. It's unacceptable, as such a compiler switch would create a different language. So it has to be the first option. Which isn't that bad as the "correct" term isn't really appropriate here. This /is/ a change that will break legacy code, but the failures should happen mostly at compile time and the fix is both trivial and backwards compatible. Delaying these kind of changes would only make things worse.The third exception is in AddressExpression (&exp). In current, both &func and &propfunc return their function pointers. Some peoples argues that the latter should return an address of the returned value of propfunc after implementing more property enforcement, but I'm difficult to accept that. The root cause is: AddressExpression is just only one built-in feature for getting an exact type of property function (Note that typeof(propfunc) returns the type of propfunc result). If compiler will always translate the code &propfunc to &(propfunc()), we will lost a way to get an exact type of propfunc, and then std.traits.FunctionTypeOf will never work for propfunc. To resolve the issue, I have proposed a small enhancement for AddressExpression. http://d.puremagic.com/issues/show_bug.cgi?id=9062 It will distinguish &propfunc and &(propfunc), the former returns a function poiinter of propfunc, and the latter returns an address of propfunc result.No, extremely bad idea; parens shouldn't make any difference. &cast(function)prop // or 'cast(delegate)', as appropriateThe real example about that is here. https://github.com/D-Programming-Language/phobos/pull/968/files#L0L1136 ---- How about that?The property situation is as bad as it is in part because the migration was handled wrongly. What should have happened is that the 'property' compiler switch should have enabled legacy code to compile and property enforcement should have been on by default, to the extent supported by the compiler. Doing it the other way meant that people are writing incorrect code even today. [1] Your changes seem to go in the right direction. Committing to such property enforcement will however be necessary, as keeping the current optional status forever won't work, because of issues like the ones you list above. artur [1] Yeah, "incorrect" means /just/ "incompatible with property enforcement". But the alternative is /no/ enforcement, and if you believe that to be the right approach then every trace of property should go.
Dec 06 2012