On 1/3/23 19:42, thebluepandabear wrote:

>      @property {

As your post proves, that feature is at most half-baked and is discouraged. Today, there is just one known obscure effect of using it.

>          void name(string name) {
>              _name = name;
>          }

>      d.name = "Poodle";

> In the code we can see that we have utilized UFCS (universal function
> call syntax)

UFCS is for calling free-standing functions as if they are member functions. Since your example already uses member functions, this feature is not UFCS. And I don't think it has a name.

It is always possible to pass a single-argument with the assignment syntax:

void foo(int i) {}

void main() {
    foo = 42;
}

Pretty wild! :) But that's what makes your assignment above work. (Not UFCS.)

> not enforced [...] we can
> do the following in our code:

>      d.name("poodle");

I don't see a problem with that. :)

> I am disappointed that `@property` does not

Many people are disappointed that @property is pretty much useless.

> is there a way to enforce

D gives us the tools to do that but it's not trivial. The function can return an object that represents a variable (member variable or not). And an assignment to that representative object can set the actual variable.

However, I tried to achieve it with an intermediary object but failed because the same ="Poodle" syntax broke it and demanded that we type the empty parenthesis. So, I think what you want does not exist.

// I have a feeling something similar exists in Phobos
// but I could not find it.
//
// This is a reference to any variable.
struct MyRef(T) {
    T * ptr;

    void opAssign(T value) {
        *ptr = value;
    }

    void toString(scope void delegate(in char[]) sink) const {
        sink(*ptr);
    }
}

// This is a convenience function template so that
// the users don't have to say e.g. MyRef!string
// themselves. (See name() below.)
auto myRef(T)(ref T var) {
    return MyRef!T(&var);
}

class Dog {
    @property name() {
        return myRef(_name);
    }

    private {
        string _name;
    }
}

void main() {
    Dog d = new Dog();


    // Great: The following won't work.
    // d.name("poodle");


    // However, now there is the empty parenthesis. :(
    d.name() = "Poodle";

    import std.stdio;
    writeln(d.name);
}

Ali

Reply via email to