Partial modification of DIP23 to allow module level property
Kenji Hara
k.hara.pg at gmail.com
Fri Feb 8 21:15:34 PST 2013
> http://wiki.dlang.org/DIP23
I had thought about DIP23 for a while, to allow module-level
property function.
As the conclusion, we can have that without breaking the essence
in DIP23.
==========
> In a nutshell
> 2. A @property may have EXACTLY ONE or EXACTLY TWO parameters,
> counting the implicit this parameter if at all.
> The ONE-parameter version is ALWAYS a getter, and the
> TWO-parameter version is ALWAYS a setter.
> There's no variadics, defaulted parameters, and such.
We should change this sentence to:
----
2. A @property may have EXACTLY ZERO or EXACTLY ONE parameter,
without counting the implicit this parameter if at all.
The ZERO-parameter version is ALWAYS a getter, and the
ONE-parameter version is ALWAYS a setter.
There's no variadics, defaulted parameters, and such.
----
> Optional parens stay in
No modification is necessary.
> No module-level properties
It should be replaced to completely:
----
* Module level properties stay in
There is still module-level property emulating a global variable.
That means a @property defined at module level must take either
ZERO parameter (meaning its a getter) or ONE parameter (meaning
it's a setter).
// at module level
private long _distance;
@property long distance() { return _distance; }
@property void distance(double d) { assert(d >= 0); _distance =
cast(long)std.math.trunc(d); }
unittest
{
distance = 3.1;
assert(_distance == 3)
auto d = distance;
assert(d == 3);
}
To avoid syntactic ambiguity, it's forbidden to define property
getter callable by using UFCS.
@property ref int front(int[] a) { return a[0]; }
unittest
{
int[] arr = [1,2,3];
assert(front(arr) == 1); // OK
assert(arr.front == 1); // compile-time error, "setter
@property function cannot call with UFCS"
}
Instead, such 'front' function would work if remove the @property
annotation.
ref int front(int[] a) { return a[0]; }
unittest
{
int[] arr = [1,2,3];
assert(front(arr) == 1); // OK
assert(arr.front() == 1); // OK, UFCS
assert(arr.front == 1); // Even OK, UFCS + optional
paranthesis feature
arr.front() = 2; // assign to returned ref
assert(arr[0] == 2);
arr.front = 3; // Even OK, optional parenthesis
assert(arr[0] == 2);
int* p = &arr.front; // Even OK, arr.front is rewritten to
// front(arr), so '&' operator will be applied to the ref
value returned from 'front'.
}
For the combination of UFCS and setter syntax, a function which
takes TWO parameters and defined at module level can SPECIALLY be
annotated with @property.
@property void all(double[] x, int y) { x[] = cast(double) y; }
unittest
{
auto d = [ 1.2, 3.4 ];
d.all = 42; // UFCS + setter syntax
// rewritten to: all(d, 42)
assert(d == [ 42.0, 42.0 ]);
}
----
Regards.
Kenji Hara
More information about the Digitalmars-d
mailing list