www.digitalmars.com         C & C++   DMDScript  

digitalmars.D - Function calls

reply bearophile <bearophileHUGS lycos.com> writes:
I have written the following closure, to generate numbers in 1-7 from numbers
in 1-5, as alternative implementation of this:
http://rosettacode.org/wiki/Seven-dice_from_Five-dice#D

auto dice7Gen(alias d5)() {
    int rem = 0;
    int max = 1;

    int gen7() {
        while (rem / 7 == max / 7) {
            while (max < 7) {
                int rand5 = d5() - 1;
                max *= 5;
                rem = 5 * rem + rand5;
            }

            int groups = max / 7;
            if (rem >=  7 * groups) {
                rem -= 7 * groups;
                max -= 7 * groups;
            }
        }

        int result = rem % 7;
        rem /= 7;
        max /= 7;
        return result + 1;
    }

    return gen7;
}

Can you spot the bug? It returns an integer instead of a closure :-)
The correct last line has to be:
    return &gen7;

But I think the real "bug" here is in the D2 design. In D2 calling callables
without () has to be disallowed:
- & to take their reference/address
- () to call them
Otherwise syntax error at compile-time.

Only properties marked with  property are allowed to be called without (). (If
you really want it, then even free functions may be allowed to be marked with
 property. This probably will not cause many bugs).

This can avoid bugs and tidy the language a little more.

Bye,
bearophile
Jan 26 2010
next sibling parent Bernard Helyer <b.helyer gmail.com> writes:
On 27/01/10 20:34, bearophile wrote:
 But I think the real "bug" here is in the D2 design. In D2 calling callables
without () has to be disallowed:
 -&  to take their reference/address
 - () to call them
 Otherwise syntax error at compile-time.

Nothing to add except a voice of support.
Jan 27 2010
prev sibling next sibling parent reply "Lars T. Kyllingstad" <public kyllingen.NOSPAMnet> writes:
bearophile wrote:
 I have written the following closure, to generate numbers in 1-7 from numbers
in 1-5, as alternative implementation of this:
 http://rosettacode.org/wiki/Seven-dice_from_Five-dice#D
 
 auto dice7Gen(alias d5)() {
     int rem = 0;
     int max = 1;
 
     int gen7() {
         while (rem / 7 == max / 7) {
             while (max < 7) {
                 int rand5 = d5() - 1;
                 max *= 5;
                 rem = 5 * rem + rand5;
             }
 
             int groups = max / 7;
             if (rem >=  7 * groups) {
                 rem -= 7 * groups;
                 max -= 7 * groups;
             }
         }
 
         int result = rem % 7;
         rem /= 7;
         max /= 7;
         return result + 1;
     }
 
     return gen7;
 }
 
 Can you spot the bug? It returns an integer instead of a closure :-)
 The correct last line has to be:
     return &gen7;
 
 But I think the real "bug" here is in the D2 design. In D2 calling callables
without () has to be disallowed:
 - & to take their reference/address
 - () to call them
 Otherwise syntax error at compile-time.
 
 Only properties marked with  property are allowed to be called without (). (If
you really want it, then even free functions may be allowed to be marked with
 property. This probably will not cause many bugs).
 
 This can avoid bugs and tidy the language a little more.
 
 Bye,
 bearophile

I thought that this issue had been settled a long time ago, and that this was the whole point of property. -Lars
Jan 27 2010
parent Michel Fortin <michel.fortin michelf.com> writes:
On 2010-01-27 05:58:51 -0500, "Lars T. Kyllingstad" 
<public kyllingen.NOSPAMnet> said:

 I thought that this issue had been settled a long time ago, and that 
 this was the whole point of  property.

It's just not fully implemented yet. The property attribute is there, but it doesn't change how you can call a function. -- Michel Fortin michel.fortin michelf.com http://michelf.com/
Jan 27 2010
prev sibling next sibling parent reply =?UTF-8?B?UGVsbGUgTcOlbnNzb24=?= <pelle.mansson gmail.com> writes:
On 01/27/2010 08:34 AM, bearophile wrote:
 I have written the following closure, to generate numbers in 1-7 from numbers
in 1-5, as alternative implementation of this:
 http://rosettacode.org/wiki/Seven-dice_from_Five-dice#D

 auto dice7Gen(alias d5)() {
      int rem = 0;
      int max = 1;

      int gen7() {
          while (rem / 7 == max / 7) {
              while (max<  7) {
                  int rand5 = d5() - 1;
                  max *= 5;
                  rem = 5 * rem + rand5;
              }

              int groups = max / 7;
              if (rem>=  7 * groups) {
                  rem -= 7 * groups;
                  max -= 7 * groups;
              }
          }

          int result = rem % 7;
          rem /= 7;
          max /= 7;
          return result + 1;
      }

      return gen7;
 }

 Can you spot the bug? It returns an integer instead of a closure :-)
 The correct last line has to be:
      return&gen7;

 But I think the real "bug" here is in the D2 design. In D2 calling callables
without () has to be disallowed:
 -&  to take their reference/address
 - () to call them
 Otherwise syntax error at compile-time.

 Only properties marked with  property are allowed to be called without (). (If
you really want it, then even free functions may be allowed to be marked with
 property. This probably will not cause many bugs).

 This can avoid bugs and tidy the language a little more.

 Bye,
 bearophile

I disagree, I find the function calls without the () to be really prettifying. But maybe that's just me. I don't think that it causes serious bugs, you would see that it's an integer the moment you try and use it. It also helps changing code from/to functions. I really like this feature, and would miss it should it go away.
Jan 27 2010
next sibling parent reply "Adam D. Ruppe" <destructionator gmail.com> writes:
On Wed, Jan 27, 2010 at 06:34:57PM +0100, Pelle Månsson wrote:
 I disagree, I find the function calls without the () to be really 
 prettifying.
 
 But maybe that's just me.
 
 I don't think that it causes serious bugs, you would see that it's an 
 integer the moment you try and use it. It also helps changing code 
 from/to functions.
 
 I really like this feature, and would miss it should it go away.

Me too. -- Adam D. Ruppe http://arsdnet.net
Jan 27 2010
parent reply downs <default_357-line yahoo.de> writes:
Adam D. Ruppe wrote:
 On Wed, Jan 27, 2010 at 06:34:57PM +0100, Pelle Månsson wrote:
 I disagree, I find the function calls without the () to be really 
 prettifying.

 But maybe that's just me.

 I don't think that it causes serious bugs, you would see that it's an 
 integer the moment you try and use it. It also helps changing code 
 from/to functions.

 I really like this feature, and would miss it should it go away.

Me too.

Me three.
Jan 27 2010
next sibling parent reply Michel Fortin <michel.fortin michelf.com> writes:
On 2010-01-27 14:01:56 -0500, downs <default_357-line yahoo.de> said:

 Adam D. Ruppe wrote:
 On Wed, Jan 27, 2010 at 06:34:57PM +0100, Pelle Månsson wrote:
 I really like this feature, and would miss it should it go away.

Me too.

Me three.

I'll miss the feature too. But I think it's the right thing to do because otherwise you can't have properties that behave like properties when returning a callable type. -- Michel Fortin michel.fortin michelf.com http://michelf.com/
Jan 27 2010
parent reply boscop <kingboscop nospam.gmail.com> writes:
On 27.01.2010 20:54, Michel Fortin wrote:
 On 2010-01-27 14:01:56 -0500, downs <default_357-line yahoo.de> said:
 
 Adam D. Ruppe wrote:
 On Wed, Jan 27, 2010 at 06:34:57PM +0100, Pelle Månsson wrote:
 I really like this feature, and would miss it should it go away.

Me too.

Me three.

I'll miss the feature too. But I think it's the right thing to do because otherwise you can't have properties that behave like properties when returning a callable type.

It may be optically pleasant sometimes to be able to omit the parens, but beside the problem with returning a callable type it's also easier to spot where computations happen instead of fast access to properties, even more in complex expressions. Of course you can hide a bottleneck in a property but I'm talking about the normal case here. And it's not hard to type two parens for better readability.
Jan 27 2010
parent =?UTF-8?B?UGVsbGUgTcOlbnNzb24=?= <pelle.mansson gmail.com> writes:
On 01/27/2010 09:53 PM, boscop wrote:
 On 27.01.2010 20:54, Michel Fortin wrote:
 On 2010-01-27 14:01:56 -0500, downs<default_357-line yahoo.de>  said:

 Adam D. Ruppe wrote:
 On Wed, Jan 27, 2010 at 06:34:57PM +0100, Pelle M�nsson wrote:
 I really like this feature, and would miss it should it go away.

Me too.

Me three.

I'll miss the feature too. But I think it's the right thing to do because otherwise you can't have properties that behave like properties when returning a callable type.

It may be optically pleasant sometimes to be able to omit the parens, but beside the problem with returning a callable type it's also easier to spot where computations happen instead of fast access to properties, even more in complex expressions. Of course you can hide a bottleneck in a property but I'm talking about the normal case here. And it's not hard to type two parens for better readability.

I think you're looking for a profiler. I also disagree about the readability part, I dislike line noise.
Jan 27 2010
prev sibling next sibling parent "Nick Sabalausky" <a a.a> writes:
"downs" <default_357-line yahoo.de> wrote in message 
news:hjq2l1$1s5j$1 digitalmars.com...
 Adam D. Ruppe wrote:
 On Wed, Jan 27, 2010 at 06:34:57PM +0100, Pelle Månsson wrote:
 I disagree, I find the function calls without the () to be really
 prettifying.

 But maybe that's just me.

 I don't think that it causes serious bugs, you would see that it's an
 integer the moment you try and use it. It also helps changing code
 from/to functions.

 I really like this feature, and would miss it should it go away.

Me too.

Me three.

Meh, I hate it hate it hate it hate it hate it. I'd dance on the feature's grave. So I guess you could say I wouldn't miss it. ;)
Jan 27 2010
prev sibling parent reply Andrei Alexandrescu <SeeWebsiteForEmail erdani.org> writes:
downs wrote:
 Adam D. Ruppe wrote:
 On Wed, Jan 27, 2010 at 06:34:57PM +0100, Pelle Månsson wrote:
 I disagree, I find the function calls without the () to be really 
 prettifying.

 But maybe that's just me.

 I don't think that it causes serious bugs, you would see that it's an 
 integer the moment you try and use it. It also helps changing code 
 from/to functions.

 I really like this feature, and would miss it should it go away.


Me three.

There was a long discussion about that, which prompted the addition of property. I was in the anti- property camp, but had understanding and sympathy for the ambiguity issues involved without property. There was a vote in which as far as I recall the pro- property camp was beaten to a tender pulp. Now property is in. That has created (as I had anticipated) the unresolved issue of choosing between property or just function for any given parameterless function. Also I need to litter my code with property. To this day I am not sure whether we made the right decision. Andrei
Jan 27 2010
next sibling parent =?UTF-8?B?UGVsbGUgTcOlbnNzb24=?= <pelle.mansson gmail.com> writes:
On 01/27/2010 09:54 PM, Andrei Alexandrescu wrote:
 downs wrote:
 Adam D. Ruppe wrote:
 On Wed, Jan 27, 2010 at 06:34:57PM +0100, Pelle M�nsson wrote:
 I disagree, I find the function calls without the () to be really
 prettifying.

 But maybe that's just me.

 I don't think that it causes serious bugs, you would see that it's
 an integer the moment you try and use it. It also helps changing
 code from/to functions.

 I really like this feature, and would miss it should it go away.


Me three.

There was a long discussion about that, which prompted the addition of property. I was in the anti- property camp, but had understanding and sympathy for the ambiguity issues involved without property. There was a vote in which as far as I recall the pro- property camp was beaten to a tender pulp. Now property is in. That has created (as I had anticipated) the unresolved issue of choosing between property or just function for any given parameterless function. Also I need to litter my code with property. To this day I am not sure whether we made the right decision. Andrei

Not just parameterless functions, but functions operating on arrays as well. And mostly anything, if I recall correctly.
Jan 27 2010
prev sibling next sibling parent reply Michel Fortin <michel.fortin michelf.com> writes:
On 2010-01-27 15:54:42 -0500, Andrei Alexandrescu 
<SeeWebsiteForEmail erdani.org> said:

 Now  property is in. That has created (as I had anticipated) the 
 unresolved issue of choosing between  property or just function for any 
 given parameterless function. Also I need to litter my code with 
  property. To this day I am not sure whether we made the right decision.

Well, perhaps it'd be better if it was 'property' instead of ' property'. I find the distinction between keywords and attributes to be pretty arbitrary, almost illogical. I'm on the side that attributes (those keywords starting with ) should be reserved to things you can ignore entirely without preventing the program from working. For instance, remove all safe and trusted attributes from a program and it still works with no change in behaviour (except for when an error occurs). 'nothrow', 'pure', 'final', 'deprecated' should be attributes; ' property' should be a regular keyword. Protection attributes could be made attributes too since if you remove them all everything still works. So I think attributes should be reserved to non-essential but useful stuff in the language, generally those things adding restrictions without changing the semantics. -- Michel Fortin michel.fortin michelf.com http://michelf.com/
Jan 27 2010
next sibling parent "Craig Black" <craigblack2 cox.net> writes:
"Michel Fortin" <michel.fortin michelf.com> wrote in message 
news:hjqdca$2neo$1 digitalmars.com...
 On 2010-01-27 15:54:42 -0500, Andrei Alexandrescu 
 <SeeWebsiteForEmail erdani.org> said:

 Now  property is in. That has created (as I had anticipated) the 
 unresolved issue of choosing between  property or just function for any 
 given parameterless function. Also I need to litter my code with 
  property. To this day I am not sure whether we made the right decision.

Well, perhaps it'd be better if it was 'property' instead of ' property'. I find the distinction between keywords and attributes to be pretty arbitrary, almost illogical. I'm on the side that attributes (those keywords starting with ) should be reserved to things you can ignore entirely without preventing the program from working. For instance, remove all safe and trusted attributes from a program and it still works with no change in behaviour (except for when an error occurs). 'nothrow', 'pure', 'final', 'deprecated' should be attributes; ' property' should be a regular keyword. Protection attributes could be made attributes too since if you remove them all everything still works. So I think attributes should be reserved to non-essential but useful stuff in the language, generally those things adding restrictions without changing the semantics.

Yes, agreed, there should be some more thought put into how keywords work so that things are consistent and make sense. It seems strange that new keywords are preceded by , but older ones are not. However, aesthetically, I prefer the to a double underscore. Perhaps __gshared could be gshared or even shared. -Craig -Craig
Jan 27 2010
prev sibling parent "Lars T. Kyllingstad" <public kyllingen.NOSPAMnet> writes:
Michel Fortin wrote:
 On 2010-01-27 15:54:42 -0500, Andrei Alexandrescu 
 <SeeWebsiteForEmail erdani.org> said:
 
 Now  property is in. That has created (as I had anticipated) the 
 unresolved issue of choosing between  property or just function for 
 any given parameterless function. Also I need to litter my code with 
  property. To this day I am not sure whether we made the right decision.

Well, perhaps it'd be better if it was 'property' instead of ' property'. I find the distinction between keywords and attributes to be pretty arbitrary, almost illogical. I'm on the side that attributes (those keywords starting with ) should be reserved to things you can ignore entirely without preventing the program from working. For instance, remove all safe and trusted attributes from a program and it still works with no change in behaviour (except for when an error occurs). 'nothrow', 'pure', 'final', 'deprecated' should be attributes; ' property' should be a regular keyword. Protection attributes could be made attributes too since if you remove them all everything still works. So I think attributes should be reserved to non-essential but useful stuff in the language, generally those things adding restrictions without changing the semantics.

This was actually discussed before, and I think the general conclusion was that there is no useful definition of attributes that includes property. I think I have an idea quite similar to yours, only slightly more specific. I'll post it in a new thread. -Lars
Jan 28 2010
prev sibling parent reply Andrei Alexandrescu <SeeWebsiteForEmail erdani.org> writes:
Steven Schveighoffer wrote:
 1. Choosing between including  property or not is rare.  Most cases are 
 obvious.  If you worked with a language that requires property notation 
 (i.e. C#) this would not be as big an issue for you.

I need to put it for all front() and empty() declarations. By the way I decided that popFront() is not a property. I don't know why.
 2. Defining  property on functions you wish to call as properties can be 
 done all at once, enclosing all properties in a  property { } block.  No 
 need to "litter" all your code with that.  Furthermore, function 
 signature 'documentation' is not as littering as you think.  Verbosity 
 at definition is not as cumbersome as verbosity at the call site.  In 
 other words, the extra litter at definition time pays huge dividends in 
 clarity at the call site, and is not a constant annoyance (you only 
 define things once).

OK. The problem is, I was already enjoying clarity at the call site. So for me the whole property thing has a much less appeal than it might. I do appreciate that property eliminates ambiguities in corner cases.
 I'm sure C developers who were used to omitting prototypes were equally 
 miffed when it became required.

That situation is different. There's only one possible prototype a function can have. With property, it's anyone's guess. Andrei
Jan 28 2010
next sibling parent "Lars T. Kyllingstad" <public kyllingen.NOSPAMnet> writes:
Andrei Alexandrescu wrote:
 Steven Schveighoffer wrote:
 1. Choosing between including  property or not is rare.  Most cases 
 are obvious.  If you worked with a language that requires property 
 notation (i.e. C#) this would not be as big an issue for you.

I need to put it for all front() and empty() declarations. By the way I decided that popFront() is not a property. I don't know why.

Because it's an action, not a property. Simple as that. :) Actually, the functions you mention are probably the best examples of why the property attribute is so cool. Using it, you can signify that empty tests for emptiness, and doesn't empty() the range or container. Rule of thumb: noun or adjective --> property verb --> not property -Lars -Lars
Jan 28 2010
prev sibling next sibling parent =?UTF-8?B?UGVsbGUgTcOlbnNzb24=?= <pelle.mansson gmail.com> writes:
On 01/28/2010 04:28 PM, Steven Schveighoffer wrote:
 On Thu, 28 Jan 2010 10:22:45 -0500, Adam D. Ruppe
 <destructionator gmail.com> wrote:

 On Thu, Jan 28, 2010 at 11:47:45AM -0300, Leandro Lucarella wrote:
 Andrei Alexandrescu, el 28 de enero a las 07:57 me escribiste:
 I need to put it for all front() and empty() declarations. By the
 way I decided that popFront() is not a property. I don't know why.

Because it denotes an action?

I don't think it is that simple - I see popFront; as an action all the same as popFront();

Whether you use parentheses or not, it's not a property. The statement of Andrei is that he doesn't know why it's not a property. The simple reason is because it's an action. Now, does popFront; look like an action? Yes. But that is not the case being disambiguated. It is collateral damage. Because the compiler doesn't understand English, it can't know whether to disallow popFront; any more than an ambiguous term like read;. If there were a way to enforce "only terms that are clearly denote actions can be called without parentheses," I'd be all for it. -Steve

fluff, not collateral damage. Also, is there any case where a function is not a property and do not denote an action but is still callable without parenthesis? Aside from bad naming, of course.
Jan 28 2010
prev sibling next sibling parent reply "Lars T. Kyllingstad" <public kyllingen.NOSPAMnet> writes:
Steven Schveighoffer wrote:
 On Thu, 28 Jan 2010 10:22:45 -0500, Adam D. Ruppe 
 <destructionator gmail.com> wrote:
 
 On Thu, Jan 28, 2010 at 11:47:45AM -0300, Leandro Lucarella wrote:
 Andrei Alexandrescu, el 28 de enero a las 07:57 me escribiste:
 I need to put it for all front() and empty() declarations. By the
 way I decided that popFront() is not a property. I don't know why.

Because it denotes an action?

I don't think it is that simple - I see popFront; as an action all the same as popFront();

Whether you use parentheses or not, it's not a property. The statement of Andrei is that he doesn't know why it's not a property. The simple reason is because it's an action. Now, does popFront; look like an action? Yes. But that is not the case being disambiguated. It is collateral damage. Because the compiler doesn't understand English, it can't know whether to disallow popFront; any more than an ambiguous term like read

...or, as in Andrei's example, 'empty'. In Java you'd write isEmpty(), or even worse, getEmpty(). In D we now have the option of declaring it a property, with little chance of people thinking it actually empties anything. -Lars
Jan 28 2010
next sibling parent reply Andrei Alexandrescu <SeeWebsiteForEmail erdani.org> writes:
Denis Koroskin wrote:
 On Thu, 28 Jan 2010 20:28:17 +0300, Lars T. Kyllingstad 
 <public kyllingen.nospamnet> wrote:
 
 Steven Schveighoffer wrote:
 On Thu, 28 Jan 2010 10:22:45 -0500, Adam D. Ruppe 
 <destructionator gmail.com> wrote:

 On Thu, Jan 28, 2010 at 11:47:45AM -0300, Leandro Lucarella wrote:
 Andrei Alexandrescu, el 28 de enero a las 07:57 me escribiste:
 I need to put it for all front() and empty() declarations. By the
 way I decided that popFront() is not a property. I don't know why.

Because it denotes an action?

I don't think it is that simple - I see popFront; as an action all the same as popFront();

statement of Andrei is that he doesn't know why it's not a property. The simple reason is because it's an action. Now, does popFront; look like an action? Yes. But that is not the case being disambiguated. It is collateral damage. Because the compiler doesn't understand English, it can't know whether to disallow popFront; any more than an ambiguous term like read

...or, as in Andrei's example, 'empty'. In Java you'd write isEmpty(), or even worse, getEmpty(). In D we now have the option of declaring it a property, with little chance of people thinking it actually empties anything. -Lars

Great explanation, very convincing!

How about this: foreach (line; stdin.byLine()) { ... } vs. foreach (line; stdin.byLine) { ... } How do I choose? Andrei
Jan 28 2010
next sibling parent reply =?UTF-8?B?UGVsbGUgTcOlbnNzb24=?= <pelle.mansson gmail.com> writes:
On 01/28/2010 09:59 PM, Andrei Alexandrescu wrote:
 Denis Koroskin wrote:
 On Thu, 28 Jan 2010 20:28:17 +0300, Lars T. Kyllingstad
 <public kyllingen.nospamnet> wrote:

 Steven Schveighoffer wrote:
 On Thu, 28 Jan 2010 10:22:45 -0500, Adam D. Ruppe
 <destructionator gmail.com> wrote:

 On Thu, Jan 28, 2010 at 11:47:45AM -0300, Leandro Lucarella wrote:
 Andrei Alexandrescu, el 28 de enero a las 07:57 me escribiste:
 I need to put it for all front() and empty() declarations. By the
 way I decided that popFront() is not a property. I don't know why.

Because it denotes an action?

I don't think it is that simple - I see popFront; as an action all the same as popFront();

statement of Andrei is that he doesn't know why it's not a property. The simple reason is because it's an action. Now, does popFront; look like an action? Yes. But that is not the case being disambiguated. It is collateral damage. Because the compiler doesn't understand English, it can't know whether to disallow popFront; any more than an ambiguous term like read

...or, as in Andrei's example, 'empty'. In Java you'd write isEmpty(), or even worse, getEmpty(). In D we now have the option of declaring it a property, with little chance of people thinking it actually empties anything. -Lars

Great explanation, very convincing!

How about this: foreach (line; stdin.byLine()) { ... } vs. foreach (line; stdin.byLine) { ... } How do I choose? Andrei

I say you don't, it works both ways as it is now. I say, let's not remove this feature :) property should be for when you need to assign to it. Maybe.
Jan 28 2010
parent reply Don <nospam nospam.com> writes:
Pelle MÃ¥nsson wrote:
 On 01/28/2010 09:59 PM, Andrei Alexandrescu wrote:
 Denis Koroskin wrote:
 On Thu, 28 Jan 2010 20:28:17 +0300, Lars T. Kyllingstad
 <public kyllingen.nospamnet> wrote:

 Steven Schveighoffer wrote:
 On Thu, 28 Jan 2010 10:22:45 -0500, Adam D. Ruppe
 <destructionator gmail.com> wrote:

 On Thu, Jan 28, 2010 at 11:47:45AM -0300, Leandro Lucarella wrote:
 Andrei Alexandrescu, el 28 de enero a las 07:57 me escribiste:
 I need to put it for all front() and empty() declarations. By the
 way I decided that popFront() is not a property. I don't know why.

Because it denotes an action?

I don't think it is that simple - I see popFront; as an action all the same as popFront();

statement of Andrei is that he doesn't know why it's not a property. The simple reason is because it's an action. Now, does popFront; look like an action? Yes. But that is not the case being disambiguated. It is collateral damage. Because the compiler doesn't understand English, it can't know whether to disallow popFront; any more than an ambiguous term like read

...or, as in Andrei's example, 'empty'. In Java you'd write isEmpty(), or even worse, getEmpty(). In D we now have the option of declaring it a property, with little chance of people thinking it actually empties anything. -Lars

Great explanation, very convincing!

How about this: foreach (line; stdin.byLine()) { ... } vs. foreach (line; stdin.byLine) { ... } How do I choose? Andrei

I say you don't, it works both ways as it is now. I say, let's not remove this feature :) property should be for when you need to assign to it. Maybe.

