July 19, 2008
Sure, it's a handy feature for properties, but it is a source of too many bugs. I think that it is against the D design of avoiding features that are error-prone.

Today I once again came across with a problem with them and it's still open:

class Test
{
   void test() {}
}

How do I get a mangle of Test.test?

writefln(Test.test.mangleof);    // Should be ok, but prints v, which is not what I need
writefln((&Test.test).mangleof); // prints PFZv, which is a pointer to function
writefln(__traits(getMember, new Test(), "test").mangleof); // prints v (void, return value)

If you have other suggestions, please say, I need the solution. Custom mangling is not an option.

The following example was shown in bugzilla and it once again proves that ommitable parens lead to errors:

void main()
{
    int run()
    {
        // do the stuff
        return 0;
    }

    Thread thread = new Thread(run);  // run -> &run, this(int) is called instead of this(int delegate() dg).
}

Why not have special syntax for properties, like:

class Array(T)
{
   property T* ptr()
   {
      return _ptr;
   }

   property int length()
   {
       return _length;
   }

   void resize(int newSize)
   {
       // code here
   }

   int capacity()
   {
       // code here
   }

   private int _length;
   private T*  _ptr;
}

Usage:
Array!(int) array = new Array!(int);
int len = array.length;
array.resize = 100;       // forbidden
int capacity = array.capacity(); // okay

It is a breaking change, sure, but it solves the design flaw and fix is trivial.
July 19, 2008
On Sat, 19 Jul 2008 15:32:36 +0200, Koroskin Denis <2korden+dmd@gmail.com> wrote:

> Why not have special syntax for properties, like:

This has come up multiple times - that's one of the few things where C# wins over D. If I may repeat a suggestion I made once, maybe Walter can be hypnotized into implementing it if I just repeat it often enough :)

class foo
{
    private int _bar;
    property int bar
    {
        opGet() { return _bar; }
        opSet(auto value) { _bar = value; }
        opAddAssign(auto value) { _bar += value; } // it's extremely extendable!
    }
}

-Mike

-- 
Using Opera's revolutionary e-mail client: http://www.opera.com/mail/
July 19, 2008
"Mike" <vertex@gmx.at> wrote in message news:op.uejk9fs8kgfkbn@lucia...
> On Sat, 19 Jul 2008 15:32:36 +0200, Koroskin Denis <2korden+dmd@gmail.com> wrote:
>
>> Why not have special syntax for properties, like:
>
> This has come up multiple times - that's one of the few things where C# wins over D. If I may repeat a suggestion I made once, maybe Walter can be hypnotized into implementing it if I just repeat it often enough :)
>
> class foo
> {
>     private int _bar;
>     property int bar
>     {
>         opGet() { return _bar; }
>         opSet(auto value) { _bar = value; }
>         opAddAssign(auto value) { _bar += value; } // it's extremely
> extendable!
>     }
> }
>
> -Mike

I've always been in favor of this sort of thing as well. My reasoning is that "member variable" vs "getter/setter function" is an implementation detail, and implementation details should be possible to abstract away.

The creator of a library/API/etc should be able to design their classes in way such that if a class has a property (for instance, the color of it), then the user of the object wouldn't have to stop and think "Ok, now is color accessed as a member variable or through getters/setters?". The library creator should be able to make it so that it's the same either way.

Additionally, the ability to abstract away the "member variable" vs "getter/setter function" distinction would allow a library/API creator to develop like this: When first creating a class, the class has a property "x". At this point in time, there's nothing special that needs to be done when "x" is read from or written to. So implementing "x" as a member variable is perfectly sufficient. Later on, the class gains enhancements, some of which require additional actions to be taken whenever "x" is accessed. You're working on a library/API, so you don't want this change to be a breaking one. So instead of needing to religously implement all trivial and non-trivial properties as getters/setters right from day one in order to avoid this situation, all you'd need to do is say "Ok, property 'x' now needs getter/setter functionlity, so I'll convert it into this special 'property accessing' feature of the language instead of getter/setter functions, and that way my change won't break anything."

A third reason: Project management (Although I really think of this sort of thing more as being "lead programmer" than "manager". A manager's role is administrative, they're there to make sure the developers have what they need to do their job - chairs, computers, tools, distraction-free workspace, competent co-workers, etc. It's not their role to go sticking their fingers into the code. But I digress.). Just like how the built-in unittests, documentation, invariants, and debug conditionals allow...whoever is in charge...to have one less thing to arbitrarily define in their "coding standards", this would alliviate the need to define a standard naming convention for getters/setters. Whatever standard variable naming convention exists would be sufficient.

So, four reasons for a special "property accessing" syntax like the above:

1. The "member variable" vs "getter/setter function" distinction is an implementation detail, and as such, should be possible to abstract away.

2. User of a library doesn't always have to think "Ok, now is this property implemented as a member variable or as getters/setters?".

3. Creator of a library can change a member variable into a "getter/setter" of sorts without it being a breaking change, and without needing to religously implement all properties as getters/setters from day one.

4. Lead developer doesn't have to come up with an arbitrary "getter/setter" naming convention. They can simply say "Just use the built-in 'property accessing' syntax, and follow the usual variable naming conventions".


July 19, 2008
"Koroskin Denis" <2korden+dmd@gmail.com> wrote in message news:op.uejjwmv6n8fdl4@korden...
> Sure, it's a handy feature for properties, but it is a source of too many bugs. I think that it is against the D design of avoiding features that are error-prone.
>
> Today I once again came across with a problem with them and it's still open:
>
> class Test
> {
>    void test() {}
> }
>
> How do I get a mangle of Test.test?
>
> writefln(Test.test.mangleof);    // Should be ok, but prints v, which is
> not what I need
> writefln((&Test.test).mangleof); // prints PFZv, which is a pointer to
> function
> writefln(__traits(getMember, new Test(), "test").mangleof); // prints v
> (void, return value)
>
> If you have other suggestions, please say, I need the solution. Custom mangling is not an option.
>
> The following example was shown in bugzilla and it once again proves that ommitable parens lead to errors:
>
> void main()
> {
>     int run()
>     {
>         // do the stuff
>         return 0;
>     }
>
>     Thread thread = new Thread(run);  // run -> &run, this(int) is called
> instead of this(int delegate() dg).
> }
>
> Why not have special syntax for properties, like:
>
> class Array(T)
> {
>    property T* ptr()
>    {
>       return _ptr;
>    }
>
>    property int length()
>    {
>        return _length;
>    }
>
>    void resize(int newSize)
>    {
>        // code here
>    }
>
>    int capacity()
>    {
>        // code here
>    }
>
>    private int _length;
>    private T*  _ptr;
> }
>
> Usage:
> Array!(int) array = new Array!(int);
> int len = array.length;
> array.resize = 100;       // forbidden
> int capacity = array.capacity(); // okay
>
> It is a breaking change, sure, but it solves the design flaw and fix is trivial.

I'm not sure if I'm completely following you here. Are you basically saying that being able to call function foo by shortening "foo();" into "foo;" confuses the issue of whether you're referring to the function itself or actually trying to invoke it?

If so, then 1. I should pay more attention because I didn't realize you could do that ;). And 2. I agree.


July 19, 2008
"Mike" <vertex@gmx.at> wrote in message news:op.uejk9fs8kgfkbn@lucia...
> On Sat, 19 Jul 2008 15:32:36 +0200, Koroskin Denis <2korden+dmd@gmail.com> wrote:
>
>> Why not have special syntax for properties, like:
>
> This has come up multiple times - that's one of the few things where C# wins over D. If I may repeat a suggestion I made once, maybe Walter can be hypnotized into implementing it if I just repeat it often enough :)
>
> class foo
> {
>     private int _bar;
>     property int bar
>     {
>         opGet() { return _bar; }
>         opSet(auto value) { _bar = value; }
>         opAddAssign(auto value) { _bar += value; } // it's extremely
> extendable!
>     }

I agree, but having to reimplement the opXxxAssign methods for every property would quickly become tedious.  A much simpler way to do it is to define that:

obj.property op= expr;

is exactly the same as:

obj.property.opSet(obj.property.opGet() op expr);

I believe C# does this.  Still it'd be nice to allow opXxxAssign for properties to overload the default behavior, but it'd at least have a reasonable fallback.

In the initial designs for MiniD, when it was still a statically-typed language, I defined them exactly in this way, and then abstracted the idea by having a 'namespace' construct which could be used to implement properties, group symbols logically, and so on.

None of this will ever get into D.


July 19, 2008
"Nick Sabalausky" <a@a.a> wrote in message news:g5tdll$2sjj$1@digitalmars.com...

> I'm not sure if I'm completely following you here. Are you basically saying that being able to call function foo by shortening "foo();" into "foo;" confuses the issue of whether you're referring to the function itself or actually trying to invoke it?

It's true!


July 19, 2008
"Mike" <vertex@gmx.at> wrote in message news:op.uejk9fs8kgfkbn@lucia...
> On Sat, 19 Jul 2008 15:32:36 +0200, Koroskin Denis <2korden+dmd@gmail.com> wrote:
>
>> Why not have special syntax for properties, like:
>
> This has come up multiple times - that's one of the few things where C# wins over D. If I may repeat a suggestion I made once, maybe Walter can be hypnotized into implementing it if I just repeat it often enough :)
>
> class foo
> {
>     private int _bar;
>     property int bar
>     {
>         opGet() { return _bar; }
>         opSet(auto value) { _bar = value; }
>         opAddAssign(auto value) { _bar += value; } // it's extremely
> extendable!
>     }
> }
>
> -Mike

I'm just kind of brainstorming possible improvements to the usual way of doing properties. What if the above were adjusted into something like this (there's a few things I've done differently here):

class foo
{
    // Similar to how classes define an implict member "this",
    // "property int bar" defines an implicit "private int bar.value"
    // (Or maybe "protected int bar.value"? Or maybe adjustable somehow?).
    // This 1, elimininates the need to manually create "private _bar"
    // and 2, follows in the spirit of naming all constructors "this"
    // instead of having a different ctor name for each class
    // (and therefore achieves the same benefits - such as easier renaming).

    property int bar
    {
        // "get" and "set" can each be set separately to "public",
"private", "protected"
        // (Maybe "protected" would be useless, though? Depends if these
should
        // be overrideable.)
        get { return value; }
        set { value = set; } // The rvalue "set" is an implied param, and
                                   // works just like the implied "value" in
C#'s setters.

        // Never needed, but possibly allowed just for things like
performance.
        opAddAssign(auto addend) { value += addend; }
    }
    private func()
    {
         Stdout.formatln("{}", this.bar); // Use property
         Stdout.formatln("{}", this.bar.value); // Sidestep property
    }
}

void main()
{
    int x;
    auto f = new foo();

    f.bar = 5; // ok
    x = f.bar; // ok
    f.func(); // ok, displays "5" twice

    f.bar.value = 7; // Illegal, "bar.value" is private to "foo"
    x = f.bar.value; // Illegal, "bar.value" is private to "foo"

}






July 19, 2008
On Sat, 19 Jul 2008 21:03:28 +0200, Jarrett Billingsley <kb3ctd2@yahoo.com> wrote:

> "Nick Sabalausky" <a@a.a> wrote in message
> news:g5tdll$2sjj$1@digitalmars.com...
>
>> I'm not sure if I'm completely following you here. Are you basically
>> saying that being able to call function foo by shortening "foo();" into
>> "foo;" confuses the issue of whether you're referring to the function
>> itself or actually trying to invoke it?
>
> It's true!

For me it's mostly that there's a clear _VISUAL_ distinction between "this does something" (parens) and "this is data" (no parens); and in D there's no difference in this one (arbitrary) edge case. It's easy to "eyeball scan" code using parens pairs as visual anchors.

-Mike

-- 
Using Opera's revolutionary e-mail client: http://www.opera.com/mail/
July 19, 2008
On Sat, 19 Jul 2008 21:42:22 +0200, Nick Sabalausky <a@a.a> wrote:

Hey - I like that implicit value declaration very much. However, there needs to be a way to declare pseudo properties (without the implicit value), so I'd add an initializer to the property:

class foo
{
    property int bar
    {
        value = void; // this is the initial value; void means that there is no implicit value
        // here be getters/setters
    }
}

Maybe something like that?

-Mike

-- 
Using Opera's revolutionary e-mail client: http://www.opera.com/mail/
July 19, 2008
"Mike" <vertex@gmx.at> wrote in message news:op.uej2aznskgfkbn@lucia...
> On Sat, 19 Jul 2008 21:42:22 +0200, Nick Sabalausky <a@a.a> wrote:
>
> Hey - I like that implicit value declaration very much. However, there needs to be a way to declare pseudo properties (without the implicit value), so I'd add an initializer to the property:
>
> class foo
> {
>     property int bar
>     {
>         value = void; // this is the initial value; void means that there
> is no implicit value
>         // here be getters/setters
>     }
> }
>
> Maybe something like that?
>
> -Mike

My thought on that scenario was that if nothing within the "property int bar" block actually accesses the implied "value" member (I would think that wouldn't be too hard to detect, but maybe I'm wrong), then any access to the implied "value" from outside the block would be either completely meaningless or a sign that something is being done wrong. So in that case, the implied "value" is sort of "optimized away" (in a mannar of speaking, since it's not exactly the same as normal "optimizing away") and any attempt to access it from outside the block becomes an error.


« First   ‹ Prev
1 2 3 4
Top | Discussion index | About this forum | D home