January 05, 2006
Ivan Senji skrev:
> Fredrik Olsson wrote:
>> My $0.02 (I like that one :) ).
> 
> OK, here is my 0.02kn (currency where i come from and < $0.02) :)
> 
>>
>> 1. IMHO it is bad to be able to call both as function and as property, it confuses adopters.
>> 2. Breaking backward compatibility for properties is too late(?).
>> 3. I want more syntactic sugar!
>>
>> Today we have
>> int length(char[] str);
>> That can be called in two ways:
>> 1. int bar = length(foo);
>> 2. int baz = foo.length;
>>
>> Why not add a "property" modifier, like this;
>> property int length(char[] str);
>> And now the 1. syntax is forbidden for the "function".
>>
> 
> I am strongly in favor for adding extendable properties to *all* types and this syntax is as good as any other sugested.
> 
>> For extra syntactic sugar, if we have more then one parameter the rest of the parameters can be used as indexers. Like this:
> 
> But this isn't....
> 
>> property bool charIsNumber(char[] str, uint index) {
>>   return '0' <= str[index] && str[index] <= '9';
>> }
>> char[] foo = "Atari 520STe";
>> bool jupp = foo.charIsNumber[4];
>>
> 
> ...beacuse the rest of the parameters are in 99% of the cases not going to semanticaly be indexes.

In 99% of the cases indexes are probably int and char[]. But allowing any type makes it dead easy to emulate any kind of associative arrays. Perhaps even making the opIndex() function obsolete? As this one:
property int this(uint index);
Could mean the same thing and be consistent as well.

// Fredrik Olsson
January 05, 2006
Don Clugston skrev:
> Fredrik Olsson wrote:
>> Sean Kelly skrev:
>>
>>> S. Chancellor wrote:
>>
>> <snip>
>>
>>> I think a property syntax is a reasonable idea so long as we don't lose the ability to use free functions as properties.  I'm finding it quite useful that I can even replace global variables with no-argument functions and leave all other code unchanged.
>>>
>>
>> My $0.02 (I like that one :) ).
>>
>> 1. IMHO it is bad to be able to call both as function and as property, it confuses adopters.
>> 2. Breaking backward compatibility for properties is too late(?).
>> 3. I want more syntactic sugar!
>>
>> Today we have
>> int length(char[] str);
>> That can be called in two ways:
>> 1. int bar = length(foo);
>> 2. int baz = foo.length;
>>
>> Why not add a "property" modifier, like this;
>> property int length(char[] str);
>> And now the 1. syntax is forbidden for the "function".
> 
> I love it. Especially if it meant that properties could be added to any type (including built-in types), rather than just arrays.

I can not see why this could not be made to work with any type. But then again I see no reason why the "void func(T foo)" only creates "fake methods" for arrays.

// Fredrik Olsson
January 05, 2006
Fredrik Olsson wrote:
> Ivan Senji skrev:
>>
>> ...beacuse the rest of the parameters are in 99% of the cases not going to semanticaly be indexes.
> 
> 
> In 99% of the cases indexes are probably int and char[]. But allowing any type makes it dead easy to emulate any kind of associative arrays. Perhaps even making the opIndex() function obsolete? As this one:
> property int this(uint index);
> Could mean the same thing and be consistent as well.
> 

I think there might be a missunderstanding here. I will try to explain what i wanted to say with an example:

property int[] selectIfGreaterThan(int[] numbers, int condition);

int[] numbers;

numbers.selectIfGreaterThan(5);

5 in this case is not an index and i think in most cases of extending other types with additional properties the other parameters aren't going to be indexes but something else as in the example above.
January 05, 2006
James Dunne wrote:
> <rant>
> What is it with you people and the dependence on keywords? =P  You only need a special context-dependent identifier - this is NOT A KEYWORD. Keywords are language tokens and can only be used for the one thing that they mean.  OTOH, a special context-dependent identifier (as I call it, I guess) means that the compiler tests the name of the identifier given for a special word only within certain contexts.
> 
> In this case, when getter/setter methods are defined within a property block, the identifiers "get" and "set" have special meaning and are not just regular identifiers anymore.  HOWEVER, EVERYWHERE ELSE THEY HAVE NO SPECIAL MEANING.
> </rant>
> 
> Not blowing up on you particularly, Chris. =)

No worries, actually what you say makes perfectly good sense.  I probably shouldn't post to the NG right after ten hour shifts, else I might've realised that on my own.  :)

-- Chris Sauls
January 05, 2006
Derek Parnell wrote:
> However, there is no necessary requirement for a property to be implemented
> by just a single internal (private?) variable. Also, other members in the
> class might deal with the internal property variables in a more efficient
> manner than using the get/set paradigm.
> 
> Ok, so here's another refinement ...
> 
>   private {
>     float A;
>     long  B;
>   }
>   property goofy {
>      out (float) { goofy = cast(float)B + A; }
>      in  (float) { B = cast(long) toInt(goofy);
>                  A = goofy - cast(float)B;}
>   }
>   void someFunc(long x)
>   {
>       if (B > 0) B *= x;
>   }
> 
> Sure this is contrived, but you get my point.
> 

Actually, Derek, I think I like your refined proposal, even the new use of the in/out keywords (despite my recent education on that matter, see other posts).  It might've been arguable that internally a class might be able to do something like 'this.height._height' but... ew.  My only quirk, is I really would prefer the gettor type of a property be strong.  I just don't trust the compiler enough, I guess?  There would have to be fairly explicit rules about how it determines which 'out' clause to use.

-- Chris Sauls
January 05, 2006
Chris Sauls wrote:
> James Dunne wrote:
> 
>> <rant>
>> What is it with you people and the dependence on keywords? =P  You only need a special context-dependent identifier - this is NOT A KEYWORD. Keywords are language tokens and can only be used for the one thing that they mean.  OTOH, a special context-dependent identifier (as I call it, I guess) means that the compiler tests the name of the identifier given for a special word only within certain contexts.
>>
>> In this case, when getter/setter methods are defined within a property block, the identifiers "get" and "set" have special meaning and are not just regular identifiers anymore.  HOWEVER, EVERYWHERE ELSE THEY HAVE NO SPECIAL MEANING.
>> </rant>
>>
>> Not blowing up on you particularly, Chris. =)
> 
> 
> No worries, actually what you say makes perfectly good sense.  I probably shouldn't post to the NG right after ten hour shifts, else I might've realised that on my own.  :)
> 
> -- Chris Sauls

Ouch.  Yeah this whole week I'm pulling 10-12 hour shifts, 9am to 9pm or so.  Deadlines are so stupid and pointless... especially when no one outside your organization is depending on them, and even when they have no effect on anything.
January 05, 2006
John C wrote:
> Any attempt to define a) a setter with an argument type that doesn't match that of the getter return type, or b) a getter with a return type that doesn't match that of the setter argument type, would be an error.
> 
> Better?

Clearer, yes...  Better, no, IMHO.  :)  I don't see the utility in requiring that a property only allow one data type for its settor.  I'm all for locking down the gettor, but being able to send different kinds of data into a property can make perfectly good sense in some designs.  Stupid example: a property for setting an HTTP response code, which accepts either a ushort (401, 202, etc) or a string (char[], wchar[], dchar[]) containing the code number.

>>>2) Different protection attributes can be applied to the getter and setter, as with methods.

I do like this.

-- Chris Sauls
January 05, 2006
"Derek Parnell" <derek@psych.ward> wrote...
> On Thu, 05 Jan 2006 00:46:02 -0600, Chris Sauls wrote:
>
>> I proposed something similar to this many ages ago.  Mine looked like:
>>
>> # class Foo {
>> #   property int height {
>> #     int _height;
>> #     int get () { return _height; }
>> #     int set (int x) { return _height = x; }
>> #     int set (char[] x) { return _height = toInt(x); }
>> #   }
>> # }
[snip]
> Ok, so here's another refinement ...
>
>  private {
>    float A;
>    long  B;
>  }
>  property goofy {
>     out (float) { goofy = cast(float)B + A; }
>     in  (float) { B = cast(long) toInt(goofy);
>                 A = goofy - cast(float)B;}
>  }
>  void someFunc(long x)
>  {
>      if (B > 0) B *= x;
>  }
>
> Sure this is contrived, but you get my point.
>
> I imagine the purpose of properties is to totally divorce the
> implementation from the usage. Such that the 'public' face of the property
> is a float, for example, but the implementation can change over time
> without haven't to change any referencing source code. The implementation
> can start off being a simple, single float variable but later can change
> to
> some complex function and all the source code that references the property
> doesn't have to be modified.


Not so much the purpose of properties, but the purpose of behavioral abstraction. 'Normal' methods are no different in this regard, and classes are just larger-grained instances. Programs themselves are larger-grained again. I know you know this, but it's worth regurgitating anyway.

While I think the idea of special 'property' sugar is seductive, one has to wonder whether it really has value? For instance, the 'normal' implementation of the above example is approximately as follows:

private float A;
private long B;

void setGoofy (float goofy)
{
    B = cast(long) toInt(goofy);
   A = goofy - cast(float) B;
}

float getGoofy ()
{
   return cast(float) B + A;
}

void someFunc (long x)
{
    if (B > 0) B *= x;
}

I think it's arguable that the above is actually clearer (partly because you don't have to understand alternate syntax), plus you also have the options to inherit, override, implement call-chaining etc.

Sure, it might be nice to have some means of reducing the amount of typing involved for trivial properties; but isn't there always a tradeoff? And, isn't the 'typing aspect' a job for an IDE?

2 Cents;


January 05, 2006
"Chris Sauls" <ibisbasenji@gmail.com> wrote in message news:dpjn4t$2i2k$1@digitaldaemon.com...
> John C wrote:
>> Any attempt to define a) a setter with an argument type that doesn't match that of the getter return type, or b) a getter with a return type that doesn't match that of the setter argument type, would be an error.
>>
>> Better?
>
> Clearer, yes...  Better, no, IMHO.  :)  I don't see the utility in requiring that a property only allow one data type for its settor.  I'm all for locking down the gettor, but being able to send different kinds of data into a property can make perfectly good sense in some designs. Stupid example: a property for setting an HTTP response code, which accepts either a ushort (401, 202, etc) or a string (char[], wchar[], dchar[]) containing the code number.

I think I see what you're getting at - like overloads, but contained within the property block? That sounds useful, I hadn't considered it.

>
>>>>2) Different protection attributes can be applied to the getter and setter, as with methods.
>
> I do like this.
>
> -- Chris Sauls


January 05, 2006
On Fri, 06 Jan 2006 05:52:44 +1100, Kris <fu@bar.com> wrote:


[snip]

> While I think the idea of special 'property' sugar is seductive, one has to
> wonder whether it really has value? For instance, the 'normal'
> implementation of the above example is approximately as follows:
>
> private float A;
> private long B;
>
> void setGoofy (float goofy)
> {
>     B = cast(long) toInt(goofy);
>    A = goofy - cast(float) B;
> }
>
> float getGoofy ()
> {
>    return cast(float) B + A;
> }
>
> void someFunc (long x)
> {
>     if (B > 0) B *= x;
> }
>
> I think it's arguable that the above is actually clearer (partly because you
> don't have to understand alternate syntax), plus you also have the options
> to inherit, override, implement call-chaining etc.
>
> Sure, it might be nice to have some means of reducing the amount of typing
> involved for trivial properties; but isn't there always a tradeoff? And,
> isn't the 'typing aspect' a job for an IDE?

Yes, I understood all of that but the difference is in how you refer to the 'property'. With a true property it would

    X = A.goofy;

and in your version it would be

    X = A.getGoofy();

The difference is not just how much you type in. For example the original version of the class might have defined 'goofy' as just ...

     float goofy;

So code referring to it would have been ...

    X = A.goofy;

And then later when it was turned into a property, that type of reference would not also have to be changed but if the function-type property was implemented (ala your example) all references to 'goofy' would also have to be changed.


Why can't one inherit, override, and implement call-chaining with properties? There is nothing built into the concept which precluses those functionalities. You can even get compilers to cope with properties beibg used as 'inout' parameters if one wanted to.

-- 
Derek Parnell
Melbourne, Australia