D style - member functions

2023-04-26 Thread DLearner via Digitalmars-d-learn

Consider:
```
struct S1 {
   int A;
   int B;
   int foo() {
  return(A+B);
   }
}

struct S2 {
   int A;
   int B;
}
int fnAddS2(S2 X) {
   return (X.A + X.B);
}

void main() {
   import std.stdio : writeln;

   S1 Var1 = S1(1, 2);
   writeln("Total Var1 = ", Var1.foo());

   S2 Var2 = S2(1, 2);
   writeln("Total Var2 = ", fnAddS2(Var2));

   return;
}
```

Of the two ways shown of producing the total from the same 
underlying structure, which is the better style?


Further, do we care about the situation where there are many 
variables of type 'S', which presumably means the function code 
generated from S1 gets duplicated many times, but not so with S2?





Re: D style - member functions

2023-04-26 Thread H. S. Teoh via Digitalmars-d-learn
On Wed, Apr 26, 2023 at 06:24:08PM +, DLearner via Digitalmars-d-learn 
wrote:
> Consider:
> ```
> struct S1 {
>int A;
>int B;
>int foo() {
>   return(A+B);
>}
> }
> 
> struct S2 {
>int A;
>int B;
> }
> int fnAddS2(S2 X) {
>return (X.A + X.B);
> }
> 
> void main() {
>import std.stdio : writeln;
> 
>S1 Var1 = S1(1, 2);
>writeln("Total Var1 = ", Var1.foo());
> 
>S2 Var2 = S2(1, 2);
>writeln("Total Var2 = ", fnAddS2(Var2));
> 
>return;
> }
> ```
> 
> Of the two ways shown of producing the total from the same underlying
> structure, which is the better style?

Either way works, it doesn't really matter.  The slight difference is
that the member function is preferred when resolving a symbol, so if
there's a module-level function called `foo` that takes S1 as a
parameter, the member function would be called instead.


> Further, do we care about the situation where there are many variables
> of type 'S', which presumably means the function code generated from
> S1 gets duplicated many times, but not so with S2?

This is false. Member functions are only instantiated once in the entire
program, not with every instance of S.

(Template functions may be instantiated more than once, but that's still
only once per combination of template arguments, not once per instance
of the enclosing type.)


T

-- 
MAS = Mana Ada Sistem?


Re: D style - member functions

2023-04-26 Thread Jacob Shtokolov via Digitalmars-d-learn

On Wednesday, 26 April 2023 at 18:24:08 UTC, DLearner wrote:

Consider:
```
struct S1 {
   int A;
   int B;
   int foo() {
  return(A+B);
   }
}

struct S2 {
   int A;
   int B;
}
int fnAddS2(S2 X) {
   return (X.A + X.B);
}


There are scenarios that won't let you use the second form, e.g. 
putting your struct under the `with()` statement:


```d
with (S1) {
auto sum = foo(); // Works correctly
}

with (S2) {
auto sum = foo(); // Error: function foo(S s) is not callable 
using argument types ()

}
```

In this case, the first option will be better. But there are no 
real "best practices" defined AFAIK.


However, the second form let you generalize the pattern by using 
template declaration:


```d
int fnAdd(T)(T v) {
return (v.A + v.B); // Doesn't matter what type is this if it 
has both members A and B

}

s1.fnAdd();
s2.fnAdd();
```


Re: D style - member functions

2023-04-26 Thread Basile B. via Digitalmars-d-learn

On Wednesday, 26 April 2023 at 18:24:08 UTC, DLearner wrote:

Consider:
```
struct S1 {
   int A;
   int B;
   int foo() {
  return(A+B);
   }
}

struct S2 {
   int A;
   int B;
}
int fnAddS2(S2 X) {
   return (X.A + X.B);
}

