On 4/16/2010 10:41 PM, Andrei Alexandrescu wrote:
> Generally I'd strongly suggest making operations free generic functions
> instead of members.
I disagree on this one. It unnecessarily adds more names to an outer
namespace and makes code less readable:
vec1.cross(vec2).project(vec3).length();
vs:
length(project(cross(vec1, vec2), vec3);
The first reads naturally while the second is more like polish notation
and is easier to forget parentheses, as I did.

On 4/19/2010 6:43 AM, Lars T. Kyllingstad wrote:
> IMO, general vectors/matrices should be structs wrapping a pointer to
> the data:
>
> struct Vector(T)
> {
> T* ptr;
> size_t length;
> size_t stride;
> }
>
> Low-dimensional fixed-size vectors should probably be value types.
I think it would be confusing to have some vectors as value and others
as reference types, unless they were different types in the library itself.
I've always used two template parameters, one for type and another for
size, but almost all my vectors are only 2-4 components.
struct Vector(T, S)
{
T[S] values;
}
You can union things out from there so you can still have your .x/y/z
properties without the overhead of a function call.

On 04/19/2010 02:41 PM, Eric Poggel wrote:
> On 4/16/2010 10:41 PM, Andrei Alexandrescu wrote:
>> Generally I'd strongly suggest making operations free generic functions
>> instead of members.
>
> I disagree on this one. It unnecessarily adds more names to an outer
> namespace and makes code less readable:
>
> vec1.cross(vec2).project(vec3).length();
>
> vs:
>
> length(project(cross(vec1, vec2), vec3);
>
> The first reads naturally while the second is more like polish notation
> and is easier to forget parentheses, as I did.
Notationally I agree - but you are (or at least should be) able to
invoke a nonmember as if it were a member.
Andrei

Eric Poggel wrote:
> On 4/19/2010 6:43 AM, Lars T. Kyllingstad wrote:
>> IMO, general vectors/matrices should be structs wrapping a pointer to
>> the data:
>>
>> struct Vector(T)
>> {
>> T* ptr;
>> size_t length;
>> size_t stride;
>> }
>>
>> Low-dimensional fixed-size vectors should probably be value types.
>
> I think it would be confusing to have some vectors as value and others
> as reference types, unless they were different types in the library itself.
That was the idea, to have *both* a generic Vector(T) type and
specialised Vector2D(T) and Vector3D(T) types.
-Lars

Eric Poggel Wrote:
> On 4/16/2010 10:41 PM, Andrei Alexandrescu wrote:
> > Generally I'd strongly suggest making operations free generic functions
> > instead of members.
>
> I disagree on this one. It unnecessarily adds more names to an outer
> namespace and makes code less readable:
>
> vec1.cross(vec2).project(vec3).length();
>
> vs:
>
> length(project(cross(vec1, vec2), vec3);
>
> The first reads naturally while the second is more like polish notation
> and is easier to forget parentheses, as I did.
For the record: at least for cross(), I prefer the latter version. It always seemed awkward to me to make a symmetric (ok, anti-symmetric in this case) operation like this a member, because vec1.cross(vec2) doesn't look symmetric at all anymore. Furthermore, in the absence of an actual operator for the cross product (which we can't have, unless we resort to overloading abuse), the latter is closer to mathematical notation.
-- Clemens

> For the record: at least for cross(), I prefer the latter version. It always seemed awkward to me to make a symmetric (ok, anti-symmetric in this case) operation like this a member, because vec1.cross(vec2) doesn't look symmetric at all anymore. Furthermore, in the absence of an actual operator for the cross product (which we can't have, unless we resort to overloading abuse), the latter is closer to mathematical notation.
>
> -- Clemens
I also prefer the second version.
Don't we like to write max(a, b) and not a.max(b) ?
Ideally I'd like to be able to write operation(x) or operation(x, y) indifferently with x and y being a scalar or a small vector type, like in shader languages.
I tried with min/max but failed due to ambiguous overloading:
T min(T)(T a, T b)
vs
vec2!(T) min(T)(vec2!(T) a, vec2!(T) b)
and finally changed names (min, min2, min3...) to overcome this.
D has modules, overload sets, specialization etc... so maybe someone more skilled can figure how to sort it out.

Clemens wrote:
> Eric Poggel Wrote:
>
>> On 4/16/2010 10:41 PM, Andrei Alexandrescu wrote:
>>> Generally I'd strongly suggest making operations free generic functions
>>> instead of members.
>> I disagree on this one. It unnecessarily adds more names to an outer
>> namespace and makes code less readable:
>>
>> vec1.cross(vec2).project(vec3).length();
>>
>> vs:
>>
>> length(project(cross(vec1, vec2), vec3);
>>
>> The first reads naturally while the second is more like polish notation
>> and is easier to forget parentheses, as I did.
>
> For the record: at least for cross(), I prefer the latter version. It always seemed awkward to me to make a symmetric (ok, anti-symmetric in this case) operation like this a member, because vec1.cross(vec2) doesn't look symmetric at all anymore. Furthermore, in the absence of an actual operator for the cross product (which we can't have, unless we resort to overloading abuse), the latter is closer to mathematical notation.
>
> -- Clemens
Oddly I tend to like v1.cross(v2) because for me that feels closer to
the the mathematical notation with the cross sitting between the two
vectors. But for D at least it's a none issue because both will work.