property / getProperty() / setProperty()

Jarrett Billingsley jarrett.billingsley at gmail.com
Sat Aug 1 08:56:23 PDT 2009


On Sat, Aug 1, 2009 at 10:14 AM, Michel Fortin<michel.fortin at michelf.com> wrote:

> The best simple solution to that property problem I've seen up to now is to
> define "getProperty" and "setProperty" and have the compiler automatically
> check for these functions when it encounters the "property" symbol.
>
> Why do I favor "getThing" and "setThing" over "opGet_thing" and
> "opSet_thing"? Because the later are ugly. Please don't underestimate
> aestetics and readability as those are the key to make the language
> enjoyable to use and what the beginners will judge the language from. Also,
> the pattern will be pretty familiar to those comming from Java and
> elsewhere. And finally, for those who don't like having a property syntax,
> they can ignore properties completely and continue to use the get/set
> functions directly without making their code ugly.
>
> Here's an example:
>
> ~~~
> int getValue();
> void setValue(int x);
>
> setValue(1);              /* property: */  value = 1;
> assert(getValue() == 1);  /* property: */  assert(value == 1);
> ~~~
>
> The problems this syntax should fix are:
>
> 1. the ambiguity between actions and properties: getValue()/setValue() are
> functions and  thus actions named with verbs ("get" and "set"), but you can
> access them as the "value" property too, which is a noun that will call the
> function as necessary when an action is needed. (As a bonus, this makes
> "writeln = 2" illegal.)
>
> 2. the inconsistency for functions and properties returning something such
> as a delegate or a struct or class with an opCall member, where you
> absolutely need to write the function with a parenthesis to actually call
> the returned value. You can either call the function
> "getMyDelegate()(delegate_arg)" or use the property
> "myDelegate(delegate_arg)" just as you can with a field.
>
> This syntax doesn't solve the operator overloading issue. It isn't meant to
> do that either: properties should stay simple.
>
> The two small problems it pose are:
>
> 1. There's an ambiguity when another symbol is named after the property name
> that would call the get/set function. I suggest that this other symbol
> simply hide the property.
>
> 2. You need an uppercase algorithm in the compiler to be able to translate
> "property" to "setProperty" and "getProperty" and do the proper lookup. This
> works well for ASCII, but can it go messy with Unicode?
>
> To avoid converting to unicode upercase, we could use "get_thing" and
> "set_thing" (nicer than opGet/opSet), although that doesn't really fit with
> the coding standards of D.

It's been mentioned before, and I'll mention it again: a simple
'property' attribute that can be applied to any function.  No new
syntax, no get/set/value 'magic' keywords, just 'property.'  Applying
it to a function makes the compiler enforce the property syntax when
using the functions.  Any function that doesn't have the property
attribute - which should be most functions - can't be treated as one.
It doesn't require any special support from the compiler beyond what
it currently does.  It doesn't require any 'magic'.  It doesn't
require any verbose syntax.  It solves pretty much all the problems.

1. You can no longer call functions as properties that were never
intended to be (writeln = 4; goes away).
2. The "obj.prop(args)" ambiguity goes away.  *Either* obj.prop is a
normal method function and (args) are passed to it, *or* obj.prop has
the "property" attribute, and (args) are passed to its result.  Stuff
like "obj.prop[i]" is the same way.
3. There is no naming ambiguity.
4. There are no case issues.
5. It provides useful semantic information to tools, IDEs, and reflection.
6. It's nonintrusive and self-documenting.

The *only* technical issue I can come up with is if you had "property
ref X foo()", where foo returned a reference to some value type.  Then
you do "&obj.foo" - what does this get the address of?  To that end, I
suggest that &obj.foo always gets the address of the member or method
'foo' from object 'obj', and &(obj.foo) would get the address of the
return value of obj.foo.  The extra parens in there say "really, I
want you to evaluate the thing inside *first*".

Andrei, I don't know your thoughts on this.  I know you don't like the
idea of introducing new syntax but this is really as minimalistic as
you can get.  Do you have any technical issues with this proposal?  Is
there a reason why you would choose the opGet_foo/get_foo proposal
over this?



More information about the Digitalmars-d mailing list