void main() {
   import std.stdio : writeln;

   S1 Var1 = S1(1, 2);
   writeln("Total Var1 = ", Var1.foo());

   S2 Var2 = S2(1, 2);
   writeln("Total Var2 = ", fnAddS2(Var2));

   return;
}
```

Of the two ways shown of producing the total from the same 
underlying structure, which is the better style?



To make both version really equivalent you should rather write

int fnAddS2(ref S2 X) {
return (X.A + X.B);
}

the `this` for the member functions is a reference as obviously 
you want to eventually mutate the members and not their copy. 
What happened in your `fnAddS2` is that the whole stuff was 
blitted and mutation of the members would have no effect on the 
argument used in the call.


Further, do we care about the situation where there are many 
variables of type 'S', which presumably means the function code 
generated from S1 gets duplicated many times, but not so with 
S2?


Your presumption is wrong. The code generated for a function is 
not regenerated per instance. One version is enough to handle all 
the instances as the instance is itself a parameter of the 
function. What is happening for `foo()`, i.e the member function, 
is that there is an hidden parameter. Depending on the language 
the way the hidden argument is read might be slightly different 
but you really should consider that


struct S1 {
int A;
int B;
int foo() {
   return(A+B);
}
}

is like

struct S1 {
int A;
int B;
static int foo(ref S1 that) {
   return(that.A+that.B);
}
}

or

struct S1 {
int A;
int B;
}

int foo(ref S1 that) {
   return(that.A+that.B);
}

One problem of the hidden parameter is that for example

int foo(const ref S1 that) {
   return(that.A+that.B);
}

cannot be expressed (at first glance)... how to qualify `const` 
something that is hidden ? It's actually possible using a member 
function attribute:


struct S1 {
int A;
int B;
int foo() const /*const is for the hidden parameter*/ {
   return(A+B);
}
}



quick question, probably of little importance...

2023-04-26 Thread WhatMeWorry via Digitalmars-d-learn
I just need an even/odd functionality. Don't think D has a 
built-in operator.


// Found this C code online.

int isEven(int num)
{
return !(num & 1);
}

// found this in std.functional.unaryFun

alias isEven = unaryFun!("(a & 1) == 0");
assert(isEven(2) && !isEven(1));

If interested just in speed, is either one faster?


Re: quick question, probably of little importance...

2023-04-26 Thread Richard (Rikki) Andrew Cattermole via Digitalmars-d-learn

Don't forget ``num % 2 == 0``.

None should matter, pretty much all production compilers within the last 
30 years should recognize all forms of this and do the right thing.


Re: quick question, probably of little importance...

2023-04-26 Thread WhatMeWorry via Digitalmars-d-learn
On Wednesday, 26 April 2023 at 23:02:07 UTC, Richard (Rikki) 
Andrew Cattermole wrote:

Don't forget ``num % 2 == 0``.

None should matter, pretty much all production compilers within 
the last 30 years should recognize all forms of this and do the 
right thing.


Thanks. Fastest reply ever! And I believe across the world?   I 
suppose my examples required overhead of a function call. So 
maybe num % 2 == 0 is fastest?


Re: quick question, probably of little importance...

2023-04-26 Thread H. S. Teoh via Digitalmars-d-learn
On Wed, Apr 26, 2023 at 11:07:39PM +, WhatMeWorry via Digitalmars-d-learn 
wrote:
> On Wednesday, 26 April 2023 at 23:02:07 UTC, Richard (Rikki) Andrew
> Cattermole wrote:
> > Don't forget ``num % 2 == 0``.
> > 
> > None should matter, pretty much all production compilers within the
> > last 30 years should recognize all forms of this and do the right
> > thing.
> 
> Thanks. Fastest reply ever! And I believe across the world?   I
> suppose my examples required overhead of a function call. So maybe num
> % 2 == 0 is fastest?

If performance matters, you'd be using an optimizing compiler. And
unless you're hiding your function implementation behind a .di, almost
all optimizing compilers would inline it, so you shouldn't even be able
to tell the difference.


T

-- 
Without outlines, life would be pointless.


Re: quick question, probably of little importance...

2023-04-26 Thread Richard (Rikki) Andrew Cattermole via Digitalmars-d-learn

On 27/04/2023 11:07 AM, WhatMeWorry wrote:
On Wednesday, 26 April 2023 at 23:02:07 UTC, Richard (Rikki) Andrew 
Cattermole wrote:

Don't forget ``num % 2 == 0``.

None should matter, pretty much all production compilers within the 
last 30 years should recognize all forms of this and do the right thing.


Thanks. Fastest reply ever! And I believe across the world?   I suppose 
my examples required overhead of a function call. So maybe num % 2 == 0 
is fastest?


Indeed, all the way from New Zealand.

I wouldn't bother timing this. A compiler will rewrite it and emit 
whatever instructions it thinks is best for a given cpu target that you 
select. This is one of those things that was solved 30 years ago :)