On Tuesday, 29 January 2013 at 05:39:14 UTC, Zach the Mystic wrote:
Just for kicks I decided to rewrite std.array.front in the way my suggested syntax would define it. there are two overloads. With comments removed, the current code is:

//---- Code ----
@property ref T front(T)(T[] a)
if (!isNarrowString!(T[]) && !is(T[] == void[]))
{
assert(a.length, "Attempting to fetch the front of an empty array of " ~
                     typeof(a[0]).stringof);
    return a[0];
}

@property dchar front(A)(A a) if (isNarrowString!A)
{
assert(a.length, "Attempting to fetch the front of an empty array of " ~
                     typeof(a[0]).stringof);
    size_t i = 0;
    return decode(a, i);
}
//---- End -----

With what I am calling Highlander structs ("there can be only one"), it would look like this:

//---- Code ----
front struct
{
  ref T opGet(T)(T[] a)
  if (!isNarrowString!(T[]) && !is(T[] == void[]))
  {
assert(a.length, "Attempting to fetch the front of an empty array of " ~
                       typeof(a[0]).stringof);
      return a[0];
  }

  dchar opGet(A)(A a) if (isNarrowString!A)
  {
assert(a.length, "Attempting to fetch the front of an empty array of " ~
                       typeof(a[0]).stringof);
      size_t i = 0;
      return decode(a, i);
  }
}
//---- End -----

Three things stood out to me:
1. The identifier "front" only appears once now, prominently at the top of all the definitions. 2. Definitions of "front" cannot be scattered willy-nilly throughout the file anymore. 3. Without @property, the signatures are shorter, and the only price paid is the three extra lines it takes to wrap the whole thing with "front struct { ... }".

I don't think this is a bad exchange at all, considering you now have all the semantics of structs at your disposal for absolute total control over the look and feel of your properties.

The struct approach to implementing properties has a few major advantages.

One thing is that structs are already available and can do pretty much exactly what we want with properties, we just add specializations for use as a property.

Structs are made for wrapping up a data store into another one with functions for setting and getting and possibly doing other things, including storing additional state if required, so it's a lot more versatile than only a getter and setter with no additional state.

You can return a struct by reference, and the setter and getter will continue to work, you can also pass it by reference.

You can take the address of the struct property and use it correctly.

The "property as a function" approach cannot do these things without some crazy compiler magic.

The struct approach is neatly wrapped up into one self-contained package that is transportable.

The struct property concept is perhaps more profound than the function-only approach because it can be used for much more than what was originally intended, For example, any normal variable can be redefined into a property, allowing you to add additional state to it, and additional intelligence. Effectively, you are able to create "smart" variables and use them in a generalized way.

The property as a function approach, is not very profound, and the need for them is not very compelling, especially considering how much effort is being spend on this topic. The struct approach however is much more interesting and has much more potential use.

--rt

Reply via email to