April 19, 2010
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.
April 19, 2010
Also, the first syntax will give you intellisense in many IDE's.

April 19, 2010
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.
April 19, 2010
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
April 19, 2010
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
April 20, 2010
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
April 20, 2010
> 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.


April 21, 2010
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.


1 2 3
Next ›   Last »