// this:

#define new_vec2(x, y) list(x, y)

#define vec2_add(u, v) new_vec2(u[1]+v[1], u[2]+v[2])

#define vec2_sub(u, v) new_vec2(u[1]-v[1], u[2]+v[2])

#define vec2_mag(u) sqrt(u[1]*u[1] + u[2]*u[2])

#define vec2_scale(u, s) new_vec2(u[1]*s, u[2]*s)

#define vec2_unit(u) vec2_scale(u, 1/vec2_mag(u))

// etc.

The problem I have with the above is that it's creating a new /list for every operation. Would it be better to instead have them calculate on vector u itself, instead of returning a (new) resultant vector?

// or this:

// (operations are made on the vector itself instead of making a new /vector datum)

vector

var comp[]

New() comp = args

proc

add(vector/v)

for(var/d in max(comp.len, v.comp.len))

comp[d] += v.comp[d]

scale(s)

for(var/d in comp.len)

comp[d] *= s

// etc.

With the first method, you can do multiple operations in just one line. For example, I have a gravity simulator. This is as much as I can remember off the top of my head, but I think it's a good example.

// src and m are objects with mass

// pos (position) is a (vector, /list) coordinate

var d[] = vec2_sub(m.pos, pos) // displacement vector

var r = vec2_mag(d) // distance between them

vel = vec2_add(vel, vec2_scale(d, grav_const * m.mass / r / r / r))

This makes a total of 3 /lists just to change one vector. One as a result of vec2_sub, another as a result of vec2_scale, and the last as a result of vec2_add. vel is a whole new /list in the end.

To do this with the second method:

var vector/d = new(m.pos.comp.Copy())

d.sub(pos)

var r = d.mag()

d.scale(grav_const * m.mass / r / r / r)

vel.add(d)

This makes only one vector, d for displacement, which is modified and eventually added to vel.

Which way is best? Is there even a significant difference? Can we have native vector support?

The second code snippet is pretty simple. I'd just give vectors a copy proc so you can say m.pos.copy() instead of new(m.pos.comp.Copy()).

You could also add procs that operate on vectors in addition to procs that belong to vector objects. The catch is that these procs have to return new vector objects, but sometimes that's what you want:

This would make your second snippet even simpler.

I'm not sure how much of a difference this all makes. If one method takes twice as much time you might consider that significant, but these vector operations shouldn't be the bottleneck in your program anyway.