I think there are 3 cases: (1) I want this to _always_ be treated as if it were a field; (2) I want this to _always_ be treated as a function; (3) I don't care. (this arises most frequently in generic code: you're forced to choose between a field and a function, but you can't have both). D1 caters for case (3) very well, but does extremely poorly for (1) and (2). property is perfect for case (1). It also seems reasonable to disallow property assignment syntax for anything which isn't marked as property. Disallowing removable parentheses for no-parameter functions is the contentious part.
Jan 28 2010
parent reply Andrei Alexandrescu <SeeWebsiteForEmail erdani.org> writes:
Don wrote:
 I think there are 3 cases:
 (1) I want this to _always_ be treated as if it were a field;
 (2) I want this to _always_ be treated as a function;
 (3) I don't care. (this arises most frequently in generic code: you're 
 forced to choose between a field and a function, but you can't have both).
 
 D1 caters for case (3) very well, but does extremely poorly for (1) and 
 (2).
  property is perfect for case (1). It also seems reasonable to disallow 
 property assignment syntax for anything which isn't marked as  property.
 
 Disallowing removable parentheses for no-parameter functions is the 
 contentious part.

Good summary. I now wonder, could one overload based on property? auto a = container.empty; // check for emptiness container.empty(); // take the trash out ! Anyway, I have one more comment about the example: foreach (line; stdio.byLine) { ... } vs. foreach (line; stdio.byLine()) { ... } Steve said, byLine fetches a range off stdio. In fact it's not - it's an opApply() based loop. That already muddies the waters. But I have another, bigger concern. When I think of a property, I think I fetch it and it can't go back and modify its originator. Like if I do: auto x = y.length; I don't expect to later mess with x and change y through it. I'm sure an inventive mind could find an argument against this but if I try to be honest with myself I'd think it's tenuous to have the tail property wag the dog object. Unfortunately that's exactly what happens with stdin.byLine: even if it were a range, it would alter stdin through its usage. It's not a property in the same way stdin.eof or stdin.isOpen are. Andrei
Jan 28 2010
next sibling parent Andrei Alexandrescu <SeeWebsiteForEmail erdani.org> writes:
Andrei Alexandrescu wrote:
 Don wrote:
 I think there are 3 cases:
 (1) I want this to _always_ be treated as if it were a field;
 (2) I want this to _always_ be treated as a function;
 (3) I don't care. (this arises most frequently in generic code: you're 
 forced to choose between a field and a function, but you can't have 
 both).

 D1 caters for case (3) very well, but does extremely poorly for (1) 
 and (2).
  property is perfect for case (1). It also seems reasonable to 
 disallow property assignment syntax for anything which isn't marked as 
  property.

 Disallowing removable parentheses for no-parameter functions is the 
 contentious part.

Good summary. I now wonder, could one overload based on property? auto a = container.empty; // check for emptiness container.empty(); // take the trash out ! Anyway, I have one more comment about the example: foreach (line; stdio.byLine) { ... } vs. foreach (line; stdio.byLine()) { ... } Steve said, byLine fetches a range off stdio. In fact it's not - it's an opApply() based loop.

I was mistaken. byLine does fetch a range. http://www.dsource.org/projects/phobos/browser/trunk/phobos/std/stdio.d BTW I love byLine. Andrei
Jan 28 2010
prev sibling parent reply "Nick Sabalausky" <a a.a> writes:
"Andrei Alexandrescu" <SeeWebsiteForEmail erdani.org> wrote in message 
news:hjt1ea$306u$1 digitalmars.com...
 Good summary. I now wonder, could one overload based on  property?

 auto a = container.empty; // check for emptiness
 container.empty();        // take the trash out

 !

Why would that ever enter into anyone's mind? You already can't overload on a member's type, you already can't overload on function's return type, and you certainly can't overload on a mere decorator. There's no issue here.
 Anyway, I have one more comment about the example:

 foreach (line; stdio.byLine) { ... }
 vs.
 foreach (line; stdio.byLine()) { ... }

 Steve said, byLine fetches a range off stdio. In fact it's not - it's an 
 opApply() based loop. That already muddies the waters. But I have another, 
 bigger concern. When I think of a property, I think I fetch it and it 
 can't go back and modify its originator. Like if I do:

 auto x = y.length;

 I don't expect to later mess with x and change y through it.

 I'm sure an inventive mind could find an argument against this but if I 
 try to be honest with myself I'd think it's tenuous to have the tail 
 property wag the dog object.

If you see a problem with being able to do this: auto dog = new Dog(); auto tail = dog.tail; tail.wag(); Then you obviously haven't done much game programming. (Now obviously something like "tail.bark()" would be ridiculous, but hardly a real risk.) Additionally, even if that could be considered a problem, I don't see how having ommittable parens on no-param function calls would in any way alleviate the problem.
Jan 28 2010
parent Andrei Alexandrescu <SeeWebsiteForEmail erdani.org> writes:
Nick Sabalausky wrote:
 "Andrei Alexandrescu" <SeeWebsiteForEmail erdani.org> wrote in message 
 news:hjt1ea$306u$1 digitalmars.com...
 Good summary. I now wonder, could one overload based on  property?

 auto a = container.empty; // check for emptiness
 container.empty();        // take the trash out

 !

Why would that ever enter into anyone's mind? You already can't overload on a member's type, you already can't overload on function's return type, and you certainly can't overload on a mere decorator. There's no issue here.
 Anyway, I have one more comment about the example:

 foreach (line; stdio.byLine) { ... }
 vs.
 foreach (line; stdio.byLine()) { ... }

 Steve said, byLine fetches a range off stdio. In fact it's not - it's an 
 opApply() based loop. That already muddies the waters. But I have another, 
 bigger concern. When I think of a property, I think I fetch it and it 
 can't go back and modify its originator. Like if I do:

 auto x = y.length;

 I don't expect to later mess with x and change y through it.

 I'm sure an inventive mind could find an argument against this but if I 
 try to be honest with myself I'd think it's tenuous to have the tail 
 property wag the dog object.

If you see a problem with being able to do this: auto dog = new Dog(); auto tail = dog.tail; tail.wag();

Nonono, the expression "tail wagging the dog" means that the actual tail stands still and the dog is shaking like a tail. Andrei
Jan 28 2010
prev sibling next sibling parent reply Andrei Alexandrescu <SeeWebsiteForEmail erdani.org> writes:
Steven Schveighoffer wrote:
 On Thu, 28 Jan 2010 15:59:30 -0500, Andrei Alexandrescu 
 <SeeWebsiteForEmail erdani.org> wrote:
 foreach (line; stdin.byLine()) { ... }

 vs.

 foreach (line; stdin.byLine) { ... }

 How do I choose?

byLine is a property. It is fetching a range on stdin. -Steve

Damn. I was sure the answer will be different. Andrei
Jan 28 2010
next sibling parent reply Michiel Helvensteijn <m.helvensteijn.remove gmail.com> writes:
Andrei Alexandrescu wrote:

 foreach (line; stdin.byLine()) { ... }

 vs.

 foreach (line; stdin.byLine) { ... }

 How do I choose?

byLine is a property. It is fetching a range on stdin. -Steve

Damn. I was sure the answer will be different.

byLine() is a function. It changes the state of stdin. Calling it consecutively will in general result in different return values. If there were two guys: stdin.currentLine (property) and stdin.nextLine(), it would be a different story. A property should act very much like a field. The advantages of properties are that they can be derived (not have a one-to-one relation with a storage location) or can do some clever caching/memoizing/logging. Omitting parentheses on an action just because you can is stupid. It actually makes the language less readable and less predictable. And all that for saving two keystrokes. -- Michiel Helvensteijn
Jan 28 2010
next sibling parent reply Andrei Alexandrescu <SeeWebsiteForEmail erdani.org> writes:
Michiel Helvensteijn wrote:
 Andrei Alexandrescu wrote:
 
 foreach (line; stdin.byLine()) { ... }

 vs.

 foreach (line; stdin.byLine) { ... }

 How do I choose?

-Steve


byLine() is a function. It changes the state of stdin. Calling it consecutively will in general result in different return values. If there were two guys: stdin.currentLine (property) and stdin.nextLine(), it would be a different story. A property should act very much like a field. The advantages of properties are that they can be derived (not have a one-to-one relation with a storage location) or can do some clever caching/memoizing/logging.

I agree, but I'll also note that I got contradictory opinions from different supporters of property. So now it looks all the more like a judgment call, which is exactly what I was worried in the first place.
 Omitting parentheses on an action just because you can is stupid. It
 actually makes the language less readable and less predictable. And all
 that for saving two keystrokes.

I found my code to be more readable and just as predictable with the current rule. And it's not about two keystrokes, it's about persistent and ubiquitous syntactic noise. Gosh, property does suck. I was afraid that'd be true. Andrei
Jan 28 2010
parent reply Lutger <lutger.blijdestijn gmail.com> writes:
On 01/28/2010 11:05 PM, Andrei Alexandrescu wrote:
 Michiel Helvensteijn wrote:
 Andrei Alexandrescu wrote:

 foreach (line; stdin.byLine()) { ... }

 vs.

 foreach (line; stdin.byLine) { ... }

 How do I choose?

-Steve


byLine() is a function. It changes the state of stdin. Calling it consecutively will in general result in different return values. If there were two guys: stdin.currentLine (property) and stdin.nextLine(), it would be a different story. A property should act very much like a field. The advantages of properties are that they can be derived (not have a one-to-one relation with a storage location) or can do some clever caching/memoizing/logging.

I agree, but I'll also note that I got contradictory opinions from different supporters of property. So now it looks all the more like a judgment call, which is exactly what I was worried in the first place.
 Omitting parentheses on an action just because you can is stupid. It
 actually makes the language less readable and less predictable. And all
 that for saving two keystrokes.

I found my code to be more readable and just as predictable with the current rule. And it's not about two keystrokes, it's about persistent and ubiquitous syntactic noise. Gosh, property does suck. I was afraid that'd be true. Andrei

Lot's of things are judgement calls, I don't see the problem. property is a tool like everything else, there are many more cases where it's pretty clear cut. The ambivalence here is inherent in the code, and only brought out by the property question, not caused by it. Notice there was also no consensus of what byLine actually did under the hood. Also, don't forget these: - property allows you to forbid the caller using parenthesis, there is no other way in D to achieve this for accessor functions - so far ignored in this thread: any kind of code inspection (reflection, compile time, by IDE) can use the ' property property' for various purposes.
Jan 28 2010
parent reply Andrei Alexandrescu <SeeWebsiteForEmail erdani.org> writes:
Lutger wrote:
 On 01/28/2010 11:05 PM, Andrei Alexandrescu wrote:
 Michiel Helvensteijn wrote:
 Andrei Alexandrescu wrote:

 foreach (line; stdin.byLine()) { ... }

 vs.

 foreach (line; stdin.byLine) { ... }

 How do I choose?

-Steve


byLine() is a function. It changes the state of stdin. Calling it consecutively will in general result in different return values. If there were two guys: stdin.currentLine (property) and stdin.nextLine(), it would be a different story. A property should act very much like a field. The advantages of properties are that they can be derived (not have a one-to-one relation with a storage location) or can do some clever caching/memoizing/logging.

I agree, but I'll also note that I got contradictory opinions from different supporters of property. So now it looks all the more like a judgment call, which is exactly what I was worried in the first place.
 Omitting parentheses on an action just because you can is stupid. It
 actually makes the language less readable and less predictable. And all
 that for saving two keystrokes.

I found my code to be more readable and just as predictable with the current rule. And it's not about two keystrokes, it's about persistent and ubiquitous syntactic noise. Gosh, property does suck. I was afraid that'd be true. Andrei

Lot's of things are judgement calls, I don't see the problem. property is a tool like everything else, there are many more cases where it's pretty clear cut. The ambivalence here is inherent in the code, and only brought out by the property question, not caused by it. Notice there was also no consensus of what byLine actually did under the hood. Also, don't forget these: - property allows you to forbid the caller using parenthesis, there is no other way in D to achieve this for accessor functions - so far ignored in this thread: any kind of code inspection (reflection, compile time, by IDE) can use the ' property property' for various purposes.

Wise words. So how do I go about byLine? Andrei
Jan 28 2010
parent Lutger <lutger.blijdestijn gmail.com> writes:
On 01/28/2010 11:28 PM, Andrei Alexandrescu wrote:
 Lutger wrote:
 On 01/28/2010 11:05 PM, Andrei Alexandrescu wrote:
 Michiel Helvensteijn wrote:
 Andrei Alexandrescu wrote:

 foreach (line; stdin.byLine()) { ... }

 vs.

 foreach (line; stdin.byLine) { ... }

 How do I choose?

-Steve


byLine() is a function. It changes the state of stdin. Calling it consecutively will in general result in different return values. If there were two guys: stdin.currentLine (property) and stdin.nextLine(), it would be a different story. A property should act very much like a field. The advantages of properties are that they can be derived (not have a one-to-one relation with a storage location) or can do some clever caching/memoizing/logging.

I agree, but I'll also note that I got contradictory opinions from different supporters of property. So now it looks all the more like a judgment call, which is exactly what I was worried in the first place.
 Omitting parentheses on an action just because you can is stupid. It
 actually makes the language less readable and less predictable. And all
 that for saving two keystrokes.

I found my code to be more readable and just as predictable with the current rule. And it's not about two keystrokes, it's about persistent and ubiquitous syntactic noise. Gosh, property does suck. I was afraid that'd be true. Andrei

Lot's of things are judgement calls, I don't see the problem. property is a tool like everything else, there are many more cases where it's pretty clear cut. The ambivalence here is inherent in the code, and only brought out by the property question, not caused by it. Notice there was also no consensus of what byLine actually did under the hood. Also, don't forget these: - property allows you to forbid the caller using parenthesis, there is no other way in D to achieve this for accessor functions - so far ignored in this thread: any kind of code inspection (reflection, compile time, by IDE) can use the ' property property' for various purposes.

Wise words. So how do I go about byLine? Andrei

You make a good judgement call :) this is possible right: auto iter = stdin.byLine; foreach(line; iter) ... could you imagine byLine as an abbreviation of byLineRange or getByLineRange a la Java? or even conceive of: stdin.byLine = aDifferentFlavorOfByLine? So yes, I'm inclined to think of it as a property.
Jan 28 2010
prev sibling next sibling parent reply Michiel Helvensteijn <m.helvensteijn.remove gmail.com> writes:
Bill Baxter wrote:

 byLine() is a function. It changes the state of stdin. Calling it
 consecutively will in general result in different return values. If there
 were two guys: stdin.currentLine (property) and stdin.nextLine(), it
 would be a different story.

That's not how it works, I think. Just calling byLine() by itself only returns a range struct. Consuming things from that range is what changes the state of stdin.

Ah, my bad. I was guessing. Still, returning a handle from a property that can change the state of the originating object is.. iffy. -- Michiel Helvensteijn
Jan 28 2010
next sibling parent reply Andrei Alexandrescu <SeeWebsiteForEmail erdani.org> writes:
Michiel Helvensteijn wrote:
 Bill Baxter wrote:
 
 byLine() is a function. It changes the state of stdin. Calling it
 consecutively will in general result in different return values. If there
 were two guys: stdin.currentLine (property) and stdin.nextLine(), it
 would be a different story.

Just calling byLine() by itself only returns a range struct. Consuming things from that range is what changes the state of stdin.

Ah, my bad. I was guessing. Still, returning a handle from a property that can change the state of the originating object is.. iffy.

I agree. So where's the consensus? Things seemed so clear when people were beaten with property over their head. Andrei
Jan 28 2010
next sibling parent reply Michiel Helvensteijn <m.helvensteijn.remove gmail.com> writes:
Andrei Alexandrescu wrote:

 I agree. So where's the consensus? Things seemed so clear when people
 were beaten with  property over their head.

If I read the TLP correctly, property seems not to be working correctly. property (or any other notation marking property getters/setters) should be enforced. Functions that have it must only be invoked using property syntax. Functions that don't have it must be called with parentheses. That's the whole point. To give the designer of the class control over how it is used. The problem is people blurring the line between what's supposed to be a function and what's supposed to be a property, by abusing property syntax to invoke actions without parentheses. In reality, I believe there's not only a clear line between the two intentions, there's a demilitarized zone. You just need to enforce it. You can't have your cake and eat it too. -- Michiel Helvensteijn
Jan 28 2010
parent reply =?UTF-8?B?UGVsbGUgTcOlbnNzb24=?= <pelle.mansson gmail.com> writes:
On 01/28/2010 11:23 PM, Michiel Helvensteijn wrote:
 Andrei Alexandrescu wrote:

 I agree. So where's the consensus? Things seemed so clear when people
 were beaten with  property over their head.

If I read the TLP correctly, property seems not to be working correctly. property (or any other notation marking property getters/setters) should be enforced. Functions that have it must only be invoked using property syntax. Functions that don't have it must be called with parentheses. That's the whole point. To give the designer of the class control over how it is used. The problem is people blurring the line between what's supposed to be a function and what's supposed to be a property, by abusing property syntax to invoke actions without parentheses. In reality, I believe there's not only a clear line between the two intentions, there's a demilitarized zone. You just need to enforce it. You can't have your cake and eat it too.

I don't understand what any of this would improve. Is the byLine example less readable without the ()? Is it more bug prone? The only thing achieved as I can see is that every class designer makes up his own rules about which functions are property and which are not. If this is somehow enforced, it will become a guessing game about how to call no-argument functions. For what?
Jan 28 2010
next sibling parent reply Andrei Alexandrescu <SeeWebsiteForEmail erdani.org> writes:
Pelle MÃ¥nsson wrote:
 On 01/28/2010 11:23 PM, Michiel Helvensteijn wrote:
 Andrei Alexandrescu wrote:

 I agree. So where's the consensus? Things seemed so clear when people
 were beaten with  property over their head.

If I read the TLP correctly, property seems not to be working correctly. property (or any other notation marking property getters/setters) should be enforced. Functions that have it must only be invoked using property syntax. Functions that don't have it must be called with parentheses. That's the whole point. To give the designer of the class control over how it is used. The problem is people blurring the line between what's supposed to be a function and what's supposed to be a property, by abusing property syntax to invoke actions without parentheses. In reality, I believe there's not only a clear line between the two intentions, there's a demilitarized zone. You just need to enforce it. You can't have your cake and eat it too.

I don't understand what any of this would improve. Is the byLine example less readable without the ()? Is it more bug prone? The only thing achieved as I can see is that every class designer makes up his own rules about which functions are property and which are not. If this is somehow enforced, it will become a guessing game about how to call no-argument functions. For what?

++ Andrei
Jan 28 2010
parent =?UTF-8?B?UGVsbGUgTcOlbnNzb24=?= <pelle.mansson gmail.com> writes:
On 01/29/2010 12:01 AM, Bill Baxter wrote:
 On Thu, Jan 28, 2010 at 2:49 PM, Andrei Alexandrescu
 <SeeWebsiteForEmail erdani.org>  wrote:
 Pelle M�nsson wrote:
 On 01/28/2010 11:23 PM, Michiel Helvensteijn wrote:
 Andrei Alexandrescu wrote:

 I agree. So where's the consensus? Things seemed so clear when people
 were beaten with  property over their head.

If I read the TLP correctly, property seems not to be working correctly. property (or any other notation marking property getters/setters) should be enforced. Functions that have it must only be invoked using property syntax. Functions that don't have it must be called with parentheses. That's the whole point. To give the designer of the class control over how it is used. The problem is people blurring the line between what's supposed to be a function and what's supposed to be a property, by abusing property syntax to invoke actions without parentheses. In reality, I believe there's not only a clear line between the two intentions, there's a demilitarized zone. You just need to enforce it. You can't have your cake and eat it too.

I don't understand what any of this would improve. Is the byLine example less readable without the ()? Is it more bug prone? The only thing achieved as I can see is that every class designer makes up his own rules about which functions are property and which are not. If this is somehow enforced, it will become a guessing game about how to call no-argument functions. For what?


