www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.learn - What's the right way for doing this in D?

reply "Namespace" <rswhite4 googlemail.com> writes:
I liked to know which of this two methods is more common to you, 
A or B:

Method A:
----
import std.stdio;

struct Vector2f {
public:
	float x;
	float y;

	float dot(ref const Vector2f vec) const {
		return this.x * vec.x + this.y * vec.y;
	}
}
----

Method B:
----
struct Vector2f {
public:
	float x;
	float y;
}

float dot(ref const Vector2f lhs, ref const Vector2f rhs) {
	return lhs.x * rhs.x + lhs.y * rhs.y;
}
----

Until now I used Method A, but because of UFCS and the fact, that 
the dot product doesn't affect the object, I thought about which 
way would make more sense. I still like Method A but I'm curious 
what you think.
Aug 24 2013
next sibling parent "bearophile" <bearophileHUGS lycos.com> writes:
Namespace:

 I liked to know which of this two methods is more common to 
 you, A or B:
Both ways work. I usually prefer the first one because it's more DRY. I use external functions when I write functions that are meant to work on more different structs, or to reduce template bloat when a function works only on not templated values. Note that fields and methods are public on default in structs, so you don't need the "public:" tag. Bye, bearophile
Aug 24 2013
prev sibling parent Andrej Mitrovic <andrej.mitrovich gmail.com> writes:
On 8/24/13, Namespace <rswhite4 googlemail.com> wrote:
 Until now I used Method A, but because of UFCS and the fact, that
 the dot product doesn't affect the object, I thought about which
 way would make more sense. I still like Method A but I'm curious
 what you think.
Note also that UFCS can introduce the function hijacking protection. For example, if you have: ----- module a; import b; struct A { } void test(A a) { } void main() { B b; b.test(); } ----- ----- module b; struct B { } void test(B b) { } ----- This will result in: a.d(10): Error: function a.test (A a) is not callable using argument types (B) I tend to use UFCS when I need the function to handle multiple types - e.g. a templated function that should be used with UFCS, or when I want to add UFCS syntax to a type which I have no control over (e.g. a Phobos or 3rd party library type). Otherwise if your function is only ever going to be used with a single type you might as well put it as a member function, unless you prefer otherwise (e.g. some people dislike indentation). Btw, I thought UFCS might disable using the 'super' syntax, but to my surprise it actually works: ----- class A { } void foo(A a) { } class B : A { void test() { super.foo(); // ok } } void main() { } ----- Pretty cool. Finally a note about the documentation. If you put your functions as member functions, the documentation becomes part of the aggregate type that they're members of. So it might make the documentation easier to read.
Aug 24 2013