October 28
On 10/27/23 14:38, Hors wrote:
> It's impossible to tell if reading or writing an object's variable would call a function because of UFCS or @property. it just hurts because you can't know if it's a function call without looking at implementation.
> 
> The most basic example is
> ```
> obj.val = 1; // actually calls obj.setVal(1)
> assert(obj.val == 1); // actually calls obj.getVal(), assertion may fail if getVal or setVal is not implemented correctly. Which is unexpected
> ```
> ...

I guess you can write `*&obj.val = 1;` to make sure it is a field.

> To fix this hidden function craziness, UFCS needs to require parantheses, and property function needs to be removed entirely.

No. Abstractions are valuable. Being able to add (and remove) e.g., logging code after the fact onto an existing exposed public field is very useful.

October 28

On Friday, 27 October 2023 at 12:38:10 UTC, Hors wrote:

>

It's impossible to tell if reading or writing an object's variable would call a function because of UFCS or @property. it just hurts because you can't know if it's a function call without looking at implementation.

The most basic example is

obj.val = 1; // actually calls obj.setVal(1)
assert(obj.val == 1); // actually calls obj.getVal(), assertion may fail if getVal or setVal is not implemented correctly. Which is unexpected

To fix this hidden function craziness, UFCS needs to require parantheses, and property function needs to be removed entirely.

that's nothing compared to hidden variables

void main()
{
    struct S{ int a; }
    S get(){return S(0);}
    get.a = 42; // pointless assignment on a hidden variable
}
October 30

On Friday, 27 October 2023 at 13:37:14 UTC, Hors wrote:

>

On Friday, 27 October 2023 at 12:53:32 UTC, duckchess wrote:

>

On Friday, 27 October 2023 at 12:46:37 UTC, Hors wrote:

>

On Friday, 27 October 2023 at 12:40:39 UTC, duckchess wrote:

>

On Friday, 27 October 2023 at 12:38:10 UTC, Hors wrote:

>

[...]

why do you need to know if it is a function call?

Because it kills D's "fast", you may think you just accessing a normal variable but in fact you just calling a lot functions, it can hurt performance. Also for years, obj.val means a variable amd obj.m() means a function. There is no good reason to change that

if they can get inlined, they are, so it doesn't really change anything.

also there absolutely is a good reason for this.

if you have code

struct Foo {
 int x = 5;
}

Foo foo;
writeln(foo.x);

but later realize that you need to have x be a function for any reason, then you don't have to update your sourcecode everywhere. like this:

struct Foo {
int _x;
 int x( = 5) { assert(_x > 0); return _x;}
}

Foo foo;
writeln(foo.x);

It can be useful in some rare cases.

Either the code isn't being used, or refactoring is common. One of my slides at DConf 2023 was literally an extended version of "don't use parens for function calls", the reasoning being it hurts refactoring.

I'd go so far as to say that these days refactoring is orders of magnitude more likely to happen than optimising.

I think the answer to "how can I know if it's a function call" is "you shouldn't care unless a profiler told you so". Especially since reading data isn't necessarily free either (cache lines).

But sometimes it does more

>

harm than good, like string operations

str.toLower

calls toLower function which makes a new string every time you use it. So it's incorrect to tell everything can be solved with inline functions

1 2
Next ›   Last »