The "what" is the things listed in DIP4 (http://www.prowiki.org/wiki4d/wiki.cgi?LanguageDevel/DIPs/DIP4) Particularly these issues: int delegate() foo() { return delegate int(){ return 5; }; } // Is this an int or a delegate? auto x = foo();

A delegate. Same as auto x = foo;
 // Is this a reference to foo, or a reference to the delegate returned by foo?
 auto y =&foo;

A reference to foo. I feel this is obvious. Maybe I am wrong.
Jan 29 2010
prev sibling parent reply "Nick Sabalausky" <a a.a> writes:
"Pelle Månsson" <pelle.mansson gmail.com> wrote in message 
news:hjt46j$5qt$1 digitalmars.com...
 I don't understand what any of this would improve. Is the byLine example 
 less readable without the ()? Is it more bug prone?

 The only thing achieved as I can see is that every class designer makes up 
 his own rules about which functions are property and which are not. If 
 this is somehow enforced, it will become a guessing game about how to call 
 no-argument functions. For what?

Class "Foo" has member "bar". Is "bar" a member variable or a member function? Can you set it? Does it require arguments? You don't know, do you? It's a guessing game. To the caller, *properties are not functions*! I don't understand why we keep having to go in circles on this. They are data. Data, data, data. Not functions. Data. "Oh, but no, they're *implemented* as functions!" Who gives a crap? That's *implementation*. They're data. Data, data, data. With the proposal, if I use a class, that class has data and functions. Not "member variables, functions called with parens, and functions called without parens." Just data and functions. That's it. Data and functions. So if this is enforced, and you have a function, how do you call it? *With parens*! Why? Because it's a fucking function and functions are fucking called with parens! For god's sake, C# has had this for years, and nobody ever wonders "Do I use parens?" in C#, because if you're going to use something, you already know damn well if it's a function or data. Because if you don't know what the hell it is, you can't f***** make sensible use of it anyway.
Jan 28 2010
parent reply Andrei Alexandrescu <SeeWebsiteForEmail erdani.org> writes:
Nick Sabalausky wrote:
 "Pelle Månsson" <pelle.mansson gmail.com> wrote in message 
 news:hjt46j$5qt$1 digitalmars.com...
 I don't understand what any of this would improve. Is the byLine example 
 less readable without the ()? Is it more bug prone?

 The only thing achieved as I can see is that every class designer makes up 
 his own rules about which functions are property and which are not. If 
 this is somehow enforced, it will become a guessing game about how to call 
 no-argument functions. For what?

Class "Foo" has member "bar". Is "bar" a member variable or a member function? Can you set it? Does it require arguments? You don't know, do you? It's a guessing game. To the caller, *properties are not functions*! I don't understand why we keep having to go in circles on this. They are data. Data, data, data. Not functions. Data. "Oh, but no, they're *implemented* as functions!" Who gives a crap? That's *implementation*. They're data. Data, data, data. With the proposal, if I use a class, that class has data and functions. Not "member variables, functions called with parens, and functions called without parens." Just data and functions. That's it. Data and functions. So if this is enforced, and you have a function, how do you call it? *With parens*! Why? Because it's a fucking function and functions are fucking called with parens! For god's sake, C# has had this for years, and nobody ever wonders "Do I use parens?" in C#, because if you're going to use something, you already know damn well if it's a function or data. Because if you don't know what the hell it is, you can't f***** make sensible use of it anyway.

Relax, we're all on the same boat. Unfortunately, your view that it's all functions and data is simplistic - it works well only when we talk about returning simple data types. I, too, wish it were that simple. Andrei
Jan 28 2010
parent reply "Nick Sabalausky" <a a.a> writes:
"Andrei Alexandrescu" <SeeWebsiteForEmail erdani.org> wrote in message 
news:hjtbjh$pbg$1 digitalmars.com...
 Nick Sabalausky wrote:
 "Pelle Månsson" <pelle.mansson gmail.com> wrote in message 
 news:hjt46j$5qt$1 digitalmars.com...
 I don't understand what any of this would improve. Is the byLine example 
 less readable without the ()? Is it more bug prone?

 The only thing achieved as I can see is that every class designer makes 
 up his own rules about which functions are property and which are not. 
 If this is somehow enforced, it will become a guessing game about how to 
 call no-argument functions. For what?

Class "Foo" has member "bar". Is "bar" a member variable or a member function? Can you set it? Does it require arguments? You don't know, do you? It's a guessing game. To the caller, *properties are not functions*! I don't understand why we keep having to go in circles on this. They are data. Data, data, data. Not functions. Data. "Oh, but no, they're *implemented* as functions!" Who gives a crap? That's *implementation*. They're data. Data, data, data. With the proposal, if I use a class, that class has data and functions. Not "member variables, functions called with parens, and functions called without parens." Just data and functions. That's it. Data and functions. So if this is enforced, and you have a function, how do you call it? *With parens*! Why? Because it's a fucking function and functions are fucking called with parens! For god's sake, C# has had this for years, and nobody ever wonders "Do I use parens?" in C#, because if you're going to use something, you already know damn well if it's a function or data. Because if you don't know what the hell it is, you can't f***** make sensible use of it anyway.

Relax, we're all on the same boat. Unfortunately, your view that it's all functions and data is simplistic - it works well only when we talk about returning simple data types. I, too, wish it were that simple.

The only catches in the idea of the caller seeing it as all data and functions are issues that are equally true regardless of whether properites are done the C# way or the D1 way. So ok, strictly speaking, there's functions and then there's data that comes in two flavors. But that still does absolutely nothing to change my point that removing optional parens creates *no* guessing game that we don't already have because it's still functions (use parens) and data (regardless of what type of data, don't use parens).
Jan 28 2010
parent =?UTF-8?B?UGVsbGUgTcOlbnNzb24=?= <pelle.mansson gmail.com> writes:
On 01/29/2010 02:21 AM, Nick Sabalausky wrote:
 "Andrei Alexandrescu"<SeeWebsiteForEmail erdani.org>  wrote in message
 news:hjtbjh$pbg$1 digitalmars.com...
 Nick Sabalausky wrote:
 "Pelle M�nsson"<pelle.mansson gmail.com>  wrote in message
 news:hjt46j$5qt$1 digitalmars.com...
 I don't understand what any of this would improve. Is the byLine example
 less readable without the ()? Is it more bug prone?

 The only thing achieved as I can see is that every class designer makes
 up his own rules about which functions are property and which are not.
 If this is somehow enforced, it will become a guessing game about how to
 call no-argument functions. For what?

Class "Foo" has member "bar". Is "bar" a member variable or a member function? Can you set it? Does it require arguments? You don't know, do you? It's a guessing game. To the caller, *properties are not functions*! I don't understand why we keep having to go in circles on this. They are data. Data, data, data. Not functions. Data. "Oh, but no, they're *implemented* as functions!" Who gives a crap? That's *implementation*. They're data. Data, data, data. With the proposal, if I use a class, that class has data and functions. Not "member variables, functions called with parens, and functions called without parens." Just data and functions. That's it. Data and functions. So if this is enforced, and you have a function, how do you call it? *With parens*! Why? Because it's a fucking function and functions are fucking called with parens! For god's sake, C# has had this for years, and nobody ever wonders "Do I use parens?" in C#, because if you're going to use something, you already know damn well if it's a function or data. Because if you don't know what the hell it is, you can't f***** make sensible use of it anyway.

Relax, we're all on the same boat. Unfortunately, your view that it's all functions and data is simplistic - it works well only when we talk about returning simple data types. I, too, wish it were that simple.

The only catches in the idea of the caller seeing it as all data and functions are issues that are equally true regardless of whether properites are done the C# way or the D1 way. So ok, strictly speaking, there's functions and then there's data that comes in two flavors. But that still does absolutely nothing to change my point that removing optional parens creates *no* guessing game that we don't already have because it's still functions (use parens) and data (regardless of what type of data, don't use parens).

I don't think this definition really works. byLine returns a range, so it's data? If it's changed to an opApply based loop, is it still data? Where is the line between a simple function returning data and just data? I think property can be used to change the assignment, but not how the "get"-part of the function is called.
Jan 29 2010
prev sibling next sibling parent reply Andrei Alexandrescu <SeeWebsiteForEmail erdani.org> writes:
Bill Baxter wrote:
 On Thu, Jan 28, 2010 at 2:11 PM, Andrei Alexandrescu
 <SeeWebsiteForEmail erdani.org> wrote:
 Michiel Helvensteijn wrote:
 Bill Baxter wrote:

 byLine() is a function. It changes the state of stdin. Calling it
 consecutively will in general result in different return values. If
 there
 were two guys: stdin.currentLine (property) and stdin.nextLine(), it
 would be a different story.

Just calling byLine() by itself only returns a range struct. Consuming things from that range is what changes the state of stdin.

can change the state of the originating object is.. iffy.

beaten with property over their head.

I really don't see what the problem is there. You are arguing that car.wheels should not be a property simply because it would let me change the color of the wheels (which are part of the car's total state)?

The problem is not localized change. The result of stdin.byLine changes the _entire_ stdin. Andrei
Jan 28 2010
next sibling parent reply Andrei Alexandrescu <SeeWebsiteForEmail erdani.org> writes:
Bill Baxter wrote:
 On Thu, Jan 28, 2010 at 2:27 PM, Andrei Alexandrescu
 <SeeWebsiteForEmail erdani.org> wrote:
 Bill Baxter wrote:
 On Thu, Jan 28, 2010 at 2:11 PM, Andrei Alexandrescu
 <SeeWebsiteForEmail erdani.org> wrote:
 Michiel Helvensteijn wrote:
 Bill Baxter wrote:

 byLine() is a function. It changes the state of stdin. Calling it
 consecutively will in general result in different return values. If
 there
 were two guys: stdin.currentLine (property) and stdin.nextLine(), it
 would be a different story.

Just calling byLine() by itself only returns a range struct. Consuming things from that range is what changes the state of stdin.

that can change the state of the originating object is.. iffy.

were beaten with property over their head.

You are arguing that car.wheels should not be a property simply because it would let me change the color of the wheels (which are part of the car's total state)?

_entire_ stdin.

Ok, so you have no problem with a car.wheels returning a mutable wheels object? So it's only when the returned property can change the entire state (or a lot of the state?) that you have a problem? I don't understand how degree changes the acceptability. Doesn't seem like it should matter to me.

If you access car.wheel, it is reasonable to repaint that wheel. The problem is that you can use car.wheel to repaint the car. Andrei
Jan 28 2010
parent reply "Nick Sabalausky" <a a.a> writes:
"Andrei Alexandrescu" <SeeWebsiteForEmail erdani.org> wrote in message 
news:hjt449$5d8$1 digitalmars.com...
 Bill Baxter wrote:
 On Thu, Jan 28, 2010 at 2:27 PM, Andrei Alexandrescu
 The problem is not localized change. The result of stdin.byLine changes 
 the
 _entire_ stdin.

Ok, so you have no problem with a car.wheels returning a mutable wheels object? So it's only when the returned property can change the entire state (or a lot of the state?) that you have a problem? I don't understand how degree changes the acceptability. Doesn't seem like it should matter to me.

If you access car.wheel, it is reasonable to repaint that wheel. The problem is that you can use car.wheel to repaint the car.

Ok, so you don't think a property of something should be able to change other parts of that something? Ok, I can understand that. But if that's so, then how would it be any better to be able to change something through the return value of one of that something's member functions? (Which, of course, is what stdin.byLine apperently already does.) Ie, Given this code: auto foo = stdin.byLine; foo.doSomethingThatAdvancesStdin(); How is it possible for that code to be bad when "byLine" is defined as a " property", but suddenly be perfectly fine when omittable parens are allowed and it's defined without " property", even though either way it's still the exact same code doing exactly the same thing and having exactly the same effects?
Jan 28 2010
parent reply "Nick Sabalausky" <a a.a> writes:
"Bill Baxter" <wbaxter gmail.com> wrote in message 
news:mailman.47.1264724411.4461.digitalmars-d puremagic.com...
On Thu, Jan 28, 2010 at 3:58 PM, Nick Sabalausky <a a.a> wrote:
 "Andrei Alexandrescu" <SeeWebsiteForEmail erdani.org> wrote in message
 news:hjt449$5d8$1 digitalmars.com...
 Bill Baxter wrote:
 On Thu, Jan 28, 2010 at 2:27 PM, Andrei Alexandrescu
 The problem is not localized change. The result of stdin.byLine 
 changes
 the
 _entire_ stdin.

Ok, so you have no problem with a car.wheels returning a mutable wheels object? So it's only when the returned property can change the entire state (or a lot of the state?) that you have a problem? I don't understand how degree changes the acceptability. Doesn't seem like it should matter to me.

If you access car.wheel, it is reasonable to repaint that wheel. The problem is that you can use car.wheel to repaint the car.

Ok, so you don't think a property of something should be able to change other parts of that something? Ok, I can understand that. But if that's so, then how would it be any better to be able to change something through the return value of one of that something's member functions? (Which, of course, is what stdin.byLine apperently already does.) Ie, Given this code: auto foo = stdin.byLine; foo.doSomethingThatAdvancesStdin(); How is it possible for that code to be bad when "byLine" is defined as a " property", but suddenly be perfectly fine when omittable parens are allowed and it's defined without " property", even though either way it's still the exact same code doing exactly the same thing and having exactly the same effects?

That's not a contradiction in Andrei's position at all. Because if there is no property, then all that dropping parens means is that it's a no-function argument.

I assume you meant "no-argument function". And yes, I already pointed out that would make it a no-argument function. And that's precisely my point. If we accept that it's bad to paint a car via its " property" wheel, then how can we possibly accept this to not be just as bad?: auto car = new Car(); auto wheel = car.getWheel_ThisIsAFunctionNotAProperty(); wheel.paintTheCar();
Jan 28 2010
parent reply Andrei Alexandrescu <SeeWebsiteForEmail erdani.org> writes:
Nick Sabalausky wrote:
 "Bill Baxter" <wbaxter gmail.com> wrote in message 
 news:mailman.47.1264724411.4461.digitalmars-d puremagic.com...
 On Thu, Jan 28, 2010 at 3:58 PM, Nick Sabalausky <a a.a> wrote:
 "Andrei Alexandrescu" <SeeWebsiteForEmail erdani.org> wrote in message
 news:hjt449$5d8$1 digitalmars.com...
 Bill Baxter wrote:
 On Thu, Jan 28, 2010 at 2:27 PM, Andrei Alexandrescu
 The problem is not localized change. The result of stdin.byLine 
 changes
 the
 _entire_ stdin.

object? So it's only when the returned property can change the entire state (or a lot of the state?) that you have a problem? I don't understand how degree changes the acceptability. Doesn't seem like it should matter to me.

problem is that you can use car.wheel to repaint the car.

other parts of that something? Ok, I can understand that. But if that's so, then how would it be any better to be able to change something through the return value of one of that something's member functions? (Which, of course, is what stdin.byLine apperently already does.) Ie, Given this code: auto foo = stdin.byLine; foo.doSomethingThatAdvancesStdin(); How is it possible for that code to be bad when "byLine" is defined as a " property", but suddenly be perfectly fine when omittable parens are allowed and it's defined without " property", even though either way it's still the exact same code doing exactly the same thing and having exactly the same effects?

there is no property, then all that dropping parens means is that it's a no-function argument.

I assume you meant "no-argument function". And yes, I already pointed out that would make it a no-argument function. And that's precisely my point. If we accept that it's bad to paint a car via its " property" wheel, then how can we possibly accept this to not be just as bad?: auto car = new Car(); auto wheel = car.getWheel_ThisIsAFunctionNotAProperty(); wheel.paintTheCar();

Because a function doesn't attempt to emulate a field. Andrei
Jan 28 2010
next sibling parent reply "Nick Sabalausky" <a a.a> writes:
"Andrei Alexandrescu" <SeeWebsiteForEmail erdani.org> wrote in message 
news:hjtcbd$r0a$1 digitalmars.com...
 Nick Sabalausky wrote:
 And yes, I already pointed out that would make it a no-argument function. 
 And that's precisely my point. If we accept that it's bad to paint a car 
 via its " property" wheel, then how can we possibly accept this to not be 
 just as bad?:

 auto car = new Car();
 auto wheel = car.getWheel_ThisIsAFunctionNotAProperty();
 wheel.paintTheCar();

Because a function doesn't attempt to emulate a field.

D's approach to properties *forces* functions to emulate fields.
Jan 28 2010
parent reply Andrei Alexandrescu <SeeWebsiteForEmail erdani.org> writes:
Nick Sabalausky wrote:
 "Andrei Alexandrescu" <SeeWebsiteForEmail erdani.org> wrote in message 
 news:hjtcbd$r0a$1 digitalmars.com...
 Nick Sabalausky wrote:
 And yes, I already pointed out that would make it a no-argument function. 
 And that's precisely my point. If we accept that it's bad to paint a car 
 via its " property" wheel, then how can we possibly accept this to not be 
 just as bad?:

 auto car = new Car();
 auto wheel = car.getWheel_ThisIsAFunctionNotAProperty();
 wheel.paintTheCar();


D's approach to properties *forces* functions to emulate fields.

Unfortunately not. It forces nothing. That's my problem with the feature - it's nothing more than fostering a convention. Andrei
Jan 28 2010
next sibling parent reply "Nick Sabalausky" <a a.a> writes:
"Andrei Alexandrescu" <SeeWebsiteForEmail erdani.org> wrote in message 
news:hjtet5$111d$1 digitalmars.com...
 Nick Sabalausky wrote:
 "Andrei Alexandrescu" <SeeWebsiteForEmail erdani.org> wrote in message 
 news:hjtcbd$r0a$1 digitalmars.com...
 Nick Sabalausky wrote:
 And yes, I already pointed out that would make it a no-argument 
 function. And that's precisely my point. If we accept that it's bad to 
 paint a car via its " property" wheel, then how can we possibly accept 
 this to not be just as bad?:

 auto car = new Car();
 auto wheel = car.getWheel_ThisIsAFunctionNotAProperty();
 wheel.paintTheCar();


D's approach to properties *forces* functions to emulate fields.

Unfortunately not. It forces nothing. That's my problem with the feature - it's nothing more than fostering a convention.

A programming language *is* a set of enforced conventions. When something either can't be enforced mechanically (ex: accurate and meaningful variable names), or has real practical value in not having an enforced convention (ex: user-definable variable names, free-form whitespace, underscores in numeric literals), that's when it's left to the users to make up their own arbitrary and likely-conflicting conventions. Arbitrary freedoms just for the sake of it: great in real life, lousy in a programming language. If we don't enforce the convention of (non-property) functions being called with parens, the only things gained besides that useless "arbitrary freedom in a programming language just for the sake of it" is a couple fewer keystrokes and an extremely minuscule reduction in alleged "noise" (the usefulness of which is easily canceled out by the fact that reduction in inconsistency improves readability too).
Jan 28 2010
next sibling parent reply "Nick Sabalausky" <a a.a> writes:
"Nick Sabalausky" <a a.a> wrote in message 
news:hjtl33$1dag$1 digitalmars.com...
 "Andrei Alexandrescu" <SeeWebsiteForEmail erdani.org> wrote in message 
 news:hjtet5$111d$1 digitalmars.com...
 Nick Sabalausky wrote:
 "Andrei Alexandrescu" <SeeWebsiteForEmail erdani.org> wrote in message 
 news:hjtcbd$r0a$1 digitalmars.com...
 Nick Sabalausky wrote:
 And yes, I already pointed out that would make it a no-argument 
 function. And that's precisely my point. If we accept that it's bad to 
 paint a car via its " property" wheel, then how can we possibly accept 
 this to not be just as bad?:

 auto car = new Car();
 auto wheel = car.getWheel_ThisIsAFunctionNotAProperty();
 wheel.paintTheCar();


D's approach to properties *forces* functions to emulate fields.

Unfortunately not. It forces nothing. That's my problem with the feature - it's nothing more than fostering a convention.

A programming language *is* a set of enforced conventions. When something either can't be enforced mechanically (ex: accurate and meaningful variable names), or has real practical value in not having an enforced convention (ex: user-definable variable names, free-form whitespace, underscores in numeric literals), that's when it's left to the users to make up their own arbitrary and likely-conflicting conventions. Arbitrary freedoms just for the sake of it: great in real life, lousy in a programming language. If we don't enforce the convention of (non-property) functions being called with parens, the only things gained besides that useless "arbitrary freedom in a programming language just for the sake of it" is a couple fewer keystrokes and an extremely minuscule reduction in alleged "noise" (the usefulness of which is easily canceled out by the fact that reduction in inconsistency improves readability too).

We can keep dancing around it with different evidence, metaphors and philosophies all we want, but the bottom line is, omittable parens are a feature, and they just happen to be a feature that 1. causes problems and 2. provides extremely minimal benefits. And what do we do with features that cause problems and provide extremely minimal benefits? We yank 'em.
Jan 28 2010
parent Justin Johansson <no spam.com> writes:
Nick Sabalausky wrote:
 "Nick Sabalausky" <a a.a> wrote in message 
 news:hjtl33$1dag$1 digitalmars.com...
 "Andrei Alexandrescu" <SeeWebsiteForEmail erdani.org> wrote in message 
 news:hjtet5$111d$1 digitalmars.com...
 Nick Sabalausky wrote:
 "Andrei Alexandrescu" <SeeWebsiteForEmail erdani.org> wrote in message 
 news:hjtcbd$r0a$1 digitalmars.com...
 Nick Sabalausky wrote:
 And yes, I already pointed out that would make it a no-argument 
 function. And that's precisely my point. If we accept that it's bad to 
 paint a car via its " property" wheel, then how can we possibly accept 
 this to not be just as bad?:

 auto car = new Car();
 auto wheel = car.getWheel_ThisIsAFunctionNotAProperty();
 wheel.paintTheCar();



feature - it's nothing more than fostering a convention.

either can't be enforced mechanically (ex: accurate and meaningful variable names), or has real practical value in not having an enforced convention (ex: user-definable variable names, free-form whitespace, underscores in numeric literals), that's when it's left to the users to make up their own arbitrary and likely-conflicting conventions. Arbitrary freedoms just for the sake of it: great in real life, lousy in a programming language. If we don't enforce the convention of (non-property) functions being called with parens, the only things gained besides that useless "arbitrary freedom in a programming language just for the sake of it" is a couple fewer keystrokes and an extremely minuscule reduction in alleged "noise" (the usefulness of which is easily canceled out by the fact that reduction in inconsistency improves readability too).

We can keep dancing around it with different evidence, metaphors and philosophies all we want, but the bottom line is, omittable parens are a feature, and they just happen to be a feature that 1. causes problems and 2. provides extremely minimal benefits. And what do we do with features that cause problems and provide extremely minimal benefits? We yank 'em.

Creeping elegance is the root of all evil.*** (***Variation on a theme attributed to exactly-one famous computer scientist.) Best wishes, Justin Johansson
Jan 29 2010
prev sibling parent Jesse Phillips <jessekphillips+D gmail.com> writes:
Nick Sabalausky wrote:

 A programming language *is* a set of enforced conventions. When something 
 either can't be enforced mechanically (ex: accurate and meaningful variable 
 names), or has real practical value in not having an enforced convention 
 (ex: user-definable variable names, free-form whitespace, underscores in 
 numeric literals), that's when it's left to the users to make up their own 
 arbitrary and likely-conflicting conventions. Arbitrary freedoms just for 
 the sake of it: great in real life, lousy in a programming language.

 If we don't enforce the convention of (non-property) functions being called 
 with parens, the only things gained besides that useless "arbitrary freedom 
 in a programming language just for the sake of it" is a couple fewer 
 keystrokes and an extremely minuscule reduction in alleged "noise" (the 
 usefulness of which is easily canceled out by the fact that reduction in 
 inconsistency improves readability too).

I agree. If we do not require parentheses on functions then there is no benefit to having property. I was on the side of not having a special "property" syntax. However the DIP4 example "ambiguous-looking code" was enough to make me happy to see property. And I like the simplicity for creating them, over say C# and Java... I've just been assuming properties have not yet been finished. And maybe we will get +=,-= in the future.
Jan 28 2010
prev sibling parent Andrei Alexandrescu <SeeWebsiteForEmail erdani.org> writes:
Steven Schveighoffer wrote:
 On Thu, 28 Jan 2010 20:51:29 -0500, Andrei Alexandrescu 
 <SeeWebsiteForEmail erdani.org> wrote:
 
 Nick Sabalausky wrote:
 "Andrei Alexandrescu" <SeeWebsiteForEmail erdani.org> wrote in 
 message news:hjtcbd$r0a$1 digitalmars.com...
 Nick Sabalausky wrote:
 And yes, I already pointed out that would make it a no-argument 
 function. And that's precisely my point. If we accept that it's bad 
 to paint a car via its " property" wheel, then how can we possibly 
 accept this to not be just as bad?:

 auto car = new Car();
 auto wheel = car.getWheel_ThisIsAFunctionNotAProperty();
 wheel.paintTheCar();



Unfortunately not. It forces nothing. That's my problem with the feature - it's nothing more than fostering a convention.

It forces a convention.

It forces you to define a convention as vacuous and open to interpretation as any other. Not a quantum leap I reckon. Andrei
Jan 29 2010
prev sibling parent Rainer Deyke <rainerd eldwood.com> writes:
Andrei Alexandrescu wrote:
 Nick Sabalausky wrote:
 auto car = new Car();
 auto wheel = car.getWheel_ThisIsAFunctionNotAProperty();
 wheel.paintTheCar();

Because a function doesn't attempt to emulate a field.

Not really relevant, since the same applies to fields. auto car = new Car(); auto wheel = car.wheelFieldnotPropertyOrFunction; wheel.paintTheCar(); In this case, the wheel field contains a pointer back to the car. -- Rainer Deyke - rainerd eldwood.com
Jan 29 2010
prev sibling next sibling parent reply Michel Fortin <michel.fortin michelf.com> writes:
On 2010-01-28 17:27:58 -0500, Andrei Alexandrescu 
<SeeWebsiteForEmail erdani.org> said:

 The problem is not localized change. The result of stdin.byLine changes 
 the _entire_ stdin.

No. Calling byLine doesn't change the stream. It returns a different view of stdin, which can be used to modify the stream, or not. I think it should be a property. If it was 'getNextLine' then it should be a function. As a proof, this doesn't have any effect: stdin.byLine; If you put it in a foreach loop, then it has an effect. But it's foreach that has the effect of calling popFront on the byLine view of stdin. Getting byLine by itself doesn't do anything. Another term I'd use for a property, perhaps a better one, is an 'accessor'. A property, or an accessor, gives you access to an aspect of the object you're dealing with. In the case above, you get access to stdin line by line. Getting access to something might allow you to modify it, or it may not, depending on what it is exactly. But just getting access to it doesn't modify the object in itself. Sorry to arrive late in this conversation. Let me address some other points: I know not everyone get it right all the time. But that's not necessarily a contradiction, it just means that the concept isn't really well understood. If there was a good definition for it from an authoritative reference, it might help reduce the confusion. Currently the only authoritative element seems to be the syntax, no wonder it's confusing. Andrei, you keep complaining it's a convention. It *is* a convention, because only a convention can differentiate actions from accessors. Ideally, we wouldn't need a special syntax: English words would be enough. But as you know English words alone are often ambiguous. Either the convention is (1) how we name things -- like isEmpty vs. empty -- but I think you don't like that. Either it's (2) a syntactic convention -- empty vs. empty() -- but then the meaning becomes a little more subtle. Or (3) you can give the same meaning to both empty and empty(), but then people are left to guess what it means (action or accessor), and it creates incongruities with callables. Or (4) you can force empty() to always be with parenthesis and let people guess what it means; at least you don't have incongruities. There's no perfect solution. But of all of these options, the one used in D1 (number 3) has the most drawbacks: you can't distinguish actions from accessors, and on top of that you have problems with returning callables. -- Michel Fortin michel.fortin michelf.com http://michelf.com/
Jan 28 2010
next sibling parent reply =?UTF-8?B?UGVsbGUgTcOlbnNzb24=?= <pelle.mansson gmail.com> writes:
On 01/29/2010 05:48 AM, Michel Fortin wrote:
 No. Calling byLine doesn't change the stream. It returns a different
 view of stdin, which can be used to modify the stream, or not. I think
 it should be a property. If it was 'getNextLine' then it should be a
 function. As a proof, this doesn't have any effect:

 stdin.byLine;

