Re: Is there a way to enforce UFCS?

2023-01-06 Thread Salih Dincer via Digitalmars-d-learn

On Friday, 6 January 2023 at 15:31:09 UTC, Salih Dincer wrote:
If you don't want to get the above output you should use the 
previous example. But don't forget to connect alias and opCall. 
For example, you can use @property in version 2.0.83 without 
all the fanfare.




I forgot one thing: if you implement getter/setter like below use 
inout as well.


Actually, this must be a bit of a bug and neither I nor anyone 
else reported it!  Ok they will say don't use @property.  But 
this time the screen output will be like typeid.  If you don't 
want that to happen, you have to use inout in getter functions.


```d
struct Funy(T)
{
  this(T x) {
    value = x;
  }

  T value;
  alias opCall this;

  @property:
  T opCall(T n)
  {
    return value = n;
  }

  T opCall() inout
  {
return value;
  }
}
```

SDB@79




Re: Is there a way to enforce UFCS?

2023-01-06 Thread Salih Dincer via Digitalmars-d-learn
On Thursday, 5 January 2023 at 23:05:17 UTC, thebluepandabear 
wrote:

them or remove them.


I agree, forbidding function call syntax would be a great 
usecase for `@property`.


It will probably never get implemented though.


In older versions, it worked when printing values ​​with writeln. 
But due to an error in formattedWrite, the program breaks. So I 
stopped using @property. For example, you can't see the 
difference in:


```d
struct Funy(T)
{
  import std.conv : to;
  this(X)(X x) {
    value = x.to!T;
  }
  T value;
  alias value this; // [a] getter
  //@property
  T opAssign(T x) { // [b] setter
return value = x;
  }
  alias opCall = opAssign; /* hack: `opAssign` methods
  are not used for initialization,
  but for subsequent assignments
  [c] incrementor: */
  //@property
  T opOpAssign(string op: "+", X)(X x) {
return value = value + x.to!T;
  }
}

import std.stdio;
void main()
{
  auto funy = Funy!uint(20);
  funy.value.writeln; // 20
  funy = 10;
  funy.value.writeln; // 1

  class Fun
  {
Funy!int n;
this(int i)
{
  n = i; // or:
  n(i + 1);
}
  }

  auto fun = new Fun(-2);
  fun.n.writeln; // -1
  fun.n += 19.999;
  fun.n.writeln; // 18
}
```

Let's continue the fun...

```d
struct Funy(T)
{
  this(T x) { value = x; }
  T value;
  alias opCall this;

  //@property:
  T opCall(T n) { return value = n; }
  T opCall() { return value; }
}

import std.stdio;
void main()
{
  auto funy = Funy!uint(20);
  funy.value.writeln; // 20
  funy = 10;
  funy.value.writeln; // 1

  class Fun
  {
Funy!int n;
this(int i) {
  n = i; // or:
  n(i + 1);
}
  }

  auto fun = new Fun(-2);
  fun.n.writeln; // -1
  fun.n = 20;
  fun.n.writeln; // 0
} /* PRINTS:
20
10
Funy!int(-1)
Funy!int(20)
```

If you don't want to get the above output you should use the 
previous example. But don't forget to connect alias and opCall. 
For example, you can use @property in version 2.0.83 without all 
the fanfare.


SDB@79


Re: Is there a way to enforce UFCS?

2023-01-05 Thread thebluepandabear via Digitalmars-d-learn

them or remove them.


I agree, forbidding function call syntax would be a great usecase 
for `@property`.


It will probably never get implemented though.


Re: Is there a way to enforce UFCS?

2023-01-05 Thread H. S. Teoh via Digitalmars-d-learn
On Thu, Jan 05, 2023 at 02:32:17PM +, Dom DiSc via Digitalmars-d-learn 
wrote:
[...]
> I think this is really another usecase for @property: we should forbid the
> function call syntax for them (so one needs to use them like a variable).
[...]
> Properties are not functions. If you want a function, use a function. If
> @properties would be the same as functions, they are superfluous garbage.
> Either make something useful out of them or remove them.

We have been talking about deprecating and removing @property for years
now.  Somebody just has to bite the bullet and push it through the
deprecation process...

... OR come up with a DIP that implements @property in a sane, fully
worked out way, not the half-hearted, incomplete, leaky implementation
that it is today.

//

In my own code, I've stopped bothering with @property for the most part.
Parentheses are optional for argumentless functions in general anyway,
so there's really no need to write @property on anything. This works:

struct S {
private int _x;
int x() { return _x; }
}

S s;
int y = s.x;

The only significant thing @property does right now is to add confusion
when the unary & operator is used or when the property function returns
a delegate.  Not worth the trouble, I say.  Just don't use @property at
all, plain old member functions work just fine.


T

-- 
Some ideas are so stupid that only intellectuals could believe them. -- George 
Orwell


Re: Is there a way to enforce UFCS?

2023-01-05 Thread Dom DiSc via Digitalmars-d-learn

