View mode: basic / threaded / horizontal-split · Log in · Help
July 27, 2009
Re: Reddit: why aren't people using D?
On Mon, 27 Jul 2009 15:30:17 -0400, bearophile <bearophileHUGS@lycos.com>  
wrote:

> Steven Schveighoffer:
>> property
>> {
>>     int x() {}
>>     void x(int n) {}
>>     bool empty() {}
>> }
>
> An alternative:
>
> property(x) {
>     ... // or getter and/or setter
> }

No, that is a different proposal.  All I was saying is if property is an  
attribute, then like other attributes (const, etc), code like this:

property int x() {}
property void x(int n) {}
property bool empty() {}

can be rewritten as above.

-Steve
July 27, 2009
properties
Steven Schveighoffer wrote:
> The "getter" notation that currently exists only has a few minor 
> problems.  The most major of those problems is if the return value is a 
> callable type, such as a delegate, you can't easily perform the call on 
> the returned value.

Thanks for a very lucid analysis! So let me give an example:

class A
{
    int delegate() wyda()
    {
        return delegate int() { return 5; };
    }
}

void main(string[] args)
{
    auto a = new A;
    auto b = a.wyda;
    writeln(typeof(b).stringof);
    auto c = a.wyda();
    writeln(typeof(c).stringof);
    auto d = a.wyda()();
    writeln(typeof(d).stringof);
    auto e = &a.wyda;
    writeln(typeof(e).stringof);
}

This program prints:

int delegate()
int delegate()
int
int delegate() delegate()

I agree that that's an issue. One can't currently implement 
transparently a property that returns a delegate taking no arguments. 
There's an extra () needed.

>  Being that it isn't very bad for the getter 
> property, would it make sense to leave that functionality?  That is:
> 
> 1. A setter must be defined in the opSet_X(int x) form
> 2. A getter can be a function with no required arguments, but this 
> getter should not return callable types

... with zero arguments.

> 3. A getter can be defined in the opGet_X() form, and then using X() 
> will be the eqivalent of opGet_X()().
> 
> There are small implications to leaving the existing getter syntax.  
> Namely one can call a function not intended to be a getter in a 
> property-like syntax, resulting in less-than-obvious code.

This I don't agree with. I am very happy that I define popFront() as a 
method and then call it without parens.

>  Also, this 
> distinction will be very hard to explain to newbies ("how come a getter 
> is defined as x(), but a setter has to be opSet_x(...)?).

I don't see that as a problem. You just explain that the trailing () is 
not necessary, and then you tell them to define opSet_x if they want to 
enable obj.x = y.

> The more I look at it, the more I like the keyword solution.  I do find 
> the C#-like syntax which groups properties together appealing, but I 
> think you only absolutely need that if you are going to have 
> context-keywords, which I DON'T think we need.  I do find the whole 
> construct of C# properties tedious to type.
> 
> With a keyword attribute, you could even group your properties together 
> to save on typing/ugliness:
> 
> property
> {
>    int x() {}
>    void x(int n) {}
>    bool empty() {}
> }

Not a fan, but this would work. I just don't see why I need to go 
through with it.


Andrei
July 27, 2009
Aliases as Properties
Andrei Alexandrescu Wrote:

> Steven Schveighoffer wrote:
> > The "getter" notation that currently exists only has a few minor 
> > problems.  The most major of those problems is if the return value is a 
> > callable type, such as a delegate, you can't easily perform the call on 
> > the returned value.
> 
> Thanks for a very lucid analysis! So let me give an example:
> 
> class A
> {
>      int delegate() wyda()
>      {
>          return delegate int() { return 5; };
>      }
> }
> 
> void main(string[] args)
> {
>      auto a = new A;
>      auto b = a.wyda;
>      writeln(typeof(b).stringof);
>      auto c = a.wyda();
>      writeln(typeof(c).stringof);
>      auto d = a.wyda()();
>      writeln(typeof(d).stringof);
>      auto e = &a.wyda;
>      writeln(typeof(e).stringof);
> }
> 
> This program prints:
> 
> int delegate()
> int delegate()
> int
> int delegate() delegate()
> 
> I agree that that's an issue. One can't currently implement 
> transparently a property that returns a delegate taking no arguments. 
> There's an extra () needed.
> 
> >  Being that it isn't very bad for the getter 
> > property, would it make sense to leave that functionality?  That is:
> > 
> > 1. A setter must be defined in the opSet_X(int x) form
> > 2. A getter can be a function with no required arguments, but this 
> > getter should not return callable types
> 
> ... with zero arguments.
> 
> > 3. A getter can be defined in the opGet_X() form, and then using X() 
> > will be the eqivalent of opGet_X()().
> > 
> > There are small implications to leaving the existing getter syntax.  
> > Namely one can call a function not intended to be a getter in a 
> > property-like syntax, resulting in less-than-obvious code.
> 
> This I don't agree with. I am very happy that I define popFront() as a 
> method and then call it without parens.
> 
> >  Also, this 
> > distinction will be very hard to explain to newbies ("how come a getter 
> > is defined as x(), but a setter has to be opSet_x(...)?).
> 
> I don't see that as a problem. You just explain that the trailing () is 
> not necessary, and then you tell them to define opSet_x if they want to 
> enable obj.x = y.
> 
> > The more I look at it, the more I like the keyword solution.  I do find 
> > the C#-like syntax which groups properties together appealing, but I 
> > think you only absolutely need that if you are going to have 
> > context-keywords, which I DON'T think we need.  I do find the whole 
> > construct of C# properties tedious to type.
> > 
> > With a keyword attribute, you could even group your properties together 
> > to save on typing/ugliness:
> > 
> > property
> > {
> >    int x() {}
> >    void x(int n) {}
> >    bool empty() {}
> > }
> 
> Not a fan, but this would work. I just don't see why I need to go 
> through with it.
> 
> 
> Andrei

Hi, I'm new here. A simple idea I've had is to simply use aliases for defining properties.

If you allow writing aliases as expressions, you have get properties. Then a simple extension to the syntax would also allow for writing set properties.

alias (a) property;
alias (a = n) property(n);

foo(property); // Get
property = 32; // Set

This virtually eliminates any problems with properties, and it doesn't require any new keywords. It won't break existing aliases either.
July 27, 2009
Re: Aliases as Properties
On Mon, Jul 27, 2009 at 7:33 PM, escalan<escalan@gmail.com> wrote:
> Hi, I'm new here. A simple idea I've had is to simply use aliases for defining properties.
>
> If you allow writing aliases as expressions, you have get properties. Then a simple extension to the syntax would also allow for writing set properties.
>
> alias (a) property;
> alias (a = n) property(n);
>
> foo(property); // Get
> property = 32; // Set
>
> This virtually eliminates any problems with properties, and it doesn't require any new keywords. It won't break existing aliases either.
>

Except if you want to do anything more complex in your setter/getter
than a simple expression.
July 27, 2009
Re: Aliases as Properties
On Mon, Jul 27, 2009 at 7:49 PM, Jarrett
Billingsley<jarrett.billingsley@gmail.com> wrote:
> On Mon, Jul 27, 2009 at 7:33 PM, escalan<escalan@gmail.com> wrote:
>> Hi, I'm new here. A simple idea I've had is to simply use aliases for defining properties.
>>
>> If you allow writing aliases as expressions, you have get properties. Then a simple extension to the syntax would also allow for writing set properties.
>>
>> alias (a) property;
>> alias (a = n) property(n);
>>
>> foo(property); // Get
>> property = 32; // Set
>>
>> This virtually eliminates any problems with properties, and it doesn't require any new keywords. It won't break existing aliases either.
>>
>
> Except if you want to do anything more complex in your setter/getter
> than a simple expression.

Also, if your suggestion really did just replace any accesses to the
property with the aliased expression, there would be no way to
override it in subclasses, it would be invisible to the debugger, etc.
July 28, 2009
Re: Reddit: why aren't people using D?
Wed, 22 Jul 2009 23:10:53 +0200, Michiel Helvensteijn wrote:

> * Tuples (no dedicated syntax, no parallel assignment, no non-flattening
> tuples without workarounds, no returning tuples)

I'm planning to write a DIP on better tuple support.  Here is a brief
overview of my ideas.  I think I'll blog a bit more before filing an
actual DIP.

http://snakecoder.wordpress.com/2009/07/28/language-support-for-tuples-in-d
July 28, 2009
Re: properties
On Mon, 27 Jul 2009 18:37:01 -0400, Andrei Alexandrescu  
<SeeWebsiteForEmail@erdani.org> wrote:

> Steven Schveighoffer wrote:
>> The "getter" notation that currently exists only has a few minor  
>> problems.  The most major of those problems is if the return value is a  
>> callable type, such as a delegate, you can't easily perform the call on  
>> the returned value.
>
> Thanks for a very lucid analysis!

You're welcome :)

>>  Being that it isn't very bad for the getter property, would it make  
>> sense to leave that functionality?  That is:
>>  1. A setter must be defined in the opSet_X(int x) form
>> 2. A getter can be a function with no required arguments, but this  
>> getter should not return callable types
>
> ... with zero arguments.

No, callable types period.  Note that this does not compile:

class A
{
    int delegate(int foo) wyda()
    {
        return delegate int(int foo) { return foo;};
    }
}


int main(string[] args)
{
    auto a = new A;
    auto b = a.wyda(5); // line 14
    auto c = a.wyda()(5);
    return 1;
}

[steves@steveslaptop files]$ dmd testme.d
testme.d(14): Error: function testme.A.wyda () does not match parameter  
types (int)
testme.d(14): Error: expected 0 arguments, not 1

commenting out line 14 compiles.

>
>> 3. A getter can be defined in the opGet_X() form, and then using X()  
>> will be the eqivalent of opGet_X()().
>>  There are small implications to leaving the existing getter syntax.   
>> Namely one can call a function not intended to be a getter in a  
>> property-like syntax, resulting in less-than-obvious code.
>
> This I don't agree with. I am very happy that I define popFront() as a  
> method and then call it without parens.

Knowing that you can call functions without parens, seeing code like:

r.popFront;

it's obvious that popFront is a function, not a property.

But, do you agree that this code looks less-than-obvious?

auto x = flush;

is flush a flag saying flushing should occur?  is it a function that  
flushes something, and returns the success?  I agree that the bizarre  
factor is not as bad as with setters, but it's still not as  
self-explanatory as if you know that something without parens must be a  
property for the compiler to accept it.

Also, without a dedicated property syntax for setters, you have the  
problem mentioned above with callable types.  At the very least you need  
the alternate syntax, the automagic properties for zero-arg functions are  
optional.

>
>>  Also, this distinction will be very hard to explain to newbies ("how  
>> come a getter is defined as x(), but a setter has to be opSet_x(...)?).
>
> I don't see that as a problem. You just explain that the trailing () is  
> not necessary, and then you tell them to define opSet_x if they want to  
> enable obj.x = y.

Perhaps.  I admit that I don't have any real evidence to support my claim,  
but I don't think you do either ;)

>
>> The more I look at it, the more I like the keyword solution.  I do find  
>> the C#-like syntax which groups properties together appealing, but I  
>> think you only absolutely need that if you are going to have  
>> context-keywords, which I DON'T think we need.  I do find the whole  
>> construct of C# properties tedious to type.
>>  With a keyword attribute, you could even group your properties  
>> together to save on typing/ugliness:
>>  property
>> {
>>    int x() {}
>>    void x(int n) {}
>>    bool empty() {}
>> }
>
> Not a fan, but this would work. I just don't see why I need to go  
> through with it.

Let's separate this problem into two sections:

1. do we have to hint to the compiler that a function is a property or not?

I think we do, otherwise, we have the strange setter anomalies, and the  
inability to return delegates from getters.  If you think this is not the  
case, state your arguments and solutions to those problems.  I don't think  
the compiler can tell if something is meant to be a property or not by  
looking at it.

2. Assuming #1 is true for either getters and/or setters, what should the  
hints be?

This is more of a bikeshed issue, but there are some technical issues to  
consider (- = negative, + = positive):

For an opSet style syntax (e.g. int opSet_foo()):
 - There is a possible conflict between opSet_foo and foo.  Since it would  
be the only operator function where the calling syntax is also valid  
symbol.  i.e. opAddAssign is called via +=, which can't be a valid  
symbol.  The compiler absolutely has to forbid this, which might be tough  
to implement.
 - The meaning is a bit cryptic, kind of like opApply.  I understand that  
it follows in line with other operators, so you might realize it is  
special, but it's not obvious that something is a property (this is really  
a bikeshed issue).
 + Because the function is of a different form than the property call, you  
