View mode: basic / threaded / horizontal-split · Log in · Help
July 24, 2009
DIP4: Properties
An alternate usage/definition syntax for properties.

http://prowiki.org/wiki4d/wiki.cgi?LanguageDevel/DIPs/DIP4

Note that there are a few parts marked NEED HELP, that could use assistance
from someone with more expertise in this than me.
July 24, 2009
Re: DIP4: Properties
Some comments:

There should be an actual proposal definition instead of just an
example.  Examples tend to be misinterpreted.

I've tried to work out a possible grammar:

Decl:
	BasicType DeclaratorInitializer '{' PropertyDecls '}'

PropertyDecls:
	PropertyDecl
	PropertyDecl PropertyDecls

PropertyDecl:
	PropertyIdentifier BlockStatement

PropertyIdentifier:
	'get'
	'set'

(note: additions to this grammar are below)

---

The "optimise implicit value away" thing is a bit iffy.  I'd prefer some
actual syntactic distinction between a property with automatic storage.
It would be far too easy to accidentally cause the backing to be added.

I had the following idea, but I'm worried that it's context-sensitive;
it looks an awful lot like a normal AutoDeclaration, except that it's
missing the assignment.  Mayhap someone with stronger grammar-fu could
tell me? :D

We could add the following:

PropertyDecl:
	'auto' Identifier ';'

If this appears in a property, it creates a private variable with the
same type as the property itself, scoped to the property declaration.
This would allow for people to use whatever "magic" name they like.
Your first example property would become:

int width = int.init
{
   auto value;
   get { return value; }
   set { value = set; }
}

---

Also, having the value being assigned to the property be called "set" is
really unnerving.  We've already got to explain to people why in
templates you "assign" to the name of the template; I don't want to have
to explain that it works in completely the opposite way for property
setters.  I think the solution to this is to just make it explicit
somehow.  `set(v) { value = v; }` is not THAT much more typing (minimum
of 3 characters), and it saves you from having to memorise yet another
magic identifier.

---

Q: How do properties interact with templates?

---

Being able to modify a read-only property is just *nasty*.  Having
either explicit backing or protection attributes on the getter/setter
would be a better solution.

Change PropertyDecl to:

PropertyDecl:
	PropertyIdentifier BlockStatement
	ProtectionAttribute PropertyIdentifier BlockStatement

---

Q: Is this syntax context-free?  I can't think of any existing case it
would conflict with.  Wish there was some easy way to check.

---

One issue I have with rewriting {a.b op= c} to {a.b = a.b op c} is that
the former may be much more efficient than the latter.  It might perhaps
be wise to postpone addressing this until later [1].

---

Some time ago, Andrei indicated that he felt properties needed *three*
basic operations: get, swap and delete, or something.  We should find
that post and look at whether it's a good idea.

---

Q: Why is 'delete' or 'remove' not available?  It's present in Python
(as an example), why not here?


[1] Personally, I suspect it would be best if we had a pragma or
something that told the compiler "look, even if this is a property,
don't rewrite it; I'll take care of it."  That, or maybe rewrite {a.b
op= c} to {auto tmp = a.b; tmp op= c; a.b = tmp}.
July 24, 2009
Re: DIP4: Properties
Sorry; posted without going over the Description section.  :P

Again, automatic storage just rubs me the wrong way.  Less magic, please.

---

Without automatic storage, there's a fairly simple way to make it
visible outside the property; move the "auto value;" declaration outside
and make it "T _blah;" or something.  Not pretty, granted, but
consistent and means we don't have to muck with traits or special
syntax.  It's also *obvious* where stuff is accessible from.

---

struct Property(T)
{
   T delegate() getter;
   void delegate(T) setter;

   T get()
   {
       return enforce(getter, new MissingGetterException)();
   }
   void set(T v)
   {
       enforce(setter, new MissingSetterException)(v);
   }
}

The exceptions shouldn't need explanation.  :)

---

Interacting with inheritance is tricky.  I think what should be done is
this:

class A { int foo { get; set; } }

Would generate the following hidden functions:

A.__property_foo_get
A.__property_foo_set

Then, this:

{
   A a;
   auto p = &a.foo;
}

translates to this:

{
   A a;
   Property!(int) p = {
       getter:&a.__property_foo_get,
       setter:&a.__property_foo_set};
}

This should allow class implementations to add a setter to read-only
properties specified in either an interface or base class.

(Incidentally, the internal storage could be __property_foo_(name) or
something.)

As for defaults: public.  Properties are usually defined for public
interfaces; if it was private, you might as well just use a field.

---

Again, I don't like having "set" be magical.  _argptr and _arguments are
bad enough as it is, please let's not add more invisibly defined magic
identifiers!

---

Regarding your cons: get and set mustn't be made keywords; they're too
short and useful.  Using in and out is actually a pretty good idea.

Come to think of it... would it at all be useful to be able to expose a
ref property that just exposes an underlying field?

Your note regarding array properties and extension methods was one I
hadn't considered.  It should DEFINITELY be given thought.
July 24, 2009
Re: Properties
Now that I've finally gotten my ng client to play nice and actually show me
my own DIP4 thread (unsubscribed digitalmars.D and then re-subscribed), I'm
moving the comment that was left on the Wiki over here:

------------------------------------

RobertJacques says:

Cons:

* Verbosity is an issue (i.e. the addition of extra boiler-plate code)

* keyword increase: both set and get become keywords. Perhaps re-using in
and out in a manner similar to contract programming might work.

* +=, -=, etc. : The suggested syntactic sugar is good, but could be
implemented with current properties. Separate?

* bondage and discipline: Different programmers have different coding
styles. Hence the suggested syntactic sugar of func(class, value) <=>
class.func(value) <=> class.func = value in other proposals and currently
valid for arrays. Flexibility is a virtue

* IDE's, and doc-generators: Could all be well served with a appropriate set
of DDoc tags
July 24, 2009
Re: Properties
"Nick Sabalausky" <a@a.a> wrote in message 
news:h4c202$283l$1@digitalmars.com...
> Now that I've finally gotten my ng client to play nice and actually show 
> me
> my own DIP4 thread (unsubscribed digitalmars.D and then re-subscribed), 
> I'm
> moving the comment that was left on the Wiki over here:
>
> ------------------------------------
>
> RobertJacques says:
>
> Cons:
>

Ok, now I finally have a moment to respond to at least one set of comments:

> * Verbosity is an issue (i.e. the addition of extra boiler-plate code)
>

I'm not sure I see how the proposed syntax is verbose. And I specifically 
designed it to minimize boilerplate. With the current style, you have to 
(typically) define a private variable, and then one or two functions for 
getting/setting. This proposal isn't really much more than that even in the 
worst case. Maybe you could elaborate on what you mean?

> * keyword increase: both set and get become keywords. Perhaps re-using in
> and out in a manner similar to contract programming might work.
>

I indicated in the proposal that they would not be keywords. Someone 
indicated in the "Reddit: Why aren't people using D?" thread that that would 
be possible. Maybe they could explain here?

I suppose it might be required to make "value" and "set" keywords because of 
their use as implicit variables, but I'm not convinced. Maybe a language 
expert could shed some light on this?

Also, regarding in/out contracts, something like this was one of my earlier 
ideas, but I decided against it because I wasn't sure if it would cause 
parsing problems, and I wanted to leave the door open for (I forget who's) 
suggestion of allowing operator overloading for a property if that ended up 
being deemed necissary. But, I may as well stick it on the table here for 
open discussion:

-----------------------------
// Viable? Preferable?
int width = 7
get { return value; }
set { value = set; }
-----------------------------

> * +=, -=, etc. : The suggested syntactic sugar is good, but could be
> implemented with current properties. Separate?
>

Perhaps. What does everyone else think?

> * bondage and discipline: Different programmers have different coding
> styles. Hence the suggested syntactic sugar of func(class, value) <=>
> class.func(value) <=> class.func = value in other proposals and currently
> valid for arrays. Flexibility is a virtue
>

I'm sorry, but I have to strongly disagree with this one. Saying that 
"class.func(value) <=> class.func = value" is a matter of style is like 
saying that "2 + 2" vs "2 ~ 2" to do addition is a matter of style. (And I 
question the "func(class, value) <=> class.func(value)" part as well, albiet 
not quite as strongly) Within a language, each syntax and operator has it's 
own meaning. Allowing them to be switched around interchangably serves no 
purpose besides obfuscation.

> * IDE's, and doc-generators: Could all be well served with a appropriate 
> set
> of DDoc tags

In the case of doc-generators, yes, that could be done and would not be 
unreasonable. However, any information that a doc-generator can get directly 
from the code instead of an additional doc-generator-specific syntax (let's 
not forget, that would add extra verbosity/boilerplate!) can only be an 
improvement.

In the case of debuggers, it's probably possible, but it's a bad idea. A 
debugging feature should not be dependant on any specific doc-generator. 
DDoc may be built into DMD, but it is expected that any standard doc 
generator can be used instead. The only way for a debugger to get around 
that is to try to support every doc-generator that someone might want to use 
(and just for the sake of properties alone?), which may be possible, but not 
the right approach.
July 24, 2009
Re: DIP4: Properties
Am I right in thinking that the automated storage is mainly to cut down 
verbosity? What other purpose could it serve? It looks to me the proposal 
could be much simplified by cutting this feature. 

I think the "int foo {get;set;}" syntax may be sufficient and useful for 
keeping simple properties simple though. The advantage over plain fields in 
this case is primarily to keep interface compatibility. Speaking of which, 
how should properties behave in interfaces?
July 25, 2009
Re: Properties
On Fri, 24 Jul 2009 17:12:39 -0400, Nick Sabalausky <a@a.a> wrote:

> "Nick Sabalausky" <a@a.a> wrote in message
> news:h4c202$283l$1@digitalmars.com...
>> Now that I've finally gotten my ng client to play nice and actually show
>> me
>> my own DIP4 thread (unsubscribed digitalmars.D and then re-subscribed),
>> I'm
>> moving the comment that was left on the Wiki over here:
>>
>> ------------------------------------
>>
>> RobertJacques says:
>>
>> Cons:
>>
>
> Ok, now I finally have a moment to respond to at least one set of  
> comments:
>
>> * Verbosity is an issue (i.e. the addition of extra boiler-plate code)
>>
>
> I'm not sure I see how the proposed syntax is verbose. And I specifically
> designed it to minimize boilerplate. With the current style, you have to
> (typically) define a private variable, and then one or two functions for
> getting/setting. This proposal isn't really much more than that even in  
> the
> worst case. Maybe you could elaborate on what you mean?

Your syntax seems very C# inspired. After doing a class project in C# a  
while ago, which heavily used properties, I breathed a major sigh of  
relief coming back to D properties. If I had to pick something concrete,  
I'd say the lack of clean one-liners is an issue as is the extra  
indentation.

I'd also note I almost never do the private var, public method pattern.  
(Really, only when I want a expose a read-only view of something) Most of  
the time I'm doing some kind of transform and storing the data in a  
seperate internal format.

>> * keyword increase: both set and get become keywords. Perhaps re-using  
>> in
>> and out in a manner similar to contract programming might work.
>>
>
> I indicated in the proposal that they would not be keywords. Someone
> indicated in the "Reddit: Why aren't people using D?" thread that that  
> would
> be possible. Maybe they could explain here?
>
> I suppose it might be required to make "value" and "set" keywords  
> because of
> their use as implicit variables, but I'm not convinced. Maybe a language
> expert could shed some light on this?
>
> Also, regarding in/out contracts, something like this was one of my  
> earlier
> ideas, but I decided against it because I wasn't sure if it would cause
> parsing problems, and I wanted to leave the door open for (I forget  
> who's)
> suggestion of allowing operator overloading for a property if that ended  
> up
> being deemed necissary. But, I may as well stick it on the table here for
> open discussion:
>
> -----------------------------
> // Viable? Preferable?
> int width = 7
> get { return value; }
> set { value = set; }
> -----------------------------

Hmm... Here's some random ideas

int width = 7         /// Property with storage
out                   { return width;           }
in(int   i)           { width = i;              }
inout(alias op)(int i){ return width op i;      }

auto high_five        /// Property with no storage
out(float)     { return 5.99; }

>> * +=, -=, etc. : The suggested syntactic sugar is good, but could be
>> implemented with current properties. Separate?
>>
>
> Perhaps. What does everyone else think?
>
>> * bondage and discipline: Different programmers have different coding
>> styles. Hence the suggested syntactic sugar of func(class, value) <=>
>> class.func(value) <=> class.func = value in other proposals and  
>> currently
>> valid for arrays. Flexibility is a virtue
>>
>
> I'm sorry, but I have to strongly disagree with this one. Saying that
> "class.func(value) <=> class.func = value" is a matter of style is like
> saying that "2 + 2" vs "2 ~ 2" to do addition is a matter of style. (And  
> I
> question the "func(class, value) <=> class.func(value)" part as well,  
> albiet
> not quite as strongly) Within a language, each syntax and operator has  
> it's
> own meaning. Allowing them to be switched around interchangably serves no
> purpose besides obfuscation.

Well, actually "func(class, value) <=> class.func(value)" is extremely  
valuable for extending third party structs/classes. It's also very much  
about programmer style. Some people prefer/understand one better than the  
other. It can also help make porting/refactoring go smoother. I've also  
used "class.func = value" several times even when according to the style  
of the library I shouldn't; In each case, it increased the readability and  
understandability of my code as a whole, despite "class.func = value" not  
making much sense in isolation.

Anyways, enforcing style for style's sake is always bondage and discipline  
programming. I mean, people have issues with restrictions even when they  
buy safety and robustness.

BTW, I think you meant "2 + 2" vs "2 ~ 2" to do concatenation. And if you  
really meant addition, then well that's just bad function name choice.  
It's got nothing to do with style.

>> * IDE's, and doc-generators: Could all be well served with a appropriate
>> set
>> of DDoc tags
>
> In the case of doc-generators, yes, that could be done and would not be
> unreasonable. However, any information that a doc-generator can get  
> directly
> from the code instead of an additional doc-generator-specific syntax  
> (let's
> not forget, that would add extra verbosity/boilerplate!) can only be an
> improvement.
>
> In the case of debuggers, it's probably possible, but it's a bad idea. A
> debugging feature should not be dependant on any specific doc-generator.
> DDoc may be built into DMD, but it is expected that any standard doc
> generator can be used instead. The only way for a debugger to get around
> that is to try to support every doc-generator that someone might want to  
> use
> (and just for the sake of properties alone?), which may be possible, but  
> not
> the right approach.

Curiosity, how would a debugger set a watch on a property since it doesn't  
acually exist?
Top | Discussion index | About this forum | D home