On Wednesday, 4 January 2023 at 14:21:46 UTC, bauss wrote:

```d
class Foo {
  int bar;

  void setBar(Foo foo, int value) {
foo.bar = value;
  }
}

void main() {
  foo.setBar(100); // Not UFCS - just method call to the class
  foo.setBar = 100; // Not UFCS - simply a setter function call 
(equal to the above)

  setBar(foo, 100); // Error
}
```


I think this is really another usecase for @property: we should 
forbid the function call syntax for them (so one needs to use 
them like a variable).
This is useful to enable library authors to enforce this, so that 
if a property is replaced by a variable (e.g. during 
refactoring), it's not a braking change for the users of the 
library.
Else it could be that setters or getters are directly called, 
which would not compile anymore with a variable (that doesn't 
have getters or setters).


@properties are intended to be used like variables - the only 
differences (and the reason why they exist) is the read or write 
protection they provide, and that they may be calculated on the 
fly (not stored in memory at all). That they are realized with a 
construct that looks similar to (a pair of) functions should be 
completely transparent for the user of a library.


Properties are not functions. If you want a function, use a 
function. If @properties would be the same as functions, they are 
superfluous garbage. Either make something useful out of them or 
remove them.




Re: Is there a way to enforce UFCS?

2023-01-04 Thread thebluepandabear via Digitalmars-d-learn

On Wednesday, 4 January 2023 at 14:21:46 UTC, bauss wrote:
On Wednesday, 4 January 2023 at 03:42:28 UTC, thebluepandabear 
wrote:

...

My question is: is there a way to enforce UFCS-syntax?


None of your code actually uses UFCS.

This is UFCS:

```
class Foo {
  int bar;
}

void setBar(Foo foo, int value) {
  foo.bar = value;
}

void main() {
  foo.setBar(100); // UFCS
  setBar(foo, 100); // Non-UFCS (Above expands to this)
}
```

This is not UFCS but just class method calling:

```
class Foo {
  int bar;

  void setBar(Foo foo, int value) {
foo.bar = value;
  }
}

void main() {
  foo.setBar(100); // Not UFCS - just method call to the class
  foo.setBar = 100; // Not UFCS - simply a setter function call 
(equal to the above)

  setBar(foo, 100); // Error
}
```

Also note that @property doesn't really do anything now and 
there's even talk about deprecating it. Althought I personally 
still use it, then it doesn't have much of a function and none 
of your code is affected if you remove it.


Yeah I got mixed up.

I think a good use of `@property` is for code clarity, it makes 
it clear which parts of your code should be treated as properties.


Re: Is there a way to enforce UFCS?

2023-01-04 Thread bauss via Digitalmars-d-learn
On Wednesday, 4 January 2023 at 03:42:28 UTC, thebluepandabear 
wrote:

...

My question is: is there a way to enforce UFCS-syntax?


None of your code actually uses UFCS.

This is UFCS:

```
class Foo {
  int bar;
}

void setBar(Foo foo, int value) {
  foo.bar = value;
}

void main() {
  foo.setBar(100); // UFCS
  setBar(foo, 100); // Non-UFCS (Above expands to this)
}
```

This is not UFCS but just class method calling:

```
class Foo {
  int bar;

  void setBar(Foo foo, int value) {
foo.bar = value;
  }
}

void main() {
  foo.setBar(100); // Not UFCS - just method call to the class
  foo.setBar = 100; // Not UFCS - simply a setter function call 
(equal to the above)

  setBar(foo, 100); // Error
}
```

Also note that @property doesn't really do anything now and 
there's even talk about deprecating it. Althought I personally 
still use it, then it doesn't have much of a function and none of 
your code is affected if you remove it.


Re: Is there a way to enforce UFCS?

2023-01-03 Thread Ali Çehreli via Digitalmars-d-learn

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();
}

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



Is there a way to enforce UFCS?

2023-01-03 Thread thebluepandabear via Digitalmars-d-learn

Say you have the following class which represents a dog :

```D
class Dog {
@property {
string name();

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

private {
string _name;
}
}
```

And you have the following code with constructs a `Dog` object:

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

d.name = "Poodle";
writeln(d.name);
}
```

In the code we can see that we have utilized UFCS (universal 
function call syntax) to set the properties for the object. This 
feature is great. We have also used D's `@property` annotation 
which gives us some other advantages that you can see in the 
documentation.


The issue I have is that UFCS is not enforced, which I thought 
would be a rather good use for the `@property` annotation. This 
means that we can do the following in our code:


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

d.name("poodle");
writeln(d.name());
}
```

I prefer the UFCS version over the non-UFCS version since it is 
more clear that it is a property and it matches closely with the 
official D style guide.


I am disappointed that `@property` does not enforce UFCS, as I 
believe that it would add to its usefulness. Sometimes throughout 
my codebase I get confused and write properties in non-UFCS 
syntax, which bugs me a bit.


My question is: is there a way to enforce UFCS-syntax?