can use it as a function easily.  For example, easy to get a delegate to  
it, just &opSet_foo.
 + no changes to parser!  No new keywords (some people value this, but I'm  
not really one of them)

For a new keyword-style syntax (e.g. property int foo()):
 + Much easier for the compiler to resolve a conflict, since you are  
directly declaring the called symbol.
 + Easier to understand that foo is a property than with opSet_foo, and  
easier to know how to call it.
 - If you wanted to use the property as a function (for example, get a  
delegate to the property), it might be more difficult.  For example, if a  
property is "property ref int foo()", &foo might give you the address of  
the returned value.  I don't really know a great solution to this problem,  
maybe a cast?  Maybe you forgo the ability to take the address of the  
return value, and just have it always be a delegate?
 - new keyword (some people might not like this, I don't really have a  
problem with it).
 + Easy to annotate groups of properties by enclosing them in an attribute  
block.

------

One more point.  From my point of view, the readability of the code, and  
obvious meaning of the code to a user of the code is more important than  
the ease of development.  I've always been a fan of verbose function names  
and variables which describe what the function/variable is rather than  
short easy to type names.  For instance I loathe the module structure of  
phobos, simply because the module names are too terse.  For me to try and  
find something, it's not obvious.

So to that point, I think it's more important to make the readability and  
self-explanatory nature of properties better than to make them easier to  
declare.  Remember, you only define them once, but you use them over and  
over.  Where is it better to save time, on reading the docs or on writing  
the declaration?

-Steve
July 28, 2009
Re: properties
Steven Schveighoffer wrote:
> On Mon, 27 Jul 2009 18:37:01 -0400, Andrei Alexandrescu 
>> ... with zero arguments.
> 
> No, callable types period.  Note that this does not compile:
> 
> class A
> {
>     int delegate(int foo) wyda()
>     {
>         return delegate int(int foo) { return foo;};
>     }
> }
> 
> 
> int main(string[] args)
> {
>     auto a = new A;
>     auto b = a.wyda(5); // line 14
>     auto c = a.wyda()(5);
>     return 1;
> }
> 
> [steves@steveslaptop files]$ dmd testme.d
> testme.d(14): Error: function testme.A.wyda () does not match parameter 
> types (int)
> testme.d(14): Error: expected 0 arguments, not 1
> 
> commenting out line 14 compiles.

Ok, thanks.

>>> 3. A getter can be defined in the opGet_X() form, and then using X() 
>>> will be the eqivalent of opGet_X()().
>>>  There are small implications to leaving the existing getter syntax.  
>>> Namely one can call a function not intended to be a getter in a 
>>> property-like syntax, resulting in less-than-obvious code.
>>
>> This I don't agree with. I am very happy that I define popFront() as a 
>> method and then call it without parens.
> 
> Knowing that you can call functions without parens, seeing code like:
> 
> r.popFront;
> 
> it's obvious that popFront is a function, not a property.
> 
> But, do you agree that this code looks less-than-obvious?
> 
> auto x = flush;
> 
> is flush a flag saying flushing should occur?  is it a function that 
> flushes something, and returns the success?  I agree that the bizarre 
> factor is not as bad as with setters, but it's still not as 
> self-explanatory as if you know that something without parens must be a 
> property for the compiler to accept it.

I think inferring meaning from the presence or absence of "()" is rather 
dicey.

> Let's separate this problem into two sections:
> 
> 1. do we have to hint to the compiler that a function is a property or not?
> 
> I think we do, otherwise, we have the strange setter anomalies, and the 
> inability to return delegates from getters.

Well I don't think so. To repeat what I wrote elsethread: foo = bar is 
rewritten into foo(bar) if and only if auto __x = foo, __x = bar works. 
This means, a setter only works if there's a corresponding getter. 
(Write-only properties be damned.)


Andrei
July 28, 2009
Re: properties
On Tue, 28 Jul 2009 10:16:16 -0400, Andrei Alexandrescu  
<SeeWebsiteForEmail@erdani.org> wrote:

> I think inferring meaning from the presence or absence of "()" is rather  
> dicey.

Really?  Then why name your functions things like empty, why not ex245, to  
make them look it up, making *sure* they know what the meaning is before  
they use it.  As one other person stated, they thought empty() emptied a  
range.

Being able to read code and understand what it means without resorting to  
documentation is the sign of a good choice of symbol names.  The presence  
or absence of parens is a hard-coded accepted meaning of field vs.  
function.  Properties build on this notion by making a virtual field that  
actually resolves to a function (but behaves like a field, and this is an  
important accepted meaning).  However, D does not allow intuitive names to  
be paired with the intuitive meaning of the presense or absence of parens,  
because you can't enforce it!  Remember my example with TimeSpans?  People  
will infer meaning from the presense or absense of parens whether you  
think it's a good idea or not.  You will never get away from it.

>> Let's separate this problem into two sections:
>>  1. do we have to hint to the compiler that a function is a property or  
>> not?
>>  I think we do, otherwise, we have the strange setter anomalies, and  
>> the inability to return delegates from getters.
>
> Well I don't think so. To repeat what I wrote elsethread: foo = bar is  
> rewritten into foo(bar) if and only if auto __x = foo, __x = bar works.  
> This means, a setter only works if there's a corresponding getter.  
> (Write-only properties be damned.)

This is a band-aid fix, easily broken.

int select(int timeoutMS = -1); // method on a socket, for example

Hell, even my TimeSpan problem would still fail.

Also you are forgoing the ability to have overloaded setters, which could  
be useful.  Not to mention getters for delegates.

-Steve
July 28, 2009
Re: properties
Steven Schveighoffer wrote:
> On Tue, 28 Jul 2009 10:16:16 -0400, Andrei Alexandrescu 
> <SeeWebsiteForEmail@erdani.org> wrote:
> 
>> I think inferring meaning from the presence or absence of "()" is 
>> rather dicey.
> 
> Really?  Then why name your functions things like empty, why not ex245, 
> to make them look it up, making *sure* they know what the meaning is 
> before they use it.

I didn't say not to infer meaning from the name.

> As one other person stated, they thought empty() 
> emptied a range.

Well it doesn't.

> Being able to read code and understand what it means without resorting 
> to documentation is the sign of a good choice of symbol names.

Sure.

> The 
> presence or absence of parens is a hard-coded accepted meaning of field 
> vs. function.

I understand how some people want to derive meaning from obj.foo() 
versus obj.foo. I think they shouldn't in D. I mean D has had for years 
the behavior that you could drop the trailing empty parentheses.

> Properties build on this notion by making a virtual field 
> that actually resolves to a function (but behaves like a field, and this 
> is an important accepted meaning).

Not quite. C# has allocated a language feature for properties. Yet they 
allow you to write write-only properties, which do NOT behave at all 
like fields, and also read-only properties, which also don't behave like 
fields. Guess what - they both behave like functions. So their 
properties are an elaborate mechanism that is actually thoroughly 
unchecked, thus going back to what you could do by calling functions. So 
why the hell did they define the feature in the first place? Oh, for 
allowing people to write a.foo() instead of a.foo. You know what, that's 
a bit disappointing for an entire language feature.

> However, D does not allow intuitive 
> names to be paired with the intuitive meaning of the presense or absence 
> of parens, because you can't enforce it!  Remember my example with 
> TimeSpans?  People will infer meaning from the presense or absense of 
> parens whether you think it's a good idea or not.  You will never get 
> away from it.
> 
>>> Let's separate this problem into two sections:
>>>  1. do we have to hint to the compiler that a function is a property 
>>> or not?
>>>  I think we do, otherwise, we have the strange setter anomalies, and 
>>> the inability to return delegates from getters.
>>
>> Well I don't think so. To repeat what I wrote elsethread: foo = bar is 
>> rewritten into foo(bar) if and only if auto __x = foo, __x = bar 
>> works. This means, a setter only works if there's a corresponding 
>> getter. (Write-only properties be damned.)
> 
> This is a band-aid fix, easily broken.
> 
> int select(int timeoutMS = -1); // method on a socket, for example
> 
> Hell, even my TimeSpan problem would still fail.

Well maybe you could change TimeSpan.

> Also you are forgoing the ability to have overloaded setters, which 
> could be useful.  Not to mention getters for delegates.

Wait, overloaded setters do NOT make the thing behave like a field, but 
you were stating how nice that is a few paragraphs ago! So what is it 
that you think is good?


Andrei
19 20 21 22 23 24 25 26 27
Top | Discussion index | About this forum | D home