Is there a way to enforce UFCS?

Ali Çehreli acehreli at yahoo.com
Wed Jan 4 04:37:09 UTC 2023


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



More information about the Digitalmars-d-learn mailing list