It reads a line off stdin. Try it.
Jan 29 2010
parent reply Michel Fortin <michel.fortin michelf.com> writes:
On 2010-01-29 06:25:44 -0500, Pelle Månsson <pelle.mansson gmail.com> said:

 On 01/29/2010 05:48 AM, Michel Fortin wrote:
 
 No. Calling byLine doesn't change the stream. It returns a different
 view of stdin, which can be used to modify the stream, or not. I think
 it should be a property. If it was 'getNextLine' then it should be a
 function. As a proof, this doesn't have any effect:
 
 stdin.byLine;

It reads a line off stdin. Try it.

Ah, I see, you're right. Silly me for not trying. So it's not an accessor after all. The problem is that, even disregarding the property syntax, the name strongly suggests it's an accessor, but it has side effects, which it shouldn't. Either we change the name to something else, like 'consumeLines()', or we make it behave like an accessor. I'd go for the second option. The basic problem lies in the very basic definition of an input range. Due to its interface (popFront + front), an input range is forced to consume the its first element by its mere existence. I think constructing an input range shouldn't have side effects. It should be more symmetrical with an output range. It could have just one function, 'take' to get the next element, and now byLine could work correctly. -- Michel Fortin michel.fortin michelf.com http://michelf.com/
Jan 29 2010
next sibling parent reply Michel Fortin <michel.fortin michelf.com> writes:
On 2010-01-29 08:18:46 -0500, "Steven Schveighoffer" 
<schveiguy yahoo.com> said:

 Hey, it's that dead horse again, let's beat it!
 
 Andrei and I and several others discussed this ad infinitum.  You will  
 never convince Andrei that his design is wrong :)

Andrei is the one who complained that it's difficult to know whether 'byLine' is a property in the first place. I'm just explaining why it is, and what should be done. I'm starting to think Anrei likes ambiguous semantics. :-)
 The truth is, the fact that byLine modifies stdin by its mere existence 
  proves to be inconsequential.  Nobody will fetch the byLine property  
 without using it.  It's still an accessor.

That's only true if you use byLine exclusively. Here is a case where the advance fetching of byLine could go wrong: // fetch 3 lines: string[] consume(3, stdin.byLine); // now fill a buffer ubyte[] buffer; buffer = stdin.rawRead(buffer); E[] consume(E, R)(int count, R range) { E[] elements; foreach (i; 0..count) { elements ~= range.front; range.popFront(); } return elements; } The problem here is that the consume() function will in reality consume 4 lines of stdin, even though it just take 3 from byLine. When we later call rawRead, a line has been lost. -- Michel Fortin michel.fortin michelf.com http://michelf.com/
Jan 29 2010
parent reply Andrei Alexandrescu <SeeWebsiteForEmail erdani.org> writes:
Michel Fortin wrote:
 On 2010-01-29 08:18:46 -0500, "Steven Schveighoffer" 
 <schveiguy yahoo.com> said:
 
 Hey, it's that dead horse again, let's beat it!

 Andrei and I and several others discussed this ad infinitum.  You 
 will  never convince Andrei that his design is wrong :)

Andrei is the one who complained that it's difficult to know whether 'byLine' is a property in the first place. I'm just explaining why it is, and what should be done. I'm starting to think Anrei likes ambiguous semantics. :-)

I'll tell you what I'd have liked: a landslide of responses to my question revealing my mistaken ways and clarifying without a shade of a doubt that byLine should be a property. Or not. (I don't even care which.) The fact we're having a debate about this (and Steve even says it's a clear cut case and there are other more ambiguous!) is worrisome. Take this: I got different answers from _supporters_ of property! A good convention is one that you apply without wasting time to think of it every single time you use it: naming conventions, braces conventions, even most class vs. struct conventions. The well-defined ones work great because _they save you time_. This property stuff doesn't save anyone time (the provider is aggravated and the client is aggravated too). Honest, I think it's quite a misfeature. If there's a possibility to fix the ambiguities of the old system, I'd kick property into oblivion today. We need digitalmars.D.is_it_a_property_or_not. Whenever in doubt, people can ask a question there. Andrei
Jan 29 2010
next sibling parent reply Michel Fortin <michel.fortin michelf.com> writes:
On 2010-01-29 10:40:23 -0500, Andrei Alexandrescu 
<SeeWebsiteForEmail erdani.org> said:

 I'll tell you what I'd have liked: a landslide of responses to my 
 question revealing my mistaken ways and clarifying without a shade of a 
 doubt that byLine should be a  property. Or not. (I don't even care 
 which.)
 
 The fact we're having a debate about this (and Steve even says it's a 
 clear cut case and there are other more ambiguous!) is worrisome. Take 
 this: I got different answers from _supporters_ of  property!

The problem entirely reside on the ambiguous semantics of 'byLine'. The name makes us think it does something while it does something else (consuming a line). If it did what we'd expect it should be a property, but since it does not it shouldn't be. Fix 'byLine', either by changing the name or changing what it does, and whether it's a property or not will become clear.
 A good convention is one that you apply without wasting time to think 
 of it every single time you use it: naming conventions, braces 
 conventions, even most class vs. struct conventions. The well-defined 
 ones work great because _they save you time_.

Well, you should probably care a little more about your naming convention. It's confusing, and it'll probably end up waisting the time of some people who'll wonder why it consumes lines before you read them. I was absolutely sure it didn't before someone pointed it out to me. -- Michel Fortin michel.fortin michelf.com http://michelf.com/
Jan 29 2010
next sibling parent reply Andrei Alexandrescu <SeeWebsiteForEmail erdani.org> writes:
Michel Fortin wrote:
 On 2010-01-29 10:40:23 -0500, Andrei Alexandrescu 
 <SeeWebsiteForEmail erdani.org> said:
 
 I'll tell you what I'd have liked: a landslide of responses to my 
 question revealing my mistaken ways and clarifying without a shade of 
 a doubt that byLine should be a  property. Or not. (I don't even care 
 which.)

 The fact we're having a debate about this (and Steve even says it's a 
 clear cut case and there are other more ambiguous!) is worrisome. Take 
 this: I got different answers from _supporters_ of  property!

The problem entirely reside on the ambiguous semantics of 'byLine'. The name makes us think it does something while it does something else (consuming a line). If it did what we'd expect it should be a property, but since it does not it shouldn't be. Fix 'byLine', either by changing the name or changing what it does, and whether it's a property or not will become clear.
 A good convention is one that you apply without wasting time to think 
 of it every single time you use it: naming conventions, braces 
 conventions, even most class vs. struct conventions. The well-defined 
 ones work great because _they save you time_.

Well, you should probably care a little more about your naming convention. It's confusing, and it'll probably end up waisting the time of some people who'll wonder why it consumes lines before you read them. I was absolutely sure it didn't before someone pointed it out to me.

That's an implementation problem of byLine, not a issue with the byLine name. Andrei
Jan 29 2010
parent Michel Fortin <michel.fortin michelf.com> writes:
On 2010-01-29 11:19:32 -0500, Andrei Alexandrescu 
<SeeWebsiteForEmail erdani.org> said:

 That's an implementation problem of byLine, not a issue with the byLine name.

Ok, so if you agree that 'byLine' eating a line on creation is a bug, that means you don't expect 'byLine' to eat a line. That makes 'byLine' a property since calling the accessor doesn't (theoretically) modify the underlying object, it just provides access to an aspect of that object. Now it seems Steven and I both agree that it's a property. -- Michel Fortin michel.fortin michelf.com http://michelf.com/
Jan 29 2010
prev sibling parent "Lars T. Kyllingstad" <public kyllingen.NOSPAMnet> writes:
Michel Fortin wrote:
 On 2010-01-29 10:40:23 -0500, Andrei Alexandrescu 
 <SeeWebsiteForEmail erdani.org> said:
 
 I'll tell you what I'd have liked: a landslide of responses to my 
 question revealing my mistaken ways and clarifying without a shade of 
 a doubt that byLine should be a  property. Or not. (I don't even care 
 which.)

 The fact we're having a debate about this (and Steve even says it's a 
 clear cut case and there are other more ambiguous!) is worrisome. Take 
 this: I got different answers from _supporters_ of  property!

The problem entirely reside on the ambiguous semantics of 'byLine'. The name makes us think it does something while it does something else (consuming a line). If it did what we'd expect it should be a property, but since it does not it shouldn't be. Fix 'byLine', either by changing the name or changing what it does, and whether it's a property or not will become clear.

This is a very good point! Using byLine as an argument against property is just silly, as it is badly-named to begin with. The name itself doesn't really tell you what it does, you have to read the docs or see it in the context of a foreach to understand it. The omittable parentheses are not the problem here. A more descriptive name would be either of these, depending on how the function actually works: readByLine() // not a property lines // definitely a property byLinesRange // also definitely a property
 A good convention is one that you apply without wasting time to think 
 of it every single time you use it: naming conventions, braces 
 conventions, even most class vs. struct conventions. The well-defined 
 ones work great because _they save you time_.

Well, you should probably care a little more about your naming convention. It's confusing, and it'll probably end up waisting the time of some people who'll wonder why it consumes lines before you read them. I was absolutely sure it didn't before someone pointed it out to me.

Speaking of Andrei's naming convention; in the case of empty() there were a lot of protests to the name, because people couldn't tell whether it was a property or an action. The property annotation mends that. -Lars
Jan 29 2010
prev sibling next sibling parent Justin Johansson <no spam.com> writes:
Andrei Alexandrescu wrote:
 We need digitalmars.D.is_it_a_property_or_not. Whenever in doubt, people 
 can ask a question there.
 Andrei

Obviously that's a rhetorical suggestion by Andrei ... but maybe a good idea if all this silliness prevails. Justin
Jan 29 2010
prev sibling next sibling parent reply Andrei Alexandrescu <SeeWebsiteForEmail erdani.org> writes:
Steven Schveighoffer wrote:
 On Fri, 29 Jan 2010 10:40:23 -0500, Andrei Alexandrescu 
 <SeeWebsiteForEmail erdani.org> wrote:
 
 Michel Fortin wrote:
 On 2010-01-29 08:18:46 -0500, "Steven Schveighoffer" 
 <schveiguy yahoo.com> said:

 Hey, it's that dead horse again, let's beat it!

 Andrei and I and several others discussed this ad infinitum.  You 
 will  never convince Andrei that his design is wrong :)

'byLine' is a property in the first place. I'm just explaining why it is, and what should be done. I'm starting to think Anrei likes ambiguous semantics. :-)

I'll tell you what I'd have liked: a landslide of responses to my question revealing my mistaken ways and clarifying without a shade of a doubt that byLine should be a property. Or not. (I don't even care which.)

It's been mentioned before that tough decisions need to be made in many areas of programming. Deciding what is a property and what is not is no different.

Except it has no reward associated with it. Andrei
Jan 29 2010
parent reply Andrei Alexandrescu <SeeWebsiteForEmail erdani.org> writes:
Steven Schveighoffer wrote:
 On Fri, 29 Jan 2010 11:17:04 -0500, Andrei Alexandrescu 
 <SeeWebsiteForEmail erdani.org> wrote:
 
 Steven Schveighoffer wrote:
 On Fri, 29 Jan 2010 10:40:23 -0500, Andrei Alexandrescu 
 <SeeWebsiteForEmail erdani.org> wrote:

 Michel Fortin wrote:
 On 2010-01-29 08:18:46 -0500, "Steven Schveighoffer" 
 <schveiguy yahoo.com> said:

 Hey, it's that dead horse again, let's beat it!

 Andrei and I and several others discussed this ad infinitum.  You 
 will  never convince Andrei that his design is wrong :)

whether 'byLine' is a property in the first place. I'm just explaining why it is, and what should be done. I'm starting to think Anrei likes ambiguous semantics. :-)

I'll tell you what I'd have liked: a landslide of responses to my question revealing my mistaken ways and clarifying without a shade of a doubt that byLine should be a property. Or not. (I don't even care which.)

many areas of programming. Deciding what is a property and what is not is no different.

Except it has no reward associated with it.

Clarity. Disambiguation. All the rewards that come from other naming conventions. Sorry you don't see it that way.

How is f.byLine clearer and less ambiguous than f.byLine()? Or vice versa for that matter? Andrei
Jan 29 2010
parent reply Andrei Alexandrescu <SeeWebsiteForEmail erdani.org> writes:
Steven Schveighoffer wrote:
 On Fri, 29 Jan 2010 11:21:28 -0500, Andrei Alexandrescu 
 <SeeWebsiteForEmail erdani.org> wrote:
 
 How is f.byLine clearer and less ambiguous than f.byLine()? Or vice 
 versa for that matter?

Note that properties can be named things other than byLine. -Steve

What I meant to say is that in the property landscape the following two conventions become suddenly attractive: * Do not use property at all * Use property for all nullary functions And they're bound to save a lot of time to everyone involved. Andrei
Jan 29 2010
next sibling parent reply Ary Borenszweig <ary esperanto.org.ar> writes:
Andrei Alexandrescu wrote:
 Steven Schveighoffer wrote:
 On Fri, 29 Jan 2010 11:21:28 -0500, Andrei Alexandrescu 
 <SeeWebsiteForEmail erdani.org> wrote:

 How is f.byLine clearer and less ambiguous than f.byLine()? Or vice 
 versa for that matter?

Note that properties can be named things other than byLine. -Steve

What I meant to say is that in the property landscape the following two conventions become suddenly attractive: * Do not use property at all * Use property for all nullary functions And they're bound to save a lot of time to everyone involved.

The first post of this thread was about not invoking a function when you don't want it to be invoked. bearophile was doing: auto dg = int function() { ... }; return dg; but he wanted to return a reference to dg, not the result of invoking it. One way to prevent that is to never invoke functions unless they are marked with property. Or maybe functions defined like that (closures, whatever) should always require () to be invoked. If that doesn't sound reasonable, see this: auto dg1 = int function() { ... }; auto dg2 = dg1; I'd expect dg2's type to be dg1's type. Let's just think a solution to this problem first. :-)
Jan 29 2010
parent reply Andrei Alexandrescu <SeeWebsiteForEmail erdani.org> writes:
Ary Borenszweig wrote:
 Andrei Alexandrescu wrote:
 Steven Schveighoffer wrote:
 On Fri, 29 Jan 2010 11:21:28 -0500, Andrei Alexandrescu 
 <SeeWebsiteForEmail erdani.org> wrote:

 How is f.byLine clearer and less ambiguous than f.byLine()? Or vice 
 versa for that matter?

Note that properties can be named things other than byLine. -Steve

What I meant to say is that in the property landscape the following two conventions become suddenly attractive: * Do not use property at all * Use property for all nullary functions And they're bound to save a lot of time to everyone involved.

The first post of this thread was about not invoking a function when you don't want it to be invoked. bearophile was doing: auto dg = int function() { ... }; return dg; but he wanted to return a reference to dg, not the result of invoking it. One way to prevent that is to never invoke functions unless they are marked with property. Or maybe functions defined like that (closures, whatever) should always require () to be invoked. If that doesn't sound reasonable, see this: auto dg1 = int function() { ... }; auto dg2 = dg1; I'd expect dg2's type to be dg1's type. Let's just think a solution to this problem first. :-)

Correct. Just that I fear that it's a bit late for this all. It is disheartening enough that Walter got convinced by the past discussion and introduced property without much design - after a FAILED vote no less. I strongly believe a better solution is available, but everyone wanted the feature so the feature just got born. FWIW, my take for issues like the above: if a function returns a function or a delegate, it can't avail itself of automatic invocation of "()". That takes care of a corner case and keeps the mainstream case in good shape. I am not sure of a good solution for problems like writeln = 2; Andrei
Jan 29 2010
next sibling parent reply =?UTF-8?B?UGVsbGUgTcOlbnNzb24=?= <pelle.mansson gmail.com> writes:
On 01/29/2010 06:19 PM, Andrei Alexandrescu wrote:
 Ary Borenszweig wrote:
 Andrei Alexandrescu wrote:
 Steven Schveighoffer wrote:
 On Fri, 29 Jan 2010 11:21:28 -0500, Andrei Alexandrescu
 <SeeWebsiteForEmail erdani.org> wrote:

 How is f.byLine clearer and less ambiguous than f.byLine()? Or vice
 versa for that matter?

Note that properties can be named things other than byLine. -Steve

What I meant to say is that in the property landscape the following two conventions become suddenly attractive: * Do not use property at all * Use property for all nullary functions And they're bound to save a lot of time to everyone involved.

The first post of this thread was about not invoking a function when you don't want it to be invoked. bearophile was doing: auto dg = int function() { ... }; return dg; but he wanted to return a reference to dg, not the result of invoking it. One way to prevent that is to never invoke functions unless they are marked with property. Or maybe functions defined like that (closures, whatever) should always require () to be invoked. If that doesn't sound reasonable, see this: auto dg1 = int function() { ... }; auto dg2 = dg1; I'd expect dg2's type to be dg1's type. Let's just think a solution to this problem first. :-)

Correct. Just that I fear that it's a bit late for this all. It is disheartening enough that Walter got convinced by the past discussion and introduced property without much design - after a FAILED vote no less. I strongly believe a better solution is available, but everyone wanted the feature so the feature just got born. FWIW, my take for issues like the above: if a function returns a function or a delegate, it can't avail itself of automatic invocation of "()". That takes care of a corner case and keeps the mainstream case in good shape. I am not sure of a good solution for problems like writeln = 2; Andrei

How about property? When you add a property to a function it can be called as an assignment. property does not touch the calling of no-argument functions. Are there any problems with that?
Jan 29 2010
parent reply Andrei Alexandrescu <SeeWebsiteForEmail erdani.org> writes:
Pelle MÃ¥nsson wrote:
 On 01/29/2010 06:19 PM, Andrei Alexandrescu wrote:
 Ary Borenszweig wrote:
 Andrei Alexandrescu wrote:
 Steven Schveighoffer wrote:
 On Fri, 29 Jan 2010 11:21:28 -0500, Andrei Alexandrescu
 <SeeWebsiteForEmail erdani.org> wrote:

 How is f.byLine clearer and less ambiguous than f.byLine()? Or vice
 versa for that matter?

Note that properties can be named things other than byLine. -Steve

What I meant to say is that in the property landscape the following two conventions become suddenly attractive: * Do not use property at all * Use property for all nullary functions And they're bound to save a lot of time to everyone involved.

The first post of this thread was about not invoking a function when you don't want it to be invoked. bearophile was doing: auto dg = int function() { ... }; return dg; but he wanted to return a reference to dg, not the result of invoking it. One way to prevent that is to never invoke functions unless they are marked with property. Or maybe functions defined like that (closures, whatever) should always require () to be invoked. If that doesn't sound reasonable, see this: auto dg1 = int function() { ... }; auto dg2 = dg1; I'd expect dg2's type to be dg1's type. Let's just think a solution to this problem first. :-)

Correct. Just that I fear that it's a bit late for this all. It is disheartening enough that Walter got convinced by the past discussion and introduced property without much design - after a FAILED vote no less. I strongly believe a better solution is available, but everyone wanted the feature so the feature just got born. FWIW, my take for issues like the above: if a function returns a function or a delegate, it can't avail itself of automatic invocation of "()". That takes care of a corner case and keeps the mainstream case in good shape. I am not sure of a good solution for problems like writeln = 2; Andrei

How about property? When you add a property to a function it can be called as an assignment. property does not touch the calling of no-argument functions. Are there any problems with that?

Such a " property is just for the writing" design will leave property adepts very unhappy, I think. Even I admit that such a rule will be very inconsistent, albeit workable. Andrei
Jan 29 2010
parent Lutger <lutger.blijdestijn gmail.com> writes:
On 01/29/2010 07:01 PM, Andrei Alexandrescu wrote:
...
 How about  property? When you add a  property to a function it can be
 called as an assignment.  property does not touch the calling of
 no-argument functions.

 Are there any problems with that?

Such a " property is just for the writing" design will leave property adepts very unhappy, I think. Even I admit that such a rule will be very inconsistent, albeit workable. Andrei

It's not inconsistent, at most just a bit confusing on the call site. What property does is still very clear: - same syntax as fields for zero and one parameter functions - function call syntax *not* ok - mangled differently and recognizable by ide's (think gui programmming and ui design tools) and documentation tools. Probably also for metaprogramming. Additionally at the call site you can choose to drop parens for zero argument functions, author of those functions has no control over that. This feature is now orthogonal to property and may or may not end up in style guidelines. It's also one of those things a smart IDE could help you with (did the author really want this to be a property or not?) I think that solves most of the issues property was designed for.
Jan 29 2010
prev sibling parent reply Ary Borenszweig <ary esperanto.org.ar> writes:
Andrei Alexandrescu wrote:
 Ary Borenszweig wrote:
 Andrei Alexandrescu wrote:
 Steven Schveighoffer wrote:
 On Fri, 29 Jan 2010 11:21:28 -0500, Andrei Alexandrescu 
 <SeeWebsiteForEmail erdani.org> wrote:

 How is f.byLine clearer and less ambiguous than f.byLine()? Or vice 
 versa for that matter?

Note that properties can be named things other than byLine. -Steve

What I meant to say is that in the property landscape the following two conventions become suddenly attractive: * Do not use property at all * Use property for all nullary functions And they're bound to save a lot of time to everyone involved.

The first post of this thread was about not invoking a function when you don't want it to be invoked. bearophile was doing: auto dg = int function() { ... }; return dg; but he wanted to return a reference to dg, not the result of invoking it. One way to prevent that is to never invoke functions unless they are marked with property. Or maybe functions defined like that (closures, whatever) should always require () to be invoked. If that doesn't sound reasonable, see this: auto dg1 = int function() { ... }; auto dg2 = dg1; I'd expect dg2's type to be dg1's type. Let's just think a solution to this problem first. :-)

Correct. Just that I fear that it's a bit late for this all. It is disheartening enough that Walter got convinced by the past discussion and introduced property without much design - after a FAILED vote no less. I strongly believe a better solution is available, but everyone wanted the feature so the feature just got born. FWIW, my take for issues like the above: if a function returns a function or a delegate, it can't avail itself of automatic invocation of "()". That takes care of a corner case and keeps the mainstream case in good shape. I am not sure of a good solution for problems like writeln = 2;

I think at least for the function/delegate problem, requiring () to invoke it might be good. int foo() { ... } auto dg1 = bool function() { ... }; auto x = dg1; // x is bool function() auto y = dg1(); // y is bool auto dg2 = &foo; auto z = dg2; // z is int function() auto w = dg2(); // z is int The only thing that remains "problematic" is this one: auto dg3 = foo; // It's int. To take the address use & // but might lead to unexpected results // when using "auto"
Jan 29 2010
parent =?UTF-8?B?UGVsbGUgTcOlbnNzb24=?= <pelle.mansson gmail.com> writes:
On 01/29/2010 07:23 PM, Ary Borenszweig wrote:
 Andrei Alexandrescu wrote:
 Ary Borenszweig wrote:
 Andrei Alexandrescu wrote:
 Steven Schveighoffer wrote:
 On Fri, 29 Jan 2010 11:21:28 -0500, Andrei Alexandrescu
 <SeeWebsiteForEmail erdani.org> wrote:

 How is f.byLine clearer and less ambiguous than f.byLine()? Or
 vice versa for that matter?

Note that properties can be named things other than byLine. -Steve

What I meant to say is that in the property landscape the following two conventions become suddenly attractive: * Do not use property at all * Use property for all nullary functions And they're bound to save a lot of time to everyone involved.

The first post of this thread was about not invoking a function when you don't want it to be invoked. bearophile was doing: auto dg = int function() { ... }; return dg; but he wanted to return a reference to dg, not the result of invoking it. One way to prevent that is to never invoke functions unless they are marked with property. Or maybe functions defined like that (closures, whatever) should always require () to be invoked. If that doesn't sound reasonable, see this: auto dg1 = int function() { ... }; auto dg2 = dg1; I'd expect dg2's type to be dg1's type. Let's just think a solution to this problem first. :-)

Correct. Just that I fear that it's a bit late for this all. It is disheartening enough that Walter got convinced by the past discussion and introduced property without much design - after a FAILED vote no less. I strongly believe a better solution is available, but everyone wanted the feature so the feature just got born. FWIW, my take for issues like the above: if a function returns a function or a delegate, it can't avail itself of automatic invocation of "()". That takes care of a corner case and keeps the mainstream case in good shape. I am not sure of a good solution for problems like writeln = 2;

I think at least for the function/delegate problem, requiring () to invoke it might be good. int foo() { ... } auto dg1 = bool function() { ... }; auto x = dg1; // x is bool function() auto y = dg1(); // y is bool auto dg2 = &foo; auto z = dg2; // z is int function() auto w = dg2(); // z is int The only thing that remains "problematic" is this one: auto dg3 = foo; // It's int. To take the address use & // but might lead to unexpected results // when using "auto"

If () is required to invoke delegates, that isn't a problem. First use will tell on it.
Jan 29 2010
prev sibling next sibling parent reply Justin Johansson <no spam.com> writes:
Andrei Alexandrescu wrote:
 Steven Schveighoffer wrote:
 On Fri, 29 Jan 2010 11:21:28 -0500, Andrei Alexandrescu 
 <SeeWebsiteForEmail erdani.org> wrote:

 How is f.byLine clearer and less ambiguous than f.byLine()? Or vice 
 versa for that matter?

Note that properties can be named things other than byLine. -Steve

What I meant to say is that in the property landscape the following two conventions become suddenly attractive: * Do not use property at all * Use property for all nullary functions And they're bound to save a lot of time to everyone involved. Andrei

Unless you assume no global state, nullary functions are just a figment of your imagination. Justin
Jan 29 2010
parent reply Andrei Alexandrescu <SeeWebsiteForEmail erdani.org> writes:
Justin Johansson wrote:
 Andrei Alexandrescu wrote:
 Steven Schveighoffer wrote:
 On Fri, 29 Jan 2010 11:21:28 -0500, Andrei Alexandrescu 
 <SeeWebsiteForEmail erdani.org> wrote:

 How is f.byLine clearer and less ambiguous than f.byLine()? Or vice 
 versa for that matter?

Note that properties can be named things other than byLine. -Steve

What I meant to say is that in the property landscape the following two conventions become suddenly attractive: * Do not use property at all * Use property for all nullary functions And they're bound to save a lot of time to everyone involved. Andrei

Unless you assume no global state, nullary functions are just a figment of your imagination.

Huh? What? Is there an extra "no"? Andrei
Jan 29 2010
parent Justin Johansson <no spam.com> writes:
Andrei Alexandrescu wrote:
 Justin Johansson wrote:
 Andrei Alexandrescu wrote:
 Steven Schveighoffer wrote:
 On Fri, 29 Jan 2010 11:21:28 -0500, Andrei Alexandrescu 
 <SeeWebsiteForEmail erdani.org> wrote:

 How is f.byLine clearer and less ambiguous than f.byLine()? Or vice 
 versa for that matter?

Note that properties can be named things other than byLine. -Steve

What I meant to say is that in the property landscape the following two conventions become suddenly attractive: * Do not use property at all * Use property for all nullary functions And they're bound to save a lot of time to everyone involved. Andrei

Unless you assume no global state, nullary functions are just a figment of your imagination.

Huh? What? Is there an extra "no"? Andrei

No, correct as I meant it. Confusion arises depending on whether you have a syntactic or semantic definition of "nullary" and / or FP or non-FP viewpoint. Some would argue that a simple writeln() function is a nullary function. Syntactically it is but there is a hidden argument, namely stdout. So writeln() is semantically non-nullary and may even be thought of as being declared by way of a macro expanded as fwriteln( FILE* fp = stdout). So unless the assumption is that there is no global state (including stdout in this case), thinking of writeln() as a nullary function is just a figment of one's imagination (imho) :-) It's a unary function with a default argument = stdout ! In the general case of a function, foo, taking N arguments where each argument is declared with a default value, e.g. foo( int a1 = 3, int a2 = 5, .. int aN = whatever), then called using all defaults as by foo(), or even just foo if optional dropping () is allowed, would people still argue that foo() with all default args is a nullary function? Just my two cents on nullary. -- Justin
Jan 29 2010
prev sibling parent reply Andrei Alexandrescu <SeeWebsiteForEmail erdani.org> writes:
Steven Schveighoffer wrote:
 On Fri, 29 Jan 2010 11:29:22 -0500, Andrei Alexandrescu 
 <SeeWebsiteForEmail erdani.org> wrote:
 
 Steven Schveighoffer wrote:
 On Fri, 29 Jan 2010 11:21:28 -0500, Andrei Alexandrescu 
 <SeeWebsiteForEmail erdani.org> wrote:

 How is f.byLine clearer and less ambiguous than f.byLine()? Or vice 
 versa for that matter?

-Steve

What I meant to say is that in the property landscape the following two conventions become suddenly attractive: * Do not use property at all * Use property for all nullary functions And they're bound to save a lot of time to everyone involved.

I think we all agree that setters the way D1 does them are very prone to abuse. So all that is left is no-argument functions. There are other alternative conventions to what you stated. This is my convention: * use property where the main purpose of the function is to fetch a value (computed or not, modifying the container or not)

Consider: struct Stack(T) { T pop(); ... } By your definition, pop() should be a property. It doesn't quite strike me as an intuitive decision. Andrei
Jan 29 2010
parent reply Andrei Alexandrescu <SeeWebsiteForEmail erdani.org> writes:
Steven Schveighoffer wrote:
 On Fri, 29 Jan 2010 12:23:24 -0500, Andrei Alexandrescu 
 <SeeWebsiteForEmail erdani.org> wrote:
 
 Steven Schveighoffer wrote:
 On Fri, 29 Jan 2010 11:29:22 -0500, Andrei Alexandrescu 
 <SeeWebsiteForEmail erdani.org> wrote:

 Steven Schveighoffer wrote:
 On Fri, 29 Jan 2010 11:21:28 -0500, Andrei Alexandrescu 
 <SeeWebsiteForEmail erdani.org> wrote:

 How is f.byLine clearer and less ambiguous than f.byLine()? Or 
 vice versa for that matter?

-Steve

What I meant to say is that in the property landscape the following two conventions become suddenly attractive: * Do not use property at all * Use property for all nullary functions And they're bound to save a lot of time to everyone involved.

prone to abuse. So all that is left is no-argument functions. There are other alternative conventions to what you stated. This is my convention: * use property where the main purpose of the function is to fetch a value (computed or not, modifying the container or not)

Consider: struct Stack(T) { T pop(); ... } By your definition, pop() should be a property. It doesn't quite strike me as an intuitive decision.

is pop's main purpose to fetch a value or to modify the stack? I'd say the purpose is split equally, so it's not a function whose main purpose is to fetch a value.

So now we're down to proportions, nuance, and where "main" goes. You made my point. I win.
 I admit this is a good example where a judgement 
 call comes into play, but we aren't all robots obeying every rule 
 literally.

If that's not enough, I have many others. With braces or names, I obey rules literally without any trouble. The problem with property is, there are too many exceptions, judgment calls, and edge cases.
 There are sometimes exceptions in conventions, or at least 
 the rule is subject to interpretation.

Which brings home my point: the entire business of deciding property or not is a waste of everyone's time. There's no simple rule, and there's no advantage to be gained after having made the decision one way or another. Andrei
Jan 29 2010
parent reply Michel Fortin <michel.fortin michelf.com> writes:
On 2010-01-29 12:56:43 -0500, Andrei Alexandrescu 
<SeeWebsiteForEmail erdani.org> said:

 Steven Schveighoffer wrote:
 On Fri, 29 Jan 2010 12:23:24 -0500, Andrei Alexandrescu 
 <SeeWebsiteForEmail erdani.org> wrote:
 Consider:
 
 struct Stack(T) {
      T pop();
      ...
 }
 
 By your definition, pop() should be a property. It doesn't quite strike 
 me as an intuitive decision.

is pop's main purpose to fetch a value or to modify the stack? I'd say the purpose is split equally, so it's not a function whose main purpose is to fetch a value.

So now we're down to proportions, nuance, and where "main" goes. You made my point. I win.

You win because Steven's definition is not good enough. I said before that we should have a authoritative definition. If we really can't define how a property should be defined after some reflection, then you really win. My definition is that a property gives access to an aspect of an object and doesn't modify it (the getter is essentially logical-const). In this case, 'pop' doesn't give you access to something in the stack, it removes an element (that's an action) and give you the element. It's pretty clear that 'pop' is used as a verb here, that should be enough to decide it's a function. -- Michel Fortin michel.fortin michelf.com http://michelf.com/
Jan 29 2010
next sibling parent reply Andrei Alexandrescu <SeeWebsiteForEmail erdani.org> writes:
Michel Fortin wrote:
 On 2010-01-29 12:56:43 -0500, Andrei Alexandrescu 
 <SeeWebsiteForEmail erdani.org> said:
 
 Steven Schveighoffer wrote:
 On Fri, 29 Jan 2010 12:23:24 -0500, Andrei Alexandrescu 
 <SeeWebsiteForEmail erdani.org> wrote:
 Consider:

 struct Stack(T) {
      T pop();
      ...
 }

 By your definition, pop() should be a property. It doesn't quite 
 strike me as an intuitive decision.

is pop's main purpose to fetch a value or to modify the stack? I'd say the purpose is split equally, so it's not a function whose main purpose is to fetch a value.

So now we're down to proportions, nuance, and where "main" goes. You made my point. I win.

You win because Steven's definition is not good enough. I said before that we should have a authoritative definition. If we really can't define how a property should be defined after some reflection, then you really win. My definition is that a property gives access to an aspect of an object and doesn't modify it (the getter is essentially logical-const).

Ok this makes sense. So something is a property if fetching it doesn't mess up the parent object. (Maybe properties should be pure even.) The lingering question is whether you can later use the fetched property to operate change in the parent object. I guess that it's reasonable to leave that up to the person defining the object and its property. I guess that's a set of rules that is simple, borderline meaningful, and easy to follow. By that logic File.byLine is a property, Stack.pop() is a function, Stack.top and Stack.empty are properties etc. That being said, I agree with Pelle that actions invoked without parens are darn attractive. Andrei
Jan 29 2010
parent Michel Fortin <michel.fortin michelf.com> writes:
On 2010-01-29 13:52:25 -0500, Andrei Alexandrescu 
<SeeWebsiteForEmail erdani.org> said:

 Ok this makes sense. So something is a property if fetching it doesn't 
 mess up the parent object. (Maybe properties should be pure even.)

Logical-pure, to be precise. ;-)
 The lingering question is whether you can later use the fetched 
 property to operate change in the parent object. I guess that it's 
 reasonable to leave that up to the person defining the object and its 
 property.

You can already do that with fields, so it make sense you can with properties too: class A { B b; } struct B { int c; } A a; a.b.c = 1; // works!
 I guess that's a set of rules that is simple, borderline meaningful, 
 and easy to follow. By that logic File.byLine is a property, 
 Stack.pop() is a function, Stack.top and Stack.empty are properties etc.
 
 That being said, I agree with Pelle that actions invoked without parens 
 are darn attractive.

And I agree too, they're attractive. But in a programming language I prefer to deal with less ambiguities even if it means a few more parenthesis. -- Michel Fortin michel.fortin michelf.com http://michelf.com/
Jan 29 2010
prev sibling next sibling parent Michel Fortin <michel.fortin michelf.com> writes:
On 2010-01-29 13:57:06 -0500, "Steven Schveighoffer" 
<schveiguy yahoo.com> said:

 You win because Steven's definition is not good enough. I said before  
 that we should have a authoritative definition. If we really can't  
 define how a property should be defined after some reflection, then you 
  really win.

Be careful here, don't give Andrei hard criteria for declaring victory ;)

"some reflection" is a hard criteria now? :-)
 But my larger point was that convention is convention, whether you use  
 parentheses to designate what a function does, or the symbol name 
 itself.   Deciding the convention is liable to suit some and not 
 others.  Some  people hate the flat terse names of Phobos' modules.  
 Does that mean those  people are wrong?  Does that mean Walter and 
 Andrei are wrong?  The only  thing that is wrong here is deciding there 
 is exactly one right rigid way  to designate what should and should not 
 be a property.

Andrei wanted a good enough guideline so I gave one to him. We need a guideline if we hope for some consistency. Hopefully this guideline will be used through Phobos and this will set the example.
 I think we should have a definition of property convention for Phobos, 
 but  I don't think it needs to be the *only* way people use properties 
 in their  own projects.  In fact, it can't be because there is no 
 english (or  whatever language you use) interpreter in the compiler.

If someone want to diverge from the guideline, then that's his choice. It's pretty much like operator overloading: you can use it the intended way, or you can build boost::spirit. It's not like the compiler will ever be able to enforce this kind of thing, so there'll always be room for abuse, if you feel like it. -- Michel Fortin michel.fortin michelf.com http://michelf.com/
Jan 29 2010
prev sibling parent Andrei Alexandrescu <SeeWebsiteForEmail erdani.org> writes:
Bill Baxter wrote:
 One more example to consider:  RNG.randomInt()  or RNG.randomInt
 
 I think Steven is right that you can always find corner cases, but
 that the existence of corner cases is pretty irrelevant.

I agree. It's not the existence of corner cases I'm worried about, it's the frequency. Andrei
Jan 29 2010
prev sibling parent reply Justin Johansson <no spam.com> writes:
Steven Schveighoffer wrote:
 
 We need digitalmars.D.is_it_a_property_or_not. Whenever in doubt, 
 people can ask a question there.

OK: digitalmars.d.should_this_be_a_class_or_struct. digitalmars.d.should_this_symbol_be_capitalized. digitalmars.d.should_this_use_a_function_pointer_or_delegate. digitalmars.d.should_this_be_const_or_immutable. Can we ever get any work done without these? -Steve

Closer to the mark would be ... digitalmars.d1.dont_ask digitalmars.d2.should_this_be_a_class_or_struct digitalmars.d2.should_this_symbol_be_capitalized digitalmars.d2.should_this_use_a_function_pointer_or_delegate digitalmars.d2.should_this_be_const_or_immutable digitalmars.d2.will_shared_ever_work Justin
Jan 29 2010
parent reply Michel Fortin <michel.fortin michelf.com> writes:
On 2010-01-29 11:47:17 -0500, Justin Johansson <no spam.com> said:

 Closer to the mark would be ...
 
 digitalmars.d1.dont_ask
 digitalmars.d2.should_this_be_a_class_or_struct
 digitalmars.d2.should_this_symbol_be_capitalized
 digitalmars.d2.should_this_use_a_function_pointer_or_delegate
 digitalmars.d2.should_this_be_const_or_immutable
 digitalmars.d2.will_shared_ever_work
 
 Justin

Also digitalmars.d.should_we_make_a_new_forum_for_this -- Michel Fortin michel.fortin michelf.com http://michelf.com/
Jan 29 2010
parent Justin Johansson <no spam.com> writes:
Michel Fortin wrote:
 On 2010-01-29 11:47:17 -0500, Justin Johansson <no spam.com> said:
 
 Closer to the mark would be ...

 digitalmars.d1.dont_ask
 digitalmars.d2.should_this_be_a_class_or_struct
 digitalmars.d2.should_this_symbol_be_capitalized
 digitalmars.d2.should_this_use_a_function_pointer_or_delegate
 digitalmars.d2.should_this_be_const_or_immutable
 digitalmars.d2.will_shared_ever_work

 Justin

Also digitalmars.d.should_we_make_a_new_forum_for_this

We could just join in over at scala.org.what_is_the_difference_between_var_val_and_def_keywords bit the ensuring discussion would not be as friendly. Justin
Jan 29 2010
prev sibling parent reply Andrei Alexandrescu <SeeWebsiteForEmail erdani.org> writes:
Steven Schveighoffer wrote:
 On Fri, 29 Jan 2010 08:03:13 -0500, Michel Fortin 
 <michel.fortin michelf.com> wrote:
 
 On 2010-01-29 06:25:44 -0500, Pelle MÃ¥nsson <pelle.mansson gmail.com> 
 said:

 On 01/29/2010 05:48 AM, Michel Fortin wrote:
  No. Calling byLine doesn't change the stream. It returns a different
 view of stdin, which can be used to modify the stream, or not. I think
 it should be a property. If it was 'getNextLine' then it should be a
 function. As a proof, this doesn't have any effect:
  stdin.byLine;


Ah, I see, you're right. Silly me for not trying. So it's not an accessor after all. The problem is that, even disregarding the property syntax, the name strongly suggests it's an accessor, but it has side effects, which it shouldn't. Either we change the name to something else, like 'consumeLines()', or we make it behave like an accessor. I'd go for the second option. The basic problem lies in the very basic definition of an input range. Due to its interface (popFront + front), an input range is forced to consume the its first element by its mere existence. I think constructing an input range shouldn't have side effects. It should be more symmetrical with an output range. It could have just one function, 'take' to get the next element, and now byLine could work correctly.

Hey, it's that dead horse again, let's beat it! Andrei and I and several others discussed this ad infinitum. You will never convince Andrei that his design is wrong :)

Which debate are you referring to?
 The truth is, the fact that byLine modifies stdin by its mere existence 
 proves to be inconsequential.  Nobody will fetch the byLine property 
 without using it.  It's still an accessor.

Yah, though I agree it's nicer to not prime the line in the constructor. Andrei
Jan 29 2010
parent reply Michel Fortin <michel.fortin michelf.com> writes:
On 2010-01-29 10:49:34 -0500, "Steven Schveighoffer" 
<schveiguy yahoo.com> said:

 ugh... much simpler with a true stream-like range that supports what is 
  natural for streams:
 
 for(int i = 0; i < count && !range.empty; i++) {
     elements ~= range.get();
 }
 
 But of course, then this function doesn't work for other range types.  
 I  decided in that discussion long ago that stream ranges were going to 
 suck.

You can always define a generic take() like this: E take(R, E)(ref R range) { E element = range.front; range.popFront(); return element; } This will work for any forward range. -- Michel Fortin michel.fortin michelf.com http://michelf.com/
Jan 29 2010
next sibling parent Michel Fortin <michel.fortin michelf.com> writes:
On 2010-01-29 11:00:31 -0500, "Steven Schveighoffer" 
<schveiguy yahoo.com> said:

 On Fri, 29 Jan 2010 10:53:50 -0500, Michel Fortin  
 <michel.fortin michelf.com> wrote:
 
 On 2010-01-29 10:49:34 -0500, "Steven Schveighoffer"  
 <schveiguy yahoo.com> said:
 
 ugh... much simpler with a true stream-like range that supports what is 
   natural for streams:
  for(int i = 0; i < count && !range.empty; i++) {
     elements ~= range.get();
 }
  But of course, then this function doesn't work for other range types.  
  I  decided in that discussion long ago that stream ranges were going 
 to  suck.

You can always define a generic take() like this: E take(R, E)(ref R range) { E element = range.front; range.popFront(); return element; } This will work for any forward range.

Except stream ranges. I don't get it...

Hum, well I used 'take' while you defined 'get' as the basic function for stream ranges. They're the same thing. Rename 'take' for 'get', or the reverse, and all input ranges can work with the same 'get' or 'take' function. (Note: I use 'take' instead of 'get' because it seems clearer to me that it also removes the element from the range.) -- Michel Fortin michel.fortin michelf.com http://michelf.com/
Jan 29 2010
prev sibling parent reply Andrei Alexandrescu <SeeWebsiteForEmail erdani.org> writes:
Steven Schveighoffer wrote:
 On Fri, 29 Jan 2010 10:53:50 -0500, Michel Fortin 
 <michel.fortin michelf.com> wrote:
 
 On 2010-01-29 10:49:34 -0500, "Steven Schveighoffer" 
 <schveiguy yahoo.com> said:

 ugh... much simpler with a true stream-like range that supports what 
 is  natural for streams:
  for(int i = 0; i < count && !range.empty; i++) {
     elements ~= range.get();
 }
  But of course, then this function doesn't work for other range 
 types.  I  decided in that discussion long ago that stream ranges 
 were going to suck.

You can always define a generic take() like this: E take(R, E)(ref R range) { E element = range.front; range.popFront(); return element; } This will work for any forward range.

Except stream ranges. I don't get it...

It should work for stream ranges if front() checks the "filled" flag and eats the next line if false, and popFront clears the "filled" flag. Andrei
Jan 29 2010
next sibling parent Andrei Alexandrescu <SeeWebsiteForEmail erdani.org> writes:
Steven Schveighoffer wrote:
 On Fri, 29 Jan 2010 11:18:46 -0500, Andrei Alexandrescu 
 <SeeWebsiteForEmail erdani.org> wrote:
 
 Steven Schveighoffer wrote:
 On Fri, 29 Jan 2010 10:53:50 -0500, Michel Fortin 
 <michel.fortin michelf.com> wrote:

 On 2010-01-29 10:49:34 -0500, "Steven Schveighoffer" 
 <schveiguy yahoo.com> said:

 ugh... much simpler with a true stream-like range that supports 
 what is  natural for streams:
  for(int i = 0; i < count && !range.empty; i++) {
     elements ~= range.get();
 }
  But of course, then this function doesn't work for other range 
 types.  I  decided in that discussion long ago that stream ranges 
 were going to suck.

You can always define a generic take() like this: E take(R, E)(ref R range) { E element = range.front; range.popFront(); return element; } This will work for any forward range.


It should work for stream ranges if front() checks the "filled" flag and eats the next line if false, and popFront clears the "filled" flag.

That actually makes a lot of sense. I hope this fix goes in.

http://d.puremagic.com/issues/show_bug.cgi?id=3752 Andrei
Jan 29 2010
prev sibling parent reply Michel Fortin <michel.fortin michelf.com> writes:
On 2010-01-29 11:18:46 -0500, Andrei Alexandrescu 
<SeeWebsiteForEmail erdani.org> said:

 It should work for stream ranges if front() checks the "filled" flag 
 and eats the next line if false, and popFront clears the "filled" flag.

So now you want the front to fetch from stdin on the first call? It's the same problem as 'byLine' eating the first line when you create it: neither one or the other should affect the stream. Take my example from before: // fetch 3 lines: string[] consume(3, stdin.byLine); // now fill a buffer ubyte[] buffer; buffer = stdin.rawRead(buffer); E[] consume(E, R)(int count, R range) { E[] elements; foreach (i; 0..count) { elements ~= range.front; range.popFront(); } return elements; } Now add a range.front just after the popFront(): E[] consume(E, R)(int count, R range) { E[] elements; foreach (i; 0..count) { elements ~= range.front; range.popFront(); E peakedElement = range.front; } return elements; } And suddenly you'll get the same problem. -- Michel Fortin michel.fortin michelf.com http://michelf.com/
Jan 29 2010
next sibling parent Andrei Alexandrescu <SeeWebsiteForEmail erdani.org> writes:
Michel Fortin wrote:
 On 2010-01-29 11:18:46 -0500, Andrei Alexandrescu 
 <SeeWebsiteForEmail erdani.org> said:
 
 It should work for stream ranges if front() checks the "filled" flag 
 and eats the next line if false, and popFront clears the "filled" flag.

So now you want the front to fetch from stdin on the first call? It's the same problem as 'byLine' eating the first line when you create it: neither one or the other should affect the stream. Take my example from before: // fetch 3 lines: string[] consume(3, stdin.byLine); // now fill a buffer ubyte[] buffer; buffer = stdin.rawRead(buffer); E[] consume(E, R)(int count, R range) { E[] elements; foreach (i; 0..count) { elements ~= range.front; range.popFront(); } return elements; } Now add a range.front just after the popFront(): E[] consume(E, R)(int count, R range) { E[] elements; foreach (i; 0..count) { elements ~= range.front; range.popFront(); E peakedElement = range.front; } return elements; } And suddenly you'll get the same problem.

I think this is not a problem as much as an organic characteristic of streams. STL's input streams work the same. Andrei
Jan 29 2010
prev sibling parent reply Michel Fortin <michel.fortin michelf.com> writes:
On 2010-01-29 11:54:41 -0500, "Steven Schveighoffer" 
<schveiguy yahoo.com> said:

 On Fri, 29 Jan 2010 11:33:17 -0500, Michel Fortin  
 <michel.fortin michelf.com> wrote:
 
 On 2010-01-29 11:18:46 -0500, Andrei Alexandrescu  
 <SeeWebsiteForEmail erdani.org> said:
 
 It should work for stream ranges if front() checks the "filled" flag  
 and eats the next line if false, and popFront clears the "filled" flag.

So now you want the front to fetch from stdin on the first call? It's the same problem as 'byLine' eating the first line when you create it: neither one or the other should affect the stream.

No, you're reaching here :) What Andrei is doing is acknowledging that front has already performed the job of popFront. Because of the nature of streams, you cannot get the data from the stream, and leave it on the stream at the same time. It's just not feasible. What the solution Andrei came up with does is to make stream ranges behave as close as possible to forward ranges. That small inconsistency will not hurt you because most of the time you are not calling front for an element you don't intend to use. And even within that paradigm, you are even less likely to use the stream in another capacity.

"will not hurt because most of the time"... surely you meant "will not hurt most of the time because". You're acknowledging it's an inconsistency and that it'll hurt.
 In other words, as the last usage of a range in an algorithm function,  this:
 
 r.front;
 r.popFront();
 
 is way more likely than:
 
 r.popFront()
 r.front;

Yeah, it's less likely to be a problem. But "less likely to be a problem" does still does not make things reliable. Something reliable works all the time, or it just doesn't work and tells you. And I'd argue that it's very likely that an algorithm hits the problem, check this: skipEmptyLines(stdin.byLine); string line = stdin.readln; void skipEmptyLines(R)(R range) { while (!range.empty && range.front == "") range.popFront; } skipEmptyLine works right with ranges, but not with a stream. On the last loop, it calls range.front, which removes a line from the stream, and then say it's finished. The truth is that this algorithm doesn't work with streams as it relies on a buffer being available. But it still compiles, silently introducing a bogus behaviour. If byLine defined only a 'take' function, we wouldn't have this problem as skipEmptyLines wouldn't compile, forcing you to use some kind of buffered stream or another algorithm that works correctly with streams. -- Michel Fortin michel.fortin michelf.com http://michelf.com/
Jan 29 2010
parent reply Andrei Alexandrescu <SeeWebsiteForEmail erdani.org> writes:
Michel Fortin wrote:
 Yeah, it's less likely to be a problem. But "less likely to be a 
 problem" does still does not make things reliable. Something reliable 
 works all the time, or it just doesn't work and tells you.

stream.front after stream.popFront works all the time and fetches a new line off the stream. Like Steve said, you can't at the same time fetch a line and leave it back in the stream. Andrei
Jan 29 2010
parent reply Michel Fortin <michel.fortin michelf.com> writes:
On 2010-01-29 12:21:18 -0500, Andrei Alexandrescu 
<SeeWebsiteForEmail erdani.org> said:

 Michel Fortin wrote:
 Yeah, it's less likely to be a problem. But "less likely to be a 
 problem" does still does not make things reliable. Something reliable 
 works all the time, or it just doesn't work and tells you.

stream.front after stream.popFront works all the time and fetches a new line off the stream. Like Steve said, you can't at the same time fetch a line and leave it back in the stream.

The problem is that algorithms that depends on this will work with other ranges, but will fail silently when given a stream. In all seriousness, even Java streams are better modeled than this (although more limited by not having templates). The basic Java input stream doesn't have a 'front' byte, you can only read the next byte (or the few next bytes). If you need to rewind, there is a standard way, but most streams need to be wrapped in a buffered stream first to provide this capability. So in our case, if you need to add a one-byte or a one-line buffer for a filtering stream I think it should be done explicitly as it has side effects on the underlying stream. In Java you do this by composition, creating a buffered stream from another input stream when you need one. Doing this implicitly, and especially creating a separate buffer each time you create a new filtering range, is what makes the problem hard to follow. Making 'front' lazy fetching will help in many cases, but it'll never remove the problem entirely. -- Michel Fortin michel.fortin michelf.com http://michelf.com/
Jan 29 2010
parent reply Andrei Alexandrescu <SeeWebsiteForEmail erdani.org> writes:
Michel Fortin wrote:
 On 2010-01-29 12:21:18 -0500, Andrei Alexandrescu 
 <SeeWebsiteForEmail erdani.org> said:
 
 Michel Fortin wrote:
 Yeah, it's less likely to be a problem. But "less likely to be a 
 problem" does still does not make things reliable. Something reliable 
 works all the time, or it just doesn't work and tells you.

stream.front after stream.popFront works all the time and fetches a new line off the stream. Like Steve said, you can't at the same time fetch a line and leave it back in the stream.

The problem is that algorithms that depends on this will work with other ranges, but will fail silently when given a stream.

An algorithm can fail in many silent ways if it misuses the range interface. None of std.algorithm algorithms uses front naively.
 In all seriousness, even Java streams are better modeled than this 
 (although more limited by not having templates). The basic Java input 
 stream doesn't have a 'front' byte, you can only read the next byte (or 
 the few next bytes). If you need to rewind, there is a standard way, but 
 most streams need to be wrapped in a buffered stream first to provide 
 this capability.

Can you run a basic algorithm on a Java stream and on an array as well? Andrei
Jan 29 2010
parent reply Michel Fortin <michel.fortin michelf.com> writes:
On 2010-01-29 12:53:27 -0500, Andrei Alexandrescu 
<SeeWebsiteForEmail erdani.org> said:

 An algorithm can fail in many silent ways if it misuses the range 
 interface. None of std.algorithm algorithms uses front naively.

Easy to say. How did you verify that? The problem is very subtle: if you call front after popFront on something like byLine which adds a buffer on top of another range, it'll eat one or more element on the downstream range that will be lost if you dispose of the filtering range. It won't have any effect on algorithms using the filtering range in itself, only on those using both the filtering range and the downstream range in tandem. So basically, if you have an algorithm that calls front after popFront, that algorithm cannot be used reliably for ranges filtering a stream when that stream is also used directly, or used via other filtering ranges. There's no way to enforce that as it becomes the user's problem. Whereas if input ranges only define 'take', it's pretty easy for the compiler to tell you an algorithm needs a buffer, so you add an intermediary buffer range yourself and you're now aware of the consequences.
 Can you run a basic algorithm on a Java stream and on an array as well?

Java lacks templates, and thus lack compile-time duck typing and work only with bytes. But you could iterate on an array as if it was a stream: class ArrayStream { byte[] array; int pos; ArrayStream(byte[] array) { this.array = array; pos = 0; } int read() { if (pos > array.length) return -1; else return array[pos++]; } } I'm not trying to say that Java streams are superior to ranges, but they don't have unintended buffering issues. -- Michel Fortin michel.fortin michelf.com http://michelf.com/
Jan 29 2010
parent Andrei Alexandrescu <SeeWebsiteForEmail erdani.org> writes:
Michel Fortin wrote:
 On 2010-01-29 12:53:27 -0500, Andrei Alexandrescu 
 <SeeWebsiteForEmail erdani.org> said:
 
 An algorithm can fail in many silent ways if it misuses the range 
 interface. None of std.algorithm algorithms uses front naively.

Easy to say. How did you verify that?

It's simply a mistake I make very seldom if at all (I don't remember any instance). The range interface is narrow, and algorithms are always careful with how they use it.
 The problem is very subtle: if you call front after popFront on 
 something like byLine which adds a buffer on top of another range, it'll 
 eat one or more element on the downstream range that will be lost if you 
 dispose of the filtering range. It won't have any effect on algorithms 
 using the filtering range in itself, only on those using both the 
 filtering range and the downstream range in tandem.

Subtle problems could occur with a variety of other ranges if some algorithm messes them up.
 So basically, if you have an algorithm that calls front after popFront, 
 that algorithm cannot be used reliably for ranges filtering a stream 
 when that stream is also used directly, or used via other filtering 
 ranges. There's no way to enforce that as it becomes the user's problem.
 
 Whereas if input ranges only define 'take', it's pretty easy for the 
 compiler to tell you an algorithm needs a buffer, so you add an 
 intermediary buffer range yourself and you're now aware of the 
 consequences.

I like take (I actually called it getNext). There was just too much aggravation in defining and using that interface. I've literally lost nights over figuring it out, and couldn't. Searching for getNext on this group will reveal some of the issues. Andrei
Jan 29 2010
prev sibling parent "Nick Sabalausky" <a a.a> writes:
"Michel Fortin" <michel.fortin michelf.com> wrote in message 
news:hjtpb4$1t17$1 digitalmars.com...
 Andrei, you keep complaining it's a convention. It *is* a convention, 
 because only a convention can differentiate actions from accessors. 
 Ideally, we wouldn't need a special syntax: English words would be enough. 
 But as you know English words alone are often ambiguous.

It's more than just the existence of ambiguous english words. It's also that () vs no-() makes it far easier to tell at a mere glance whether or not you're looking at a function. Imagine scrolling through a big chunk of code in a language that lacks optional-parens (and doesn't do any of that Java-style "getFoo()" crap). Without even reading a word of it, you quite literally *see* "function, function, value, value, etc." But with optional-parens (or those awful Java-style accessors), that gets thrown out the window and code needs more direct examination just to get the same amount of info out of it.
Jan 29 2010
prev sibling parent "Steven Schveighoffer" <schveiguy yahoo.com> writes:
On Fri, 29 Jan 2010 13:52:25 -0500, Andrei Alexandrescu  
<SeeWebsiteForEmail erdani.org> wrote:

 Michel Fortin wrote:
  My definition is that a property gives access to an aspect of an  
 object and doesn't modify it (the getter is essentially logical-const).

Ok this makes sense. So something is a property if fetching it doesn't mess up the parent object. (Maybe properties should be pure even.)

No, because pure implies that the object must be immutable. They should be inout (if indeed they do not modify the object). But you have some problems there. Whether it logically modifies the object or not (I hate to use it, but byLine.front as proposed would have to not be inout) is subject to interpretation. I think it should not be a hard requirement, and at best should be expected to possibly mutate private state.
 The lingering question is whether you can later use the fetched property  
 to operate change in the parent object. I guess that it's reasonable to  
 leave that up to the person defining the object and its property.

It isn't any different than using a field to modify the parent's state. Not modifying the parent's state is simply not in the charter for properties. It's too strict, and doesn't follow the abilities of that which it is modeled after.
 That being said, I agree with Pelle that actions invoked without parens  
 are darn attractive.

To each his own. I find them unclean and ambiguous. -Steve
Jan 29 2010
prev sibling parent "Steven Schveighoffer" <schveiguy yahoo.com> writes:
On Fri, 29 Jan 2010 12:56:43 -0500, Andrei Alexandrescu  
<SeeWebsiteForEmail erdani.org> wrote:


 So now we're down to proportions, nuance, and where "main" goes. You  
 made my point. I win.

You just don't get it. declaring property or not is part of naming the function. Any naming convention either can have strict rules or not. You cited two very strict naming conventions, I cited a not-so-strict one, one that is open to interpretation. A similar naming convention in Java is the "isX" being a boolean property. Well, that doesn't always work because english doesn't always follow strict rules. Same thing for properties. I don't know what you think you've won. I never said properties make every possible function name intuitive.
 I admit this is a good example where a judgement call comes into play,  
 but we aren't all robots obeying every rule literally.

If that's not enough, I have many others. With braces or names, I obey rules literally without any trouble. The problem with property is, there are too many exceptions, judgment calls, and edge cases.

We went through scores of threads dissecting the names for range methods and what they should be. Does that mean that ranges are useless because we had to waste so much time naming their functions? The fact that we are arguing over one stupid function for this long is mind-boggling. Drop the straw man and look at the big picture. MOST OF THE TIME it is useful and intuitive. If that's not worth anything to you, then I don't know what else to say.
 There are sometimes exceptions in conventions, or at least the rule is  
 subject to interpretation.

Which brings home my point: the entire business of deciding property or not is a waste of everyone's time. There's no simple rule, and there's no advantage to be gained after having made the decision one way or another.

No, there is no simple rule, just like there's no simple rule for symbol names. If you spend the time to name your properties correctly, the intuition provided saves all your users from wasting time looking up the documentation. It saves reviewers from wasting time looking up documentation to understand what a coder is doing. It's not a waste of time if it has benefits, and it does. You just refuse to believe it. -Steve
Jan 29 2010
prev sibling parent Rainer Deyke <rainerd eldwood.com> writes:
Michiel Helvensteijn wrote:
 Ah, my bad. I was guessing. Still, returning a handle from a property that
 can change the state of the originating object is.. iffy.

I disagree. For example, I recently had to deal with tables. Each table has rows and columns. Removing a row removes a cell from each column. Removing a column removes a cell from each row. However, I wanted to deal with both the set of rows and the set of columns as generic sequences. My solution was something like this: struct Table { RowView rows(); ColumnView columns(); }; I think 'rows' and 'columns' are perfect candidates for properties. They are nouns, not verbs. They could reasonably be implemented as fields instead of functions. They are not actions. They are views into the containing Table. Aspects of the Table, if you will. Properties. -- Rainer Deyke - rainerd eldwood.com
Jan 29 2010
prev sibling next sibling parent Bill Baxter <wbaxter gmail.com> writes:
On Thu, Jan 28, 2010 at 3:58 PM, Nick Sabalausky <a a.a> wrote:
 "Andrei Alexandrescu" <SeeWebsiteForEmail erdani.org> wrote in message
 news:hjt449$5d8$1 digitalmars.com...
 Bill Baxter wrote:
 On Thu, Jan 28, 2010 at 2:27 PM, Andrei Alexandrescu
 The problem is not localized change. The result of stdin.byLine change=




 the
 _entire_ stdin.

Ok, so you have no problem with a car.wheels returning a mutable wheels object? So it's only when the returned property can change the entire state (or a lot of the state?) that you have a problem? I don't understand how degree changes the acceptability. =A0Doesn't see=



 like it should matter to me.

If you access car.wheel, it is reasonable to repaint that wheel. The problem is that you can use car.wheel to repaint the car.

Ok, so you don't think a property of something should be able to change other parts of that something? Ok, I can understand that. But if that's s=

 then how would it be any better to be able to change something through th=

 return value of one of that something's member functions? (Which, of cour=

 is what stdin.byLine apperently already does.)

 Ie, Given this code:

 auto foo =3D stdin.byLine;
 foo.doSomethingThatAdvancesStdin();

 How is it possible for that code to be bad when "byLine" is defined as a
 " property", but suddenly be perfectly fine when omittable parens are
 allowed and it's defined without " property", even though either way it's
 still the exact same code doing exactly the same thing and having exactly
 the same effects?

That's not a contradiction in Andrei's position at all. Because if there is no property, then all that dropping parens means is that it's a no-function argument. In the original D1 scheme, .foo just means foo is either field or a zero-arg function. Nothing more nothing less. The problem is that you can't tell if the coder meant it to be a property or not, and this bites you in cases like returning callable. --bb
Jan 28 2010
prev sibling parent "Steven Schveighoffer" <schveiguy yahoo.com> writes:
On Thu, 28 Jan 2010 20:51:29 -0500, Andrei Alexandrescu  
<SeeWebsiteForEmail erdani.org> wrote:

 Nick Sabalausky wrote:
 "Andrei Alexandrescu" <SeeWebsiteForEmail erdani.org> wrote in message  
 news:hjtcbd$r0a$1 digitalmars.com...
 Nick Sabalausky wrote:
 And yes, I already pointed out that would make it a no-argument  
 function. And that's precisely my point. If we accept that it's bad  
 to paint a car via its " property" wheel, then how can we possibly  
 accept this to not be just as bad?:

 auto car = new Car();
 auto wheel = car.getWheel_ThisIsAFunctionNotAProperty();
 wheel.paintTheCar();



Unfortunately not. It forces nothing. That's my problem with the feature - it's nothing more than fostering a convention.

It forces a convention. The convention is important, almost as important as the name of the function. Think of it as an extension of the function name, like extra punctuation that changes the human interpretation of the function. It means you must be explicit what you intend, the parentheses become a detail that is important to the compiler. If we adopted a convention where you could do: int x, y; int z = x y; implying that x should be added to y, then that would certainly work. But what value does it add (no pun intended)? Did the user intend to add them, or did he just make a typo? The convention of requiring the operator forces you to create unambiguous code, just like requiring the parentheses forces you to declare your expectation of the function. -Steve
Jan 29 2010
prev sibling next sibling parent reply Andrei Alexandrescu <SeeWebsiteForEmail erdani.org> writes:
Bill Baxter wrote:
 On Thu, Jan 28, 2010 at 1:26 PM, Andrei Alexandrescu
 <SeeWebsiteForEmail erdani.org> wrote:
 Steven Schveighoffer wrote:
 On Thu, 28 Jan 2010 15:59:30 -0500, Andrei Alexandrescu
 <SeeWebsiteForEmail erdani.org> wrote:
 foreach (line; stdin.byLine()) { ... }

 vs.

 foreach (line; stdin.byLine) { ... }

 How do I choose?

-Steve


Maybe "property" is a misleading word. Clearly there are more things to which that applies than just what the traditional definition of the word would imply. I would not in English call my nose a "property" of me, but if I were a D object and had a .nose accessor, I would certainly think that accessor would qualify as a D property. How's this: anything that you can "get" without specifying additional information (and which doesn't change the outwardly visible state the object when you do so) is a property. The C# syntax with the special use of "get" and "set" perhaps does a better job of conveying this.

This raises the hair on my back. It's back to programming-by-convention. Andrei
Jan 28 2010
parent reply Andrei Alexandrescu <SeeWebsiteForEmail erdani.org> writes:
Bill Baxter wrote:
 On Thu, Jan 28, 2010 at 2:07 PM, Andrei Alexandrescu
 <SeeWebsiteForEmail erdani.org> wrote:
 Bill Baxter wrote:
 On Thu, Jan 28, 2010 at 1:26 PM, Andrei Alexandrescu
 <SeeWebsiteForEmail erdani.org> wrote:
 Steven Schveighoffer wrote:
 On Thu, 28 Jan 2010 15:59:30 -0500, Andrei Alexandrescu
 <SeeWebsiteForEmail erdani.org> wrote:
 foreach (line; stdin.byLine()) { ... }

 vs.

 foreach (line; stdin.byLine) { ... }

 How do I choose?

-Steve


to which that applies than just what the traditional definition of the word would imply. I would not in English call my nose a "property" of me, but if I were a D object and had a .nose accessor, I would certainly think that accessor would qualify as a D property. How's this: anything that you can "get" without specifying additional information (and which doesn't change the outwardly visible state the object when you do so) is a property. The C# syntax with the special use of "get" and "set" perhaps does a better job of conveying this.


Wait, you started off by saying "how do I decide?" and we give you a rule you can follow to decide and now you say you don't like it because it's programming-by-convention? I guess I don't really understand what your argument is.

It's not a rule. It's several contradictory ones. Andrei
Jan 28 2010
parent reply Andrei Alexandrescu <SeeWebsiteForEmail erdani.org> writes:
Bill Baxter wrote:
 On Thu, Jan 28, 2010 at 2:25 PM, Andrei Alexandrescu
 <SeeWebsiteForEmail erdani.org> wrote:
 Bill Baxter wrote:
 On Thu, Jan 28, 2010 at 2:07 PM, Andrei Alexandrescu
 <SeeWebsiteForEmail erdani.org> wrote:
 Bill Baxter wrote:
 On Thu, Jan 28, 2010 at 1:26 PM, Andrei Alexandrescu
 <SeeWebsiteForEmail erdani.org> wrote:
 Steven Schveighoffer wrote:
 On Thu, 28 Jan 2010 15:59:30 -0500, Andrei Alexandrescu
 <SeeWebsiteForEmail erdani.org> wrote:
 foreach (line; stdin.byLine()) { ... }

 vs.

 foreach (line; stdin.byLine) { ... }

 How do I choose?

-Steve


to which that applies than just what the traditional definition of the word would imply. I would not in English call my nose a "property" of me, but if I were a D object and had a .nose accessor, I would certainly think that accessor would qualify as a D property. How's this: anything that you can "get" without specifying additional information (and which doesn't change the outwardly visible state the object when you do so) is a property. The C# syntax with the special use of "get" and "set" perhaps does a better job of conveying this.


rule you can follow to decide and now you say you don't like it because it's programming-by-convention? I guess I don't really understand what your argument is.


Please point out the contradictions. I'm not seeing them.

Some said it should be stdin.byLine(), some others said it should be stdin.byLine. They invoked contradictory rules that led to contradictory conclusions. Andrei
Jan 28 2010
parent Michel Fortin <michel.fortin michelf.com> writes:
On 2010-01-29 17:22:11 -0500, Gerrit Wichert <gw green-stores.de> said:

 [skipping a long part]
 But I don't want to advertise any Perl, just hoping the idees behind
 Moose can be helpful. So back to D.

Objective-C properties look like that too. You declare a property with a name, a type and some flags (like readonly), and you can either provide your own accessor functions or tell the compiler to synthesize them. All this reminds me the debate about what to do with properties a long time ago. Walter finally settled for property, so that's what we have now. I don't really want to reopen the debate. Thinking about it, I'm wondering if property wouldn't be better named as accessor. After all, each function labeled property isn't a property in itself, it's an accessor for that property constituted of all the overloaded accessor functions having the same name. But that's just a small cosmetic issue and I don't mind very much.
 Now to your problem with byLine:
 
 Some said it should be stdin.byLine(), some others said it should be
 stdin.byLine. They invoked contradictory rules that led to contradictory
 conclusions.

If byLine internally constructs a new range instance that happens to use stdin for iterating by line, this to me ist clearly a function. And then the normal rules for calling a function in the D language must apply. This has nothing to do with properties. If you have a single ByLineRange instance stored in stdin that is simply handed out by the byLine function, than this can be seen as a getter function of a byLine property and *both* forms should be applicable.

I think that's not exactly how it should be. I'd rather say: if you can conceptualize stdin as containing a ByLineRange then it is fit as a property. The actual implementation of stdin and byLine shouldn't matter.
 So, that is my opinion about properties. I hope it makes some sense to
 you or is helpful to anyone.

It makes sense in that it's a valid way to think about properties. I just don't feel it's worth reopening that debate now that we have something. -- Michel Fortin michel.fortin michelf.com http://michelf.com/
Jan 29 2010
prev sibling parent "Steven Schveighoffer" <schveiguy yahoo.com> writes:
On Fri, 29 Jan 2010 11:29:22 -0500, Andrei Alexandrescu  
<SeeWebsiteForEmail erdani.org> wrote:

 Steven Schveighoffer wrote:
 On Fri, 29 Jan 2010 11:21:28 -0500, Andrei Alexandrescu  
 <SeeWebsiteForEmail erdani.org> wrote:

 How is f.byLine clearer and less ambiguous than f.byLine()? Or vice  
 versa for that matter?

-Steve

What I meant to say is that in the property landscape the following two conventions become suddenly attractive: * Do not use property at all * Use property for all nullary functions And they're bound to save a lot of time to everyone involved.

I think we all agree that setters the way D1 does them are very prone to abuse. So all that is left is no-argument functions. There are other alternative conventions to what you stated. This is my convention: * use property where the main purpose of the function is to fetch a value (computed or not, modifying the container or not) There are others mentioned in this thread. A property convention is useful to readers of the code. The existence of the property feature makes it *possible* to define conventions -- it doesn't define a convention itself. -Steve
Jan 29 2010
prev sibling next sibling parent Bill Baxter <wbaxter gmail.com> writes:
On Thu, Jan 28, 2010 at 2:27 PM, Andrei Alexandrescu
<SeeWebsiteForEmail erdani.org> wrote:
 Bill Baxter wrote:
 On Thu, Jan 28, 2010 at 2:11 PM, Andrei Alexandrescu
 <SeeWebsiteForEmail erdani.org> wrote:
 Michiel Helvensteijn wrote:
 Bill Baxter wrote:

 byLine() is a function. It changes the state of stdin. Calling it
 consecutively will in general result in different return values. If
 there
 were two guys: stdin.currentLine (property) and stdin.nextLine(), it
 would be a different story.

That's not how it works, I think. Just calling byLine() by itself only returns a range struct. Consuming things from that range is what changes the state of stdin.

Ah, my bad. I was guessing. Still, returning a handle from a property that can change the state of the originating object is.. iffy.

I agree. So where's the consensus? Things seemed so clear when people were beaten with property over their head.

I really don't see what the problem is there. You are arguing that car.wheels should not be a property simply because it would let me change the color of the wheels (which are part of the car's total state)?

The problem is not localized change. The result of stdin.byLine changes the _entire_ stdin.

Ok, so you have no problem with a car.wheels returning a mutable wheels object? So it's only when the returned property can change the entire state (or a lot of the state?) that you have a problem? I don't understand how degree changes the acceptability. Doesn't seem like it should matter to me. --bb
Jan 28 2010
prev sibling next sibling parent Bill Baxter <wbaxter gmail.com> writes:
On Thu, Jan 28, 2010 at 2:48 PM, Andrei Alexandrescu
<SeeWebsiteForEmail erdani.org> wrote:
 Bill Baxter wrote:
 On Thu, Jan 28, 2010 at 2:25 PM, Andrei Alexandrescu
 <SeeWebsiteForEmail erdani.org> wrote:
 Bill Baxter wrote:
 On Thu, Jan 28, 2010 at 2:07 PM, Andrei Alexandrescu
 <SeeWebsiteForEmail erdani.org> wrote:
 Bill Baxter wrote:
 On Thu, Jan 28, 2010 at 1:26 PM, Andrei Alexandrescu
 <SeeWebsiteForEmail erdani.org> wrote:
 Steven Schveighoffer wrote:
 On Thu, 28 Jan 2010 15:59:30 -0500, Andrei Alexandrescu
 <SeeWebsiteForEmail erdani.org> wrote:
 foreach (line; stdin.byLine()) { ... }

 vs.

 foreach (line; stdin.byLine) { ... }

 How do I choose?

byLine is a property. =A0It is fetching a range on stdin. -Steve

Damn. I was sure the answer will be different.

Maybe "property" is a misleading word. =A0Clearly there are more thi=






 to which that applies than just what the traditional definition of t=






 word would imply. =A0I would not in English call my nose a "property=






 me, but if I were a D object and had a .nose accessor, I would
 certainly think that accessor would qualify as a D property.

 How's this: anything that you can "get" without specifying additiona=






 information (and which doesn't change the outwardly visible state th=






 object when you do so) is a property. =A0 The C# syntax with the spe=






 use of "get" and "set" perhaps does a better job of conveying this.

This raises the hair on my back. It's back to programming-by-convention.

Wait, you started off by saying "how do I decide?" and we give you a rule you can follow to decide and now you say you don't like it because it's programming-by-convention? =A0 I guess I don't really understand what your argument is.

It's not a rule. It's several contradictory ones.

Please point out the contradictions. =A0I'm not seeing them.

Some said it should be stdin.byLine(), some others said it should be stdin.byLine. They invoked contradictory rules that led to contradictory conclusions.

Ok, I thought you were saying my rule was somehow self-contradictory. I understand what you mean now. Just that the rule to apply is not obvious. But I think that applies to many things in computer programming. Whether to use pointers or references. Whether to use classes or struct. Whether to make something private or protected, or virtual or non-virtual. Some cases are obvious, others are not. --bb
Jan 28 2010
prev sibling next sibling parent "Steven Schveighoffer" <schveiguy yahoo.com> writes:
On Fri, 29 Jan 2010 11:21:28 -0500, Andrei Alexandrescu  
<SeeWebsiteForEmail erdani.org> wrote:

 How is f.byLine clearer and less ambiguous than f.byLine()? Or vice  
 versa for that matter?

Note that properties can be named things other than byLine. -Steve
Jan 29 2010
prev sibling next sibling parent "Steven Schveighoffer" <schveiguy yahoo.com> writes:
On Fri, 29 Jan 2010 11:33:17 -0500, Michel Fortin  
<michel.fortin michelf.com> wrote:

 On 2010-01-29 11:18:46 -0500, Andrei Alexandrescu  
 <SeeWebsiteForEmail erdani.org> said:

 It should work for stream ranges if front() checks the "filled" flag  
 and eats the next line if false, and popFront clears the "filled" flag.

So now you want the front to fetch from stdin on the first call? It's the same problem as 'byLine' eating the first line when you create it: neither one or the other should affect the stream.

No, you're reaching here :) What Andrei is doing is acknowledging that front has already performed the job of popFront. Because of the nature of streams, you cannot get the data from the stream, and leave it on the stream at the same time. It's just not feasible. What the solution Andrei came up with does is to make stream ranges behave as close as possible to forward ranges. That small inconsistency will not hurt you because most of the time you are not calling front for an element you don't intend to use. And even within that paradigm, you are even less likely to use the stream in another capacity. In other words, as the last usage of a range in an algorithm function, this: r.front; r.popFront(); is way more likely than: r.popFront() r.front; -Steve
Jan 29 2010
prev sibling parent torhu <no spam.invalid> writes:
On 28.01.2010 21:59, Andrei Alexandrescu wrote:
 How about this:

 foreach (line; stdin.byLine()) { ... }

 vs.

 foreach (line; stdin.byLine) { ... }

 How do I choose?

I'd say byLine as it's currently implemented in std.stdio is not a property. It initializes and returns a new ByLine struct each time it's called. It even has arguments that enables you to configure its return value differently each time you call it. Nowhere near how it would behave if it was a field. A property should at least return the same value if you call it several times in a row, without doing anything in between that you'd expect to alter the value. The fact that using byLine's return value changes the File itself doesn't change anything. That's a separate issue. Even if byLine was a field, using it would alter the underlying File.
Jan 30 2010
prev sibling next sibling parent Bill Baxter <wbaxter gmail.com> writes:
On Thu, Jan 28, 2010 at 2:11 PM, Andrei Alexandrescu
<SeeWebsiteForEmail erdani.org> wrote:
 Michiel Helvensteijn wrote:
 Bill Baxter wrote:

 byLine() is a function. It changes the state of stdin. Calling it
 consecutively will in general result in different return values. If
 there
 were two guys: stdin.currentLine (property) and stdin.nextLine(), it
 would be a different story.

That's not how it works, I think. Just calling byLine() by itself only returns a range struct. Consuming things from that range is what changes the state of stdin.

Ah, my bad. I was guessing. Still, returning a handle from a property that can change the state of the originating object is.. iffy.

I agree. So where's the consensus? Things seemed so clear when people were beaten with property over their head.

I really don't see what the problem is there. You are arguing that car.wheels should not be a property simply because it would let me change the color of the wheels (which are part of the car's total state)? --bb
Jan 28 2010
prev sibling next sibling parent Bill Baxter <wbaxter gmail.com> writes:
On Thu, Jan 28, 2010 at 2:25 PM, Andrei Alexandrescu
<SeeWebsiteForEmail erdani.org> wrote:
 Bill Baxter wrote:
 On Thu, Jan 28, 2010 at 2:07 PM, Andrei Alexandrescu
 <SeeWebsiteForEmail erdani.org> wrote:
 Bill Baxter wrote:
 On Thu, Jan 28, 2010 at 1:26 PM, Andrei Alexandrescu
 <SeeWebsiteForEmail erdani.org> wrote:
 Steven Schveighoffer wrote:
 On Thu, 28 Jan 2010 15:59:30 -0500, Andrei Alexandrescu
 <SeeWebsiteForEmail erdani.org> wrote:
 foreach (line; stdin.byLine()) { ... }

 vs.

 foreach (line; stdin.byLine) { ... }

 How do I choose?

byLine is a property. =A0It is fetching a range on stdin. -Steve

Damn. I was sure the answer will be different.

Maybe "property" is a misleading word. =A0Clearly there are more thing=




 to which that applies than just what the traditional definition of the
 word would imply. =A0I would not in English call my nose a "property" =




 me, but if I were a D object and had a .nose accessor, I would
 certainly think that accessor would qualify as a D property.

 How's this: anything that you can "get" without specifying additional
 information (and which doesn't change the outwardly visible state the
 object when you do so) is a property. =A0 The C# syntax with the speci=




 use of "get" and "set" perhaps does a better job of conveying this.

This raises the hair on my back. It's back to programming-by-convention=



 Wait, you started off by saying "how do I decide?" and we give you a
 rule you can follow to decide and now you say you don't like it
 because it's programming-by-convention? =A0 I guess I don't really
 understand what your argument is.

It's not a rule. It's several contradictory ones.

Please point out the contradictions. I'm not seeing them. --bb
Jan 28 2010
prev sibling parent "Steven Schveighoffer" <schveiguy yahoo.com> writes:
On Fri, 29 Jan 2010 11:17:04 -0500, Andrei Alexandrescu  
<SeeWebsiteForEmail erdani.org> wrote:

 Steven Schveighoffer wrote:
 On Fri, 29 Jan 2010 10:40:23 -0500, Andrei Alexandrescu  
 <SeeWebsiteForEmail erdani.org> wrote:

 Michel Fortin wrote:
 On 2010-01-29 08:18:46 -0500, "Steven Schveighoffer"  
 <schveiguy yahoo.com> said:

 Hey, it's that dead horse again, let's beat it!

 Andrei and I and several others discussed this ad infinitum.  You  
 will  never convince Andrei that his design is wrong :)

'byLine' is a property in the first place. I'm just explaining why it is, and what should be done. I'm starting to think Anrei likes ambiguous semantics. :-)

I'll tell you what I'd have liked: a landslide of responses to my question revealing my mistaken ways and clarifying without a shade of a doubt that byLine should be a property. Or not. (I don't even care which.)

many areas of programming. Deciding what is a property and what is not is no different.

Except it has no reward associated with it.

Clarity. Disambiguation. All the rewards that come from other naming conventions. Sorry you don't see it that way. -Steve
Jan 29 2010
prev sibling parent Bill Baxter <wbaxter gmail.com> writes:
On Thu, Jan 28, 2010 at 1:26 PM, Andrei Alexandrescu
<SeeWebsiteForEmail erdani.org> wrote:
 Steven Schveighoffer wrote:
 On Thu, 28 Jan 2010 15:59:30 -0500, Andrei Alexandrescu
 <SeeWebsiteForEmail erdani.org> wrote:
 foreach (line; stdin.byLine()) { ... }

 vs.

 foreach (line; stdin.byLine) { ... }

 How do I choose?

byLine is a property. =A0It is fetching a range on stdin. -Steve

Damn. I was sure the answer will be different.

Maybe "property" is a misleading word. Clearly there are more things to which that applies than just what the traditional definition of the word would imply. I would not in English call my nose a "property" of me, but if I were a D object and had a .nose accessor, I would certainly think that accessor would qualify as a D property. How's this: anything that you can "get" without specifying additional information (and which doesn't change the outwardly visible state the object when you do so) is a property. The C# syntax with the special use of "get" and "set" perhaps does a better job of conveying this. --bb
Jan 28 2010
prev sibling next sibling parent "Denis Koroskin" <2korden gmail.com> writes:
On Wed, 27 Jan 2010 23:50:26 +0300, Nick Sabalausky <a a.a> wrote:

 "downs" <default_357-line yahoo.de> wrote in message
 news:hjq2l1$1s5j$1 digitalmars.com...
 Adam D. Ruppe wrote:
 On Wed, Jan 27, 2010 at 06:34:57PM +0100, Pelle M=C3=A5nsson wrote:
 I disagree, I find the function calls without the () to be really
 prettifying.

 But maybe that's just me.

 I don't think that it causes serious bugs, you would see that it's =




 integer the moment you try and use it. It also helps changing code
 from/to functions.

 I really like this feature, and would miss it should it go away.

Me too.

Me three.

Meh, I hate it hate it hate it hate it hate it. I'd dance on the =

 feature's
 grave.

 So I guess you could say I wouldn't miss it. ;)

Me too!
Jan 27 2010
prev sibling next sibling parent "Steven Schveighoffer" <schveiguy yahoo.com> writes:
On Wed, 27 Jan 2010 15:54:42 -0500, Andrei Alexandrescu  
<SeeWebsiteForEmail erdani.org> wrote:

 downs wrote:
 Adam D. Ruppe wrote:
 On Wed, Jan 27, 2010 at 06:34:57PM +0100, Pelle MÃ¥nsson wrote:
 I disagree, I find the function calls without the () to be really  
 prettifying.

 But maybe that's just me.

 I don't think that it causes serious bugs, you would see that it's an  
 integer the moment you try and use it. It also helps changing code  
 from/to functions.

 I really like this feature, and would miss it should it go away.



There was a long discussion about that, which prompted the addition of property. I was in the anti- property camp, but had understanding and sympathy for the ambiguity issues involved without property. There was a vote in which as far as I recall the pro- property camp was beaten to a tender pulp. Now property is in. That has created (as I had anticipated) the unresolved issue of choosing between property or just function for any given parameterless function. Also I need to litter my code with property. To this day I am not sure whether we made the right decision.

1. Choosing between including property or not is rare. Most cases are obvious. If you worked with a language that requires property notation (i.e. C#) this would not be as big an issue for you. 2. Defining property on functions you wish to call as properties can be done all at once, enclosing all properties in a property { } block. No need to "litter" all your code with that. Furthermore, function signature 'documentation' is not as littering as you think. Verbosity at definition is not as cumbersome as verbosity at the call site. In other words, the extra litter at definition time pays huge dividends in clarity at the call site, and is not a constant annoyance (you only define things once). I'm sure C developers who were used to omitting prototypes were equally miffed when it became required. -Steve
Jan 28 2010
prev sibling next sibling parent retard <re tard.com.invalid> writes:
Wed, 27 Jan 2010 18:34:57 +0100, Pelle MÃ¥nsson wrote:

 I disagree, I find the function calls without the () to be really
 prettifying.
 
 But maybe that's just me.
 
 I don't think that it causes serious bugs, you would see that it's an
 integer the moment you try and use it. It also helps changing code
 from/to functions.
 
 I really like this feature, and would miss it should it go away.

I just can't understand why implementing the optional ()s can be so hard. Scala does it and as far as I know, the solution doesn't have any problems. They also solved the property issues. In scala property methods have special names to distinguish them. object foo { def prop = 42; def prop_=(a: Int) = println(a) } defined module foo scala> foo.prop = 42 42 scala> object foo { def prop = 42; def prop_=(a: Int) = println(a) } defined module foo scala> foo.prop res12: Int = 42 scala> foo.prop() <console>:6: error: foo.prop of type Int does not take parameters foo.prop() ^ scala> foo.prop = 42 42 scala> foo.prop(42) <console>:6: error: foo.prop of type Int does not take parameters foo.prop(42) ^ scala> foo.prop_(42) <console>:6: error: value prop_ is not a member of object foo foo.prop_(42) ^ scala> foo.prop_=(42) 42 scala> foo.prop += 1 43
Jan 28 2010
prev sibling next sibling parent "Steven Schveighoffer" <schveiguy yahoo.com> writes:
On Thu, 28 Jan 2010 08:57:15 -0500, Andrei Alexandrescu  
<SeeWebsiteForEmail erdani.org> wrote:

 Steven Schveighoffer wrote:
 1. Choosing between including  property or not is rare.  Most cases are  
 obvious.  If you worked with a language that requires property notation  
 (i.e. C#) this would not be as big an issue for you.

I need to put it for all front() and empty() declarations. By the way I decided that popFront() is not a property. I don't know why.

Because popFront isn't a property. It doesn't return anything, does it? A property either fetches a value or sets a value. Defining anything else as a property is disingenuous, and that was the original problem -- you could make it look like you were accessing a property when you really aren't. popFront should not be a property and should always have parentheses after it.
 2. Defining  property on functions you wish to call as properties can  
 be done all at once, enclosing all properties in a  property { }  
 block.  No need to "litter" all your code with that.  Furthermore,  
 function signature 'documentation' is not as littering as you think.   
 Verbosity at definition is not as cumbersome as verbosity at the call  
 site.  In other words, the extra litter at definition time pays huge  
 dividends in clarity at the call site, and is not a constant annoyance  
 (you only define things once).

OK. The problem is, I was already enjoying clarity at the call site. So for me the whole property thing has a much less appeal than it might. I do appreciate that property eliminates ambiguities in corner cases.

You are governed by your personal restrictions and taste. The problem is that left to their own devices, people will use their own style of calling functions. Some will always use parentheses even when the function is supposed to be a property, others will always avoid parentheses when they can, yet others will be somewhere in between. The end result is you have code that is not intuitive to you if the author doesn't follow your style. At least with a property requirement, there is only one style.
 I'm sure C developers who were used to omitting prototypes were equally  
 miffed when it became required.

That situation is different. There's only one possible prototype a function can have. With property, it's anyone's guess.

the similarity is that an optional specification became required because it was confusing when you went to use the function how to call it. I agree the similarity is not 1 to 1, but what I meant to point out is that people who started with ANSI C (myself included) never missed that feature. Only those who used the feature would be upset. Likewise, I started using properties when I learned C# way before I learned D. I would never miss the optional-parens style of a function that's not a property because I never really got used to doing it. So do you miss it because it had true benefits or because you're just used to doing it that way? -Steve
Jan 28 2010
prev sibling next sibling parent "Adam D. Ruppe" <destructionator gmail.com> writes:
On Thu, Jan 28, 2010 at 11:47:45AM -0300, Leandro Lucarella wrote:
 Andrei Alexandrescu, el 28 de enero a las 07:57 me escribiste:
 I need to put it for all front() and empty() declarations. By the
 way I decided that popFront() is not a property. I don't know why.

Because it denotes an action?

I don't think it is that simple - I see popFront; as an action all the same as popFront(); I wonder if there is some correlation between old assembly programmers and newer language users on this issue. In assembly, there's no distinction; you write all instructions and many macros without parens, so it is no weird thing. -- Adam D. Ruppe http://arsdnet.net
Jan 28 2010
prev sibling next sibling parent "Steven Schveighoffer" <schveiguy yahoo.com> writes:
On Thu, 28 Jan 2010 10:22:45 -0500, Adam D. Ruppe  
<destructionator gmail.com> wrote:

 On Thu, Jan 28, 2010 at 11:47:45AM -0300, Leandro Lucarella wrote:
 Andrei Alexandrescu, el 28 de enero a las 07:57 me escribiste:
 I need to put it for all front() and empty() declarations. By the
 way I decided that popFront() is not a property. I don't know why.

Because it denotes an action?

I don't think it is that simple - I see popFront; as an action all the same as popFront();

Whether you use parentheses or not, it's not a property. The statement of Andrei is that he doesn't know why it's not a property. The simple reason is because it's an action. Now, does popFront; look like an action? Yes. But that is not the case being disambiguated. It is collateral damage. Because the compiler doesn't understand English, it can't know whether to disallow popFront; any more than an ambiguous term like read;. If there were a way to enforce "only terms that are clearly denote actions can be called without parentheses," I'd be all for it. -Steve
Jan 28 2010
prev sibling next sibling parent reply "Denis Koroskin" <2korden gmail.com> writes:
On Thu, 28 Jan 2010 20:28:17 +0300, Lars T. Kyllingstad  
<public kyllingen.nospamnet> wrote:

 Steven Schveighoffer wrote:
 On Thu, 28 Jan 2010 10:22:45 -0500, Adam D. Ruppe  
 <destructionator gmail.com> wrote:

 On Thu, Jan 28, 2010 at 11:47:45AM -0300, Leandro Lucarella wrote:
 Andrei Alexandrescu, el 28 de enero a las 07:57 me escribiste:
 I need to put it for all front() and empty() declarations. By the
 way I decided that popFront() is not a property. I don't know why.

Because it denotes an action?

I don't think it is that simple - I see popFront; as an action all the same as popFront();

statement of Andrei is that he doesn't know why it's not a property. The simple reason is because it's an action. Now, does popFront; look like an action? Yes. But that is not the case being disambiguated. It is collateral damage. Because the compiler doesn't understand English, it can't know whether to disallow popFront; any more than an ambiguous term like read

...or, as in Andrei's example, 'empty'. In Java you'd write isEmpty(), or even worse, getEmpty(). In D we now have the option of declaring it a property, with little chance of people thinking it actually empties anything. -Lars

Great explanation, very convincing!
Jan 28 2010
next sibling parent "Steven Schveighoffer" <schveiguy yahoo.com> writes:
On Fri, 29 Jan 2010 11:08:37 -0500, Michel Fortin  
<michel.fortin michelf.com> wrote:

 On 2010-01-29 11:00:31 -0500, "Steven Schveighoffer"  
 <schveiguy yahoo.com> said:

 On Fri, 29 Jan 2010 10:53:50 -0500, Michel Fortin   
 <michel.fortin michelf.com> wrote:

 On 2010-01-29 10:49:34 -0500, "Steven Schveighoffer"   
 <schveiguy yahoo.com> said:

 ugh... much simpler with a true stream-like range that supports what  
 is   natural for streams:
  for(int i = 0; i < count && !range.empty; i++) {
     elements ~= range.get();
 }
  But of course, then this function doesn't work for other range  
 types.   I  decided in that discussion long ago that stream ranges  
 were going to  suck.

E take(R, E)(ref R range) { E element = range.front; range.popFront(); return element; } This will work for any forward range.


Hum, well I used 'take' while you defined 'get' as the basic function for stream ranges. They're the same thing. Rename 'take' for 'get', or the reverse, and all input ranges can work with the same 'get' or 'take' function. (Note: I use 'take' instead of 'get' because it seems clearer to me that it also removes the element from the range.)

Oh, I get it now. Yes, you can define this (BTW, I agree take is better than get). Whether we will ever get x.fn() => fn(x) for ranges remains to be seen. Without that, you have boilerplate code in every forward range and beyond. The other possibility is to define an abstraction function like: E take(R, E)(ref R range) { static if(isForwardRange!(R)) { // repeat your code above } else return range.take(); } and then use take(r) whenever you need that capability. -Steve
Jan 29 2010
prev sibling parent "Steven Schveighoffer" <schveiguy yahoo.com> writes:
On Fri, 29 Jan 2010 11:18:46 -0500, Andrei Alexandrescu  
<SeeWebsiteForEmail erdani.org> wrote:

 Steven Schveighoffer wrote:
 On Fri, 29 Jan 2010 10:53:50 -0500, Michel Fortin  
 <michel.fortin michelf.com> wrote:

 On 2010-01-29 10:49:34 -0500, "Steven Schveighoffer"  
 <schveiguy yahoo.com> said:

 ugh... much simpler with a true stream-like range that supports what  
 is  natural for streams:
  for(int i = 0; i < count && !range.empty; i++) {
     elements ~= range.get();
 }
  But of course, then this function doesn't work for other range  
 types.  I  decided in that discussion long ago that stream ranges  
 were going to suck.

You can always define a generic take() like this: E take(R, E)(ref R range) { E element = range.front; range.popFront(); return element; } This will work for any forward range.


It should work for stream ranges if front() checks the "filled" flag and eats the next line if false, and popFront clears the "filled" flag.

That actually makes a lot of sense. I hope this fix goes in. -Steve
Jan 29 2010
prev sibling parent "Steven Schveighoffer" <schveiguy yahoo.com> writes:
On Thu, 28 Jan 2010 15:59:30 -0500, Andrei Alexandrescu  
<SeeWebsiteForEmail erdani.org> wrote:

 Denis Koroskin wrote:
 On Thu, 28 Jan 2010 20:28:17 +0300, Lars T. Kyllingstad  
 <public kyllingen.nospamnet> wrote:

 Steven Schveighoffer wrote:
 On Thu, 28 Jan 2010 10:22:45 -0500, Adam D. Ruppe  
 <destructionator gmail.com> wrote:

 On Thu, Jan 28, 2010 at 11:47:45AM -0300, Leandro Lucarella wrote:
 Andrei Alexandrescu, el 28 de enero a las 07:57 me escribiste:
 I need to put it for all front() and empty() declarations. By the
 way I decided that popFront() is not a property. I don't know why.

Because it denotes an action?

I don't think it is that simple - I see popFront; as an action all the same as popFront();

statement of Andrei is that he doesn't know why it's not a property. The simple reason is because it's an action. Now, does popFront; look like an action? Yes. But that is not the case being disambiguated. It is collateral damage. Because the compiler doesn't understand English, it can't know whether to disallow popFront; any more than an ambiguous term like read

...or, as in Andrei's example, 'empty'. In Java you'd write isEmpty(), or even worse, getEmpty(). In D we now have the option of declaring it a property, with little chance of people thinking it actually empties anything. -Lars


How about this: foreach (line; stdin.byLine()) { ... } vs. foreach (line; stdin.byLine) { ... } How do I choose?

byLine is a property. It is fetching a range on stdin. -Steve
Jan 28 2010
prev sibling next sibling parent Leandro Lucarella <llucax gmail.com> writes:
Andrei Alexandrescu, el 28 de enero a las 07:57 me escribiste:
 Steven Schveighoffer wrote:
1. Choosing between including  property or not is rare.  Most
cases are obvious.  If you worked with a language that requires
property notation (i.e. C#) this would not be as big an issue for
you.

I need to put it for all front() and empty() declarations. By the way I decided that popFront() is not a property. I don't know why.

Because it denotes an action? -- Leandro Lucarella (AKA luca) http://llucax.com.ar/ ---------------------------------------------------------------------- GPG Key: 5F5A8D05 (F8CD F9A7 BF00 5431 4145 104C 949E BFB6 5F5A 8D05) ----------------------------------------------------------------------
Jan 28 2010
prev sibling next sibling parent Bill Baxter <wbaxter gmail.com> writes:
On Thu, Jan 28, 2010 at 1:55 PM, Michiel Helvensteijn
<m.helvensteijn.remove gmail.com> wrote:
 Andrei Alexandrescu wrote:

 foreach (line; stdin.byLine()) { ... }

 vs.

 foreach (line; stdin.byLine) { ... }

 How do I choose?

byLine is a property. =A0It is fetching a range on stdin. -Steve

Damn. I was sure the answer will be different.

byLine() is a function. It changes the state of stdin. Calling it consecutively will in general result in different return values. If there were two guys: stdin.currentLine (property) and stdin.nextLine(), it woul=

 be a different story.

That's not how it works, I think. Just calling byLine() by itself only returns a range struct. Consuming things from that range is what changes the state of stdin. --bb
Jan 28 2010
prev sibling next sibling parent Bill Baxter <wbaxter gmail.com> writes:
On Thu, Jan 28, 2010 at 2:07 PM, Andrei Alexandrescu
<SeeWebsiteForEmail erdani.org> wrote:
 Bill Baxter wrote:
 On Thu, Jan 28, 2010 at 1:26 PM, Andrei Alexandrescu
 <SeeWebsiteForEmail erdani.org> wrote:
 Steven Schveighoffer wrote:
 On Thu, 28 Jan 2010 15:59:30 -0500, Andrei Alexandrescu
 <SeeWebsiteForEmail erdani.org> wrote:
 foreach (line; stdin.byLine()) { ... }

 vs.

 foreach (line; stdin.byLine) { ... }

 How do I choose?

byLine is a property. =A0It is fetching a range on stdin. -Steve

Damn. I was sure the answer will be different.

Maybe "property" is a misleading word. =A0Clearly there are more things to which that applies than just what the traditional definition of the word would imply. =A0I would not in English call my nose a "property" of me, but if I were a D object and had a .nose accessor, I would certainly think that accessor would qualify as a D property. How's this: anything that you can "get" without specifying additional information (and which doesn't change the outwardly visible state the object when you do so) is a property. =A0 The C# syntax with the special use of "get" and "set" perhaps does a better job of conveying this.

This raises the hair on my back. It's back to programming-by-convention.

Wait, you started off by saying "how do I decide?" and we give you a rule you can follow to decide and now you say you don't like it because it's programming-by-convention? I guess I don't really understand what your argument is. --bb
Jan 28 2010
prev sibling next sibling parent Bill Baxter <wbaxter gmail.com> writes:
On Thu, Jan 28, 2010 at 2:49 PM, Andrei Alexandrescu
<SeeWebsiteForEmail erdani.org> wrote:
 Pelle M=E5nsson wrote:
 On 01/28/2010 11:23 PM, Michiel Helvensteijn wrote:
 Andrei Alexandrescu wrote:

 I agree. So where's the consensus? Things seemed so clear when people
 were beaten with  property over their head.

If I read the TLP correctly, property seems not to be working correctl=



  property (or any other notation marking property getters/setters) shou=



 be
 enforced. Functions that have it must only be invoked using property
 syntax. Functions that don't have it must be called with parentheses.
 That's the whole point. To give the designer of the class control over
 how
 it is used.

 The problem is people blurring the line between what's supposed to be a
 function and what's supposed to be a property, by abusing property synt=



 to invoke actions without parentheses.

 In reality, I believe there's not only a clear line between the two
 intentions, there's a demilitarized zone. You just need to enforce it.
 You
 can't have your cake and eat it too.

I don't understand what any of this would improve. Is the byLine example less readable without the ()? Is it more bug prone? The only thing achieved as I can see is that every class designer makes =


 his own rules about which functions are property and which are not. If t=


 is somehow enforced, it will become a guessing game about how to call
 no-argument functions. For what?


The "what" is the things listed in DIP4 (http://www.prowiki.org/wiki4d/wiki.cgi?LanguageDevel/DIPs/DIP4) Particularly these issues: int delegate() foo() { return delegate int(){ return 5; }; } // Is this an int or a delegate? auto x =3D foo(); // Is this a reference to foo, or a reference to the delegate returned by f= oo? auto y =3D &foo; --bb
Jan 28 2010
prev sibling next sibling parent "Steven Schveighoffer" <schveiguy yahoo.com> writes:
On Fri, 29 Jan 2010 08:03:13 -0500, Michel Fortin  
<michel.fortin michelf.com> wrote:

 On 2010-01-29 06:25:44 -0500, Pelle MÃ¥nsson <pelle.mansson gmail.com>  
 said:

 On 01/29/2010 05:48 AM, Michel Fortin wrote:
  No. Calling byLine doesn't change the stream. It returns a different
 view of stdin, which can be used to modify the stream, or not. I think
 it should be a property. If it was 'getNextLine' then it should be a
 function. As a proof, this doesn't have any effect:
  stdin.byLine;


Ah, I see, you're right. Silly me for not trying. So it's not an accessor after all. The problem is that, even disregarding the property syntax, the name strongly suggests it's an accessor, but it has side effects, which it shouldn't. Either we change the name to something else, like 'consumeLines()', or we make it behave like an accessor. I'd go for the second option. The basic problem lies in the very basic definition of an input range. Due to its interface (popFront + front), an input range is forced to consume the its first element by its mere existence. I think constructing an input range shouldn't have side effects. It should be more symmetrical with an output range. It could have just one function, 'take' to get the next element, and now byLine could work correctly.

Hey, it's that dead horse again, let's beat it! Andrei and I and several others discussed this ad infinitum. You will never convince Andrei that his design is wrong :) The truth is, the fact that byLine modifies stdin by its mere existence proves to be inconsequential. Nobody will fetch the byLine property without using it. It's still an accessor. -Steve
Jan 29 2010
prev sibling next sibling parent "Steven Schveighoffer" <schveiguy yahoo.com> writes:
On Thu, 28 Jan 2010 17:54:33 -0500, Pelle MÃ¥nsson  
<pelle.mansson gmail.com> wrote:

 On 01/28/2010 11:23 PM, Michiel Helvensteijn wrote:
 Andrei Alexandrescu wrote:

 I agree. So where's the consensus? Things seemed so clear when people
 were beaten with  property over their head.

If I read the TLP correctly, property seems not to be working correctly. property (or any other notation marking property getters/setters) should be enforced. Functions that have it must only be invoked using property syntax. Functions that don't have it must be called with parentheses. That's the whole point. To give the designer of the class control over how it is used. The problem is people blurring the line between what's supposed to be a function and what's supposed to be a property, by abusing property syntax to invoke actions without parentheses. In reality, I believe there's not only a clear line between the two intentions, there's a demilitarized zone. You just need to enforce it. You can't have your cake and eat it too.

I don't understand what any of this would improve. Is the byLine example less readable without the ()? Is it more bug prone? The only thing achieved as I can see is that every class designer makes up his own rules about which functions are property and which are not. If this is somehow enforced, it will become a guessing game about how to call no-argument functions. For what?

Just as every class designer makes up his own rules about naming functions. The parentheses are part of the name of a function. Whether in your view the parentheses have meaning or not is your opinion. But you should not be able to attach your own meaning to my functions. What if we allowed a feature where you could call functions with just an unambiguous prefix? so something like: stdin.by(); Is that ok with you? It's not unambiguous, is it just as easy to understand as using the full name? The fact that byLine is just as descriptive as byLine() makes no difference. It is not a quintessential example of ambiguity. It should be a property IMO because of what it does, but even if it's not, it's not ambiguous. There are other cases which are ambiguous. -Steve
Jan 29 2010
prev sibling next sibling parent "Steven Schveighoffer" <schveiguy yahoo.com> writes:
On Fri, 29 Jan 2010 09:34:25 -0500, Michel Fortin  
<michel.fortin michelf.com> wrote:

 On 2010-01-29 08:18:46 -0500, "Steven Schveighoffer"  
 <schveiguy yahoo.com> said:

 Hey, it's that dead horse again, let's beat it!
  Andrei and I and several others discussed this ad infinitum.  You  
 will  never convince Andrei that his design is wrong :)

Andrei is the one who complained that it's difficult to know whether 'byLine' is a property in the first place. I'm just explaining why it is, and what should be done.

I agree.
 I'm starting to think Anrei likes ambiguous semantics.  :-)


 The truth is, the fact that byLine modifies stdin by its mere existence  
  proves to be inconsequential.  Nobody will fetch the byLine property   
 without using it.  It's still an accessor.

That's only true if you use byLine exclusively. Here is a case where the advance fetching of byLine could go wrong: // fetch 3 lines: string[] consume(3, stdin.byLine); // now fill a buffer ubyte[] buffer; buffer = stdin.rawRead(buffer); E[] consume(E, R)(int count, R range) { E[] elements; foreach (i; 0..count) { elements ~= range.front; range.popFront(); } return elements; } The problem here is that the consume() function will in reality consume 4 lines of stdin, even though it just take 3 from byLine. When we later call rawRead, a line has been lost.

Yeah, I am on your side. byLine has some nuances that make it incompatible with other uses of the stream. In fact, byLine might only be useful in processing the entire file. Hm... opApply? -Steve
Jan 29 2010
prev sibling next sibling parent "Steven Schveighoffer" <schveiguy yahoo.com> writes:
On Fri, 29 Jan 2010 10:31:28 -0500, Andrei Alexandrescu
<SeeWebsiteForEmail erdani.org> wrote:

 Steven Schveighoffer wrote:
 On Fri, 29 Jan 2010 08:03:13 -0500, Michel Fortin  
 <michel.fortin michelf.com> wrote:

 On 2010-01-29 06:25:44 -0500, Pelle MÃ¥nsson <pelle.mansson gmail.com>  
 said:

 On 01/29/2010 05:48 AM, Michel Fortin wrote:
  No. Calling byLine doesn't change the stream. It returns a different
 view of stdin, which can be used to modify the stream, or not. I  
 think
 it should be a property. If it was 'getNextLine' then it should be a
 function. As a proof, this doesn't have any effect:
  stdin.byLine;


Ah, I see, you're right. Silly me for not trying. So it's not an accessor after all. The problem is that, even disregarding the property syntax, the name strongly suggests it's an accessor, but it has side effects, which it shouldn't. Either we change the name to something else, like 'consumeLines()', or we make it behave like an accessor. I'd go for the second option. The basic problem lies in the very basic definition of an input range. Due to its interface (popFront + front), an input range is forced to consume the its first element by its mere existence. I think constructing an input range shouldn't have side effects. It should be more symmetrical with an output range. It could have just one function, 'take' to get the next element, and now byLine could work correctly.

Andrei and I and several others discussed this ad infinitum. You will never convince Andrei that his design is wrong :)

Which debate are you referring to?

hm... let me dig it up. (unwillingly) http://www.digitalmars.com/webnews/newsgroups.php?art_group=digitalmars.D&article_id=90971
 The truth is, the fact that byLine modifies stdin by its mere existence  
 proves to be inconsequential.  Nobody will fetch the byLine property  
 without using it.  It's still an accessor.

Yah, though I agree it's nicer to not prime the line in the constructor.

This would help, but you still have to be careful with streamed ranges. The valid point Michael brought up is the following: // fetch 3 lines: string[] consume(3, stdin.byLine); // now fill a buffer ubyte[] buffer; buffer = stdin.rawRead(buffer); E[] consume(E, R)(int count, R range) { E[] elements; foreach (i; 0..count) { elements ~= range.front; range.popFront(); } return elements; } Note the extra popFront. So the loop must be rewritten: if (count != 0) // base case, need special case for this { int i = 0; while(!range.empty) // he forgot this condition { elements ~= range.front; if(++i == count) break; range.popFront(); } } ugh... much simpler with a true stream-like range that supports what is natural for streams: for(int i = 0; i < count && !range.empty; i++) { elements ~= range.get(); } But of course, then this function doesn't work for other range types. I decided in that discussion long ago that stream ranges were going to suck. -Steve
Jan 29 2010
prev sibling next sibling parent "Steven Schveighoffer" <schveiguy yahoo.com> writes:
On Fri, 29 Jan 2010 10:40:23 -0500, Andrei Alexandrescu  
<SeeWebsiteForEmail erdani.org> wrote:

 Michel Fortin wrote:
 On 2010-01-29 08:18:46 -0500, "Steven Schveighoffer"  
 <schveiguy yahoo.com> said:

 Hey, it's that dead horse again, let's beat it!

 Andrei and I and several others discussed this ad infinitum.  You  
 will  never convince Andrei that his design is wrong :)

'byLine' is a property in the first place. I'm just explaining why it is, and what should be done. I'm starting to think Anrei likes ambiguous semantics. :-)

I'll tell you what I'd have liked: a landslide of responses to my question revealing my mistaken ways and clarifying without a shade of a doubt that byLine should be a property. Or not. (I don't even care which.)

It's been mentioned before that tough decisions need to be made in many areas of programming. Deciding what is a property and what is not is no different. Using byLine as the strawman does not disprove the usefulness of properties.
 The fact we're having a debate about this (and Steve even says it's a  
 clear cut case and there are other more ambiguous!) is worrisome. Take  
 this: I got different answers from _supporters_ of  property!

Again, property cannot provide an intuitive solution for everything, just like ranges cannot solve everything.
 A good convention is one that you apply without wasting time to think of  
 it every single time you use it: naming conventions, braces conventions,  
 even most class vs. struct conventions. The well-defined ones work great  
 because _they save you time_. This  property stuff doesn't save anyone  
 time (the provider is aggravated and the client is aggravated too).  
 Honest, I think it's quite a misfeature. If there's a possibility to fix  
 the ambiguities of the old system, I'd kick  property into oblivion  
 today.

The only one you stated here that is on par with property is naming conventions. They don't save you time writing code, they save you time *reading* code. The work goes into the writing (how to name this properly? How to make the name intuitive?) and then when reading, it comes natural. Without property you lose part of that concept. The parentheses are an extension of the symbol name, defined by the author, nothing more. What this *means* is up to you. In fact, properties *are* an extension of naming conventions.
 We need digitalmars.D.is_it_a_property_or_not. Whenever in doubt, people  
 can ask a question there.

OK: digitalmars.d.should_this_be_a_class_or_struct. digitalmars.d.should_this_symbol_be_capitalized. digitalmars.d.should_this_use_a_function_pointer_or_delegate. digitalmars.d.should_this_be_const_or_immutable. Can we ever get any work done without these? -Steve
Jan 29 2010
prev sibling next sibling parent "Steven Schveighoffer" <schveiguy yahoo.com> writes:
On Fri, 29 Jan 2010 10:53:50 -0500, Michel Fortin  
<michel.fortin michelf.com> wrote:

 On 2010-01-29 10:49:34 -0500, "Steven Schveighoffer"  
 <schveiguy yahoo.com> said:

 ugh... much simpler with a true stream-like range that supports what is  
  natural for streams:
  for(int i = 0; i < count && !range.empty; i++) {
     elements ~= range.get();
 }
  But of course, then this function doesn't work for other range types.   
 I  decided in that discussion long ago that stream ranges were going to  
 suck.

You can always define a generic take() like this: E take(R, E)(ref R range) { E element = range.front; range.popFront(); return element; } This will work for any forward range.

Except stream ranges. I don't get it... -Steve
Jan 29 2010
prev sibling next sibling parent "Steven Schveighoffer" <schveiguy yahoo.com> writes:
On Fri, 29 Jan 2010 12:23:24 -0500, Andrei Alexandrescu  
<SeeWebsiteForEmail erdani.org> wrote:

 Steven Schveighoffer wrote:
 On Fri, 29 Jan 2010 11:29:22 -0500, Andrei Alexandrescu  
 <SeeWebsiteForEmail erdani.org> wrote:

 Steven Schveighoffer wrote:
 On Fri, 29 Jan 2010 11:21:28 -0500, Andrei Alexandrescu  
 <SeeWebsiteForEmail erdani.org> wrote:

 How is f.byLine clearer and less ambiguous than f.byLine()? Or vice  
 versa for that matter?

-Steve

What I meant to say is that in the property landscape the following two conventions become suddenly attractive: * Do not use property at all * Use property for all nullary functions And they're bound to save a lot of time to everyone involved.

to abuse. So all that is left is no-argument functions. There are other alternative conventions to what you stated. This is my convention: * use property where the main purpose of the function is to fetch a value (computed or not, modifying the container or not)

Consider: struct Stack(T) { T pop(); ... } By your definition, pop() should be a property. It doesn't quite strike me as an intuitive decision.

is pop's main purpose to fetch a value or to modify the stack? I'd say the purpose is split equally, so it's not a function whose main purpose is to fetch a value. I admit this is a good example where a judgement call comes into play, but we aren't all robots obeying every rule literally. There are sometimes exceptions in conventions, or at least the rule is subject to interpretation. -Steve
Jan 29 2010
prev sibling next sibling parent "Steven Schveighoffer" <schveiguy yahoo.com> writes:
On Fri, 29 Jan 2010 13:41:43 -0500, Michel Fortin  
<michel.fortin michelf.com> wrote:

 On 2010-01-29 12:56:43 -0500, Andrei Alexandrescu  
 <SeeWebsiteForEmail erdani.org> said:

 Steven Schveighoffer wrote:
 On Fri, 29 Jan 2010 12:23:24 -0500, Andrei Alexandrescu  
 <SeeWebsiteForEmail erdani.org> wrote:
 Consider:
  struct Stack(T) {
      T pop();
      ...
 }
  By your definition, pop() should be a property. It doesn't quite  
 strike me as an intuitive decision.

say the purpose is split equally, so it's not a function whose main purpose is to fetch a value.

made my point. I win.

You win because Steven's definition is not good enough. I said before that we should have a authoritative definition. If we really can't define how a property should be defined after some reflection, then you really win.

Be careful here, don't give Andrei hard criteria for declaring victory ;) But my larger point was that convention is convention, whether you use parentheses to designate what a function does, or the symbol name itself. Deciding the convention is liable to suit some and not others. Some people hate the flat terse names of Phobos' modules. Does that mean those people are wrong? Does that mean Walter and Andrei are wrong? The only thing that is wrong here is deciding there is exactly one right rigid way to designate what should and should not be a property. I think we should have a definition of property convention for Phobos, but I don't think it needs to be the *only* way people use properties in their own projects. In fact, it can't be because there is no english (or whatever language you use) interpreter in the compiler. -Steve
Jan 29 2010
prev sibling next sibling parent Bill Baxter <wbaxter gmail.com> writes:
On Fri, Jan 29, 2010 at 10:41 AM, Michel Fortin
<michel.fortin michelf.com> wrote:
 On 2010-01-29 12:56:43 -0500, Andrei Alexandrescu
 <SeeWebsiteForEmail erdani.org> said:

 Steven Schveighoffer wrote:
 On Fri, 29 Jan 2010 12:23:24 -0500, Andrei Alexandrescu
 <SeeWebsiteForEmail erdani.org> wrote:
 Consider:

 struct Stack(T) {
 =A0 =A0 T pop();
 =A0 =A0 ...
 }

 By your definition, pop() should be a property. It doesn't quite strik=




 me as an intuitive decision.

is pop's main purpose to fetch a value or to modify the stack? =A0I'd s=



 the purpose is split equally, so it's not a function whose main purpose=



 to fetch a value.

So now we're down to proportions, nuance, and where "main" goes. You mad=


 my point. I win.

You win because Steven's definition is not good enough. I said before tha=

 we should have a authoritative definition. If we really can't define how =

 property should be defined after some reflection, then you really win.

 My definition is that a property gives access to an aspect of an object a=

 doesn't modify it (the getter is essentially logical-const). In this case=

 'pop' doesn't give you access to something in the stack, it removes an
 element (that's an action) and give you the element. It's pretty clear th=

 'pop' is used as a verb here, that should be enough to decide it's a
 function.

One more example to consider: RNG.randomInt() or RNG.randomInt I think Steven is right that you can always find corner cases, but that the existence of corner cases is pretty irrelevant. --bb
Jan 29 2010
prev sibling parent Gerrit Wichert <gw green-stores.de> writes:
Content-Type: text/plain; charset=ISO-8859-1
Content-Transfer-Encoding: 7bit

Hello,

I think the biggest part of our problem with  property is, that we are
using the wrong words. I'm no native english speaker so it  may be that
i'm totaly wrong with this,  but that's my impression. When i hear the
word property i'm thinking: "ok, this is a well defined part of the
internal state of that object instance that i'm allowed to  interact
with". 

That's what i think a property is. It is not about parentheses or not
parentheses. It is not about just marking functions to change their call
behaviour.

I think a property should be about *first* naming and defining a
distinct part of the object state and thereafter *optionally* defining
how to deal with it.

I really  don't want to talk much about syntax  but  i like the  way 
Moose  has solved this problem for  Perl5.  Even if its syntax is not
compatible to a C derived language language like D (btw. why not?), a
quick skim of its documentation  may be a source of inspiration. It
clearly was for me.

http://search.cpan.org/~drolsky/Moose-0.94/lib/Moose.pm

The coolest thing about Moose is, that it doesn't  change the language
of Perl5 in any way. For attributes (their name for properties) it just
implements  a declarative syntax that is valid perl code and executed at
compile time to define fields and accessor functions.

so a simple
    has 'x' => (is => 'rw', isa => 'Int');
just defines a field that can hold an integer and two accessor functions
x() and x(int). The name of  the  real field and how it is stored is
adjustable but defaults to the way perl objects are normaly constructed.

    has 'x' => (is => 'ro', isa => 'Int');
just omits constructing a write accessor.

To be exact at this a readonly property doesn't mean it is const, it
means that you don't have a write accessor and therefore can't
substitute its content. You can get a mutable subobject or struct via a
read accesseor and manipulate it via its own property accessors but you
can't substitute it since you have no write accessor. If you don't want
to let the client manipulate intenal state via a read accessor of a
complex property just make it return a const subobject.   

Semantically this turns a property into a little sub-class even if it is
not defined as such. It is implemented as old school fields and accessor
functions. But they are auto generated until you feel the need to define
them explicitly. There are much more ideas in Moose that may be
applicable to D that i won't go any deeper in here. Please skim it's 
documentation if you're  interested.  For me it has  turned Perl into
something beautiful while being extremly flexible.

But I don't want to advertise any Perl, just hoping the idees behind
Moose can be helpful. So back to D.

The simplest property definition i can think of ist this:

class c {
    public:
    int a;
}

This can be interpreted as a property with name 'a' that has compiler
generated accessor functions int a(), and a (int) or int a(int) .The
compiler can not only auto generate them, it can also opimize them away.
So at the end of the day a field can be seen as an optimized property.
This implicates that i should be able to access fields using accessor
function syntax.
Yes, i really mean someting like x = c.a() or c.a( x) also for field
access. Even auto old = c.a( x) may be usefull. I think this can be
essential for templates or meta programming.
Syntax like x = c.a or c.a = x is cute but should be rewritten to the
above by the compiler and then optimized away in case of auto-generated
accessors.

The whole talk about using parentheses or not  for accessor functions, 
just to  better distinguish accessors from real fields when reading D
sources i have a really simple solution for. Just conceptually get rid
of real fields  in objects. Then we don't have to distinguish. And if
"int a;" in  a class definition simply defines a lightweight rw property
that internally is implemented by the compiler as a field, we get the
benefits of real properties for each field without changing one line of
already written source code. The danger of confusing field access with a
function call omitting empty parentheses vanishes as well because every
field access is now consequently a call of a property accessor even when
optimized away. So function calls can safely omit empty parentheses
without being ambigious.   

Then later we can think about creating a DSL that helps us to *declare*
more complex  types of properties and have  the compiler construct the
implicit parts at compile time. For instance i can think of a boolean
property that has a toggle accessor.

We shouldn't compose our classes from fields and functions that we
declare to be called with or without parentheses.
We should compose our classes from properties we declare (public, privat
or whatever) and let the compiler do the boring work for us.   


Now to your problem with byLine:


 Some said it should be stdin.byLine(), some others said it should be


conclusions. If byLine internally constructs a new range instance that happens to use stdin for iterating by line, this to me ist clearly a function. And then the normal rules for calling a function in the D language must apply. This has nothing to do with properties. If you have a single ByLineRange instance stored in stdin that is simply handed out by the byLine function, than this can be seen as a getter function of a byLine property and *both* forms should be applicable. So, that is my opinion about properties. I hope it makes some sense to you or is helpful to anyone. -- Gerrit
Jan 29 2010