Revised RFC on range design for D2
Michel Fortin
michel.fortin at michelf.com
Mon Sep 29 05:32:24 PDT 2008
On 2008-09-29 00:07:28 -0400, Andrei Alexandrescu
<SeeWebsiteForEmail at erdani.org> said:
> Michel Fortin wrote:
>> On 2008-09-28 19:32:43 -0400, Andrei Alexandrescu
>> <SeeWebsiteForEmail at erdani.org> said:
>>
>>> struct S2
>>> {
>>> void prop(int x);
>>> int prop();
>>> }
>>>
>>> S2 s2;
>>> s2.prop = 42; // fine, prop is a property because it also has a getter
>>>
>>> This solution does not require any syntactic addition. Its drawback is
>>> that it makes it hard to define write-only properties. Are they
>>> important?
>>
>> I think having a function returing *the same type* is probably too
>> much. What about this case:
>>
>> struct S
>> {
>> string str();
>> void str(string s);
>> void str(wstring s);
>> void str(dstring s);
>> }
>>
>> In this case, you can only do "str = x;" when x is an UTF-8 string.
>> Setting UTF-16 and UTF-32 would (sadly) require using the parenthesis
>> syntax under your proposal. So I think you should not check for the
>> return type of the getter, just if there is a function of the same name
>> with no parameter, to determine if the "=" syntax can be used.
>
> Great point. I think the rule suggested in my latest post convers this.
> The rule was, if you can call s.str(s.str) then str is a property and
> allows the syntax "=". After than overloading will take care of all
> else.
>
>> ...
>>
>> Hum, and what do you do with this:
>>
>> struct S2
>> {
>> void prop(int x);
>> private int prop();
>> }
>>
>> S2 s2;
>> s2.prop = 42; // legal or not?
>>
>> If it's legal, then I think it'll be used as a hack to do write-only
>> properties.
>
> It is legal because access check is done after syntactic check.
Ok, so you determine if a function can be called by "=" before checking
for access rights.
> (Also Walter wants to introduce the fun() = void syntax to disallow
> copying; that might be useful in this context too.)
Ok, great. What do you do with this by the way:
struct S2
{
void prop(int x);
deprecated int prop();
}
Did the author want to eventually replace "prop()" with "prop() = void"
to keep allowing "prop = 1", or does he want to simply remove it and
disallow the "prop = 1" syntax?
I find it somewhat troubling that removing an unused function
(especially if private) could invalidate code just because it is
calling another overloaded function with the property syntax. I mean,
now to know if you can safely remove a function, you have to check if
anyone is using any of corresponding overloaded "setters" too.
>> And also, if you keep checking the return type of the getter, what about this:
>>
>> struct S2
>> {
>> void prop(Object x);
>> const(Object) prop();
>> }
>>
>> Should "prop = new Object;" be legal or not?
>
> Great question - quite an arrow in the suggestion's Achille's tendon.
> Since I can't write s.prop(s.prop), that property would be ruled out.
> This may in fact be a good thing. It would be nice to provide generic
> code with the guarantee that if the save some property of an object,
> they can restore it later:
>
> void generic(Node)(Node obj) {
> auto save = obj.indentLevel;
> scope(exit) obj.indentLevel = save;
> ...
> }
Hum, but if the setter is private, protected, or package, or if it just
doesn't exist, that guarenty doesn't exist.
Another interesting case:
struct S5
{
int prop();
void prop(int x) const;
}
Not sure what to do with it though, but it certainly breaks your
guarenty when S5 is invariant. So should the property syntax "s5.prop =
x;" works only when S5 is mutable, or not at all, or in all cases?
Then what about this strange one:
struct S5
{
int prop();
string prop() invariant;
void prop(int x) const;
}
Should the property syntax works when for S5, const(S5), invariant(S5) ?
>> What if prop() was returning an invariant(Object) instead (for which
>> there is no allowed implicit conversions)?
>
> Under the proposal entity.prop(entity.prop), that won't compile. (I
> will note that invariant(Object) does convert to const(Object)).
>
>> And what if there are two overloads for the setter: one with an
>> invariant(Object) and one with an Object (mutable)? Are both allowed to
>> be called with "="?
>
> Under the proposal entity.prop(entity.prop), that would compile.
Seems coherant.
>> Then you should probably disallow "ref" and "out" too in the setter.
>
> Consider:
>
> struct ArrayAppender {
> ref Array host;
> void host(ref Array);
> }
>
> That should work as property, ain't it?
>
> (Walter has introduced ref returns; I'm already working on an alpha
> that has the feature. Of course I found bugs, too. :o))
And "out"?
>> I'm not sure either about what you'll do once "shared" gets in the
>> picture. (And ain't "scope" comming at some point too?)
>
> Same test entity.prop(entity.prop) rules'em all.
Seems coherant, again.
>> Also, what if one or the other is a static function?
>
> Depends on how you call it. If you call it with an object in the first
> place, it works. If not, it doesn't.
Ok, let's clarify that:
struct S1
{
int prop();
static void prop(int x);
}
struct S2
{
static int prop();
void prop(int x);
}
S1 s1;
s1.prop = 1; // ok, because s1.prop returns int.
S1.prop = 1; // error, since S1.prop does not exist.
S2 s2;
s2.prop = 1; // ok, because s1.prop returns int.
Is that right?
>> And what if you have an invariant(S2) and prop(Object x) is accessible
>> (because it is invariant) while prop() is not (because not invariant),
>> should the "=" syntax apply anyway?
No answer to that one? Take this case:
struct S3
{
int prop() invariant;
void prop(int x);
}
S3 s3;
s3.prop = x; // error?
struct S4
{
int prop();
void prop(int x) invariant;
}
invariant(S4) s4;
s4.prop = x; // error?
I guess disallowing this wouldn't be too bad, since it's pretty
ridiculous anyway.
>> Basically what I want to illustrate is that another drawback of this
>> solution is that it will probably not be as straitforward to define,
>> and then understand, as it seem at first glance.
>
> I think it is very easy to define and moderately hard to implement.
The thing is that you can't explain everything just by checking if you
can compile "s.prop(s.prop)". If one of the two is private, you said it
would be allowed anyway, it becomes "s.prop(s.prop) disregarding
applicable protection attributes". Then you said that it the getter
could be "= void", but obviously "s.prop(s.prop) wouldn't compile in
that case, so you'd have to change it to "s.prop(s.prop) compiles
disregarding applicable protection attributes and whether or the the
getter is '= void'". Then you'll need to add something about the
constness of the struct or class the function is scoped in, so it
becomes:
s.prop(s.prop) compiles disregarding applicable protection attributes,
disregarding whether or the the getter is '= void', and disregarding
the constness of the enclosing scope (class or struct).
That doesn't sound so simple, and I probably got it wrong. Can you
define it better?
--
Michel Fortin
michel.fortin at michelf.com
http://michelf.com/
More information about the Digitalmars-d-announce
mailing list