Revised RFC on range design for D2

Sergey Gromov snake.scaly at gmail.com
Fri Sep 26 09:25:08 PDT 2008


In article <gbiqbo$m1e$1 at digitalmars.com>, SeeWebsiteForEmail at erdani.org 
says...
> Sergey Gromov wrote:
> > In article <gbgu0h$5sq$1 at digitalmars.com>, SeeWebsiteForEmail at erdani.org 
> > says...
> >> Sergey Gromov wrote:
> >>> I think that property function call feature in general adds an 
> >>> unnecessary ambiguity to the language.  I'd prefer functions to be 
> >>> callable only with regular function call syntax, and properties be 
> >>> usable only with member access syntax.  The same stands for 'unified 
> >>> function call' feature: if you want to inject a method into an 'array of 
> >>> chars' class you do so explicitly, and only the member call syntax is 
> >>> allowed on that method.  Otherwise code tends to become ambiguous and 
> >>> unreadable.
> >> Experience with other languages has shown that using identical syntax 
> >> for genuine member access and member function access helps 
> >> maintainability because it allows a type implementer to switch back and 
> >> forth between implementing a property as a direct member or as a 
> >> function, transparently to that type's use.
> > 
> > Sorry I may have been unclear.  I'm not against interchangeability 
> > between properties and property accessor methods.  I'm against using 
> > property accessors as methods, and against using methods as if they were 
> > property accessors.  The current situation actually breaks 
> > maintainability because after somebody used .length() you cannot replace 
> > it with a public variable anymore.  And you cannot replace
> > 
> > public void delegate(int) foo;
> > 
> > with an accessor method because the code 'instance.foo();' will stop 
> > working as it used to.
> 
> I am a bit confused about terminology. Could you please clarify with 
> examples what you mean, also defining all terms (e.g. what does 
> "property accessor" mean?) Thanks.

Property accessor is a method which is invoked when you syntactically 
access a data field.  They are called getters and setters in many 
languages.  In current D, any function or method with zero or one 
argument is considered a property accessor:

class Foo
{
  int prop()
  {
    return field + 1;
  }
  int prop(int value)
  {
    return field = value + 3;
  }
  private int field;
}

void useFoo(Foo f)
{
  auto x = f.prop;
  f.prop = 5;

  auto y = f.prop();  // also allowed
  f.prop(8);  // ditto
}

The 'prop' family of methods are property accessors in my terminology, 
and they can be replaced with an actual data field:

class Foo
{
  int prop;
}

void useFoo(Foo f)
{
  auto x = f.prop;  // fine!
  f.prop = 5;  // works

  auto y = f.prop();  // Error: function expected
  f.prop(8);  // Error: function expected
}

You see, properties and methods are *not* interchangeable in current D.  
Therefore your correct thesis:

> >> Experience with other languages has shown that using identical syntax 
> >> for genuine member access and member function access helps 
> >> maintainability because it allows a type implementer to switch back and 
> >> forth between implementing a property as a direct member or as a 
> >> function, transparently to that type's use.

does not apply to D.  Here's another example:

class Bar
{
  int delegate() meth;
}

int useBar(Bar b)
{
  return b.meth();
}

Can you replace 'meth' with a getter?

class Bar
{
  int delegate() meth()
  {
    return {return 5;};
  }

}

int useBar(Bar b)
{
  return b.meth();  // Error: cannot implicitly convert expression
  // (b.meth()) of type int delegate() to int
}

No you cannot.  But you could be able to do all those nice things if you 
had an explicit syntax for getters and setters:

class Foo
{
  property int prop() {...}
  property int prop(int value) {...}
  property int prop(int v, char c) {...} // syntax error, 2 arguments
  property int delegate() meth() {...}
}

void useFoo(Foo f)
{
  auto x = f.prop;  // OK
  f.prop = 5;  // OK

  auto y = f.prop();  // syntax error, function expected
  f.prop(8);  // syntax error, function expected

  int z = f.meth();  // OK, the delegate is called
}

That being said, I want the same explicit syntax for property and method 
injection, which are elements of aspect-oriented programming.  Let's 
call it inject:

inject T[] reverse(T)(T[] arr) {...}
inject property T middle(T)(T[] arr)
{
  return arr[$/2];
}
auto s = "abcde";
auto sr = s.reverse();  // "edcba"
auto sm = s.middle;  // 'c'
reverse(s);  // undefined identifier

With this, you receive an additional freedom which comes from removing 
the ambiguity.  Imagine I want my personal hell:

class Hell
{
  private enum random = 666;
  private inject property size_t realLen(T)(T[] any)
  {
    return random;
  }
  void tellTheTruth(string s)
  {
    writefln("real length of '%s' is %s", s, s.realLen);
  }
}

Here I've injected a useful property into all arrays but the injection 
is private to my hell only so I can pretend there's still paradise 
around.


More information about the Digitalmars-d-announce mailing list