Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Immutable version #18

Open
neojski opened this issue May 19, 2015 · 10 comments
Open

Immutable version #18

neojski opened this issue May 19, 2015 · 10 comments

Comments

@neojski
Copy link

neojski commented May 19, 2015

It was very annoying for me that methods like add or divide modified the vector. My temporary solution is my immutable-vector2d library. Do you have any ideas as how to merge my project into this one?

@maxkueng
Copy link
Owner

Hi. Yes, the vectors are mutable on purpose. The idea behind it is that,.. let's say you have a space ship that moves. So the ship has a position vector and a and a velocity vector. To move the ship you add the velocity vector to the position vector:

var ship = {
  position: new Victor(100, 200),
  velocity: new Victor(1, 0),
  move: function () {
    this.position.add(this.velocity);
  }
};

setInterval(function () {
  ship.move();
  draw();
}, 1000 / 16);

instead of doing:

// let's assume Victor is immutable
var ship = {
  ...
  move: function () {
    this.position = this.position.add(this.velocity);
  }
};

...

Do you think this is a bad idea?

You can use the .clone() method if you want to create a new vector based on another.

var ship = {
  ...
  move: function () {
    // add only half the velocity without modifying the velocity
    this.position.add(this.velocity.clone().divide(new Victor(2, 2)));
  }
};

...

What are your thoughts?

@neojski
Copy link
Author

neojski commented May 21, 2015

Sure, I'm not saying mutability is inherently bad. My scenario where I prefer things to be immutable is more math style:

var a = Vector(23, 12);
var b = Vector(25, 13);
var c = a.normalize().add(b.normalize());

to calculate angle bisector. With mutable stuff I need

var a = Vector(23, 12);
var b = Vector(25, 13);
var c = a.clone().normalize().add(b.clone().normalize());

With more calculations it's clone everywhere. Most likely we cannot do anything about that except for introducing API for both mutable and immutable operations. In that case, I think, I prefer them to be separate libraries.

@ahvonenj
Copy link

I would also prefer if the methods such as add or divide would not modify the vector. I think they should be immutable by default as every library with vector that I have ever used behaves like that.

@yukulele
Copy link

I made a Immutable vector library https://github.com/yukulele/Vector.js

@huiwang
Copy link

huiwang commented Mar 9, 2016

i agree to have an immutable version. this just makes things much more simpler to reason about.

this is extremely useful when you want to simulate something. immutability allows to travel back to the time.

@philj0st
Copy link

+1 for immutability feature. Will be awesome now that functional Javascript is becoming more and more popular. see Redux and co.
there are also a lot of games using functional programming now .. and i think games are definitly one of your library's core audiences 😄

@chinoto
Copy link

chinoto commented Aug 13, 2018

Shouldn't this be closed? Victor has been mutable for years, so changing it would break functionality for existing users. Besides, @neojski, @yukulele, and @graue have filled the need for immutable vectors.

@YarekTyshchenko
Copy link

Gah, just been bitten by this. I was really surprised that operation are mutable. Should clearly mention this on the website

@rmkane
Copy link

rmkane commented Oct 4, 2022

They are mutable, because of the ability to chain.

It would be nice to state that the library is not immutable on the README or the docs; up-front.

If you check out the docs e.g. the add method, it states that the vector is added in-place:

.add(vector) [chainable]

Adds another vector to itself.

My opinion

I will side with the author and say that this:

this.position.add(this.velocity);

Is easier to read than:

this.position = this.position.clone().add(this.velocity); // or
this.position = Victor.fromObject(this.position).add(this.velocity);

@chinoto
Copy link

chinoto commented Oct 5, 2022

The ability to chain has nothing to do with mutability, it's just a matter of whether the methods return this (or a new object in the case of an immutable version). If the methods returned nothing, then they would have to mutate this, or do a weird C-like thing like this:

let a = new Victor(1, 2);
let b = new Victor(3, 4);
let ret = new Victor(0, 0);
a.add(b, ret);
// ret has been modified by the add method

Though I think in C, the ret value is generally uninitialized, which we can't do in JavaScript due to the lack of pointers, but objects are shared by reference, so ret could be initialized as {value: null} and then a method can set value to whatever it wants.

Totally agree with your opinion examples. Would be nice if JavaScript supported operator overloading, then you could do this.position += this.velocity.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

9 participants