- 
          
- 
                Notifications
    You must be signed in to change notification settings 
- Fork 3.6k
Description
[2.0] Stabilize the set() method of p5.Vector
The set() method of p5.Vector behaves confusingly in the context of p5.js 2.x, and this behavior is the result of undocumented breaking changes. General stabilization to align with the rest of 2.x is likely warranted.
Confusing 1.x behavior
The 1.x version of set() actively modifies components that are left unspecified, in contrast with how methods like add() and mult() behave under similar circumstances.
function setup() {
  let v = createVector(1.01, 1.01, 5);
  v.set(1, 1);
  // Plausible output: `p5.Vector Object : [1, 1, 5]`
  // Actual output: `p5.Vector Object : [1, 1, 0]`
  console.log(v.toString());
}Confusing 2.x behavior
The 2.x version is still documented as maintaining the 1.x behavior, although it does not behave that way. Instead, it mutates the dimension of the vector whenever dimensions do not match. This will often be an unintended side effect, since the name set suggests the method sets existing properties (including x, y, and z), rather than eliminating or defining new properties.
function setup() {
  let v = createVector(1.01, 1.01, 5);
  v.set(1, 1);
  // Plausible output: `[1, 1, 5]`
  // Actual output: `[1, 1]`
  console.log(v.toString());
}The unintended side effect above is likely to occur, since users accustomed to the behavior of add() in 1.x may assume the unspecified components will be unchanged.
In addition to accidentally cropping the vector in place, it's also possible to accidentally promote the vector to a higher dimension.
function setup() {
  let v = createVector(1.01, 1.01);
  let w = createVector(1, 1, 0);
  v.set(w);
  // Plausible output: `[1, 1]`
  // Actual output: `[1, 1, 0]`
  console.log(v.toString());
}The unintended side effect above is also reasonably likely, as users may expect only existing components to be set.
Proposed solution: Standard broadcasting rules
A simple, useful, and extensible approach is to have set() adhere to the standard broadcasting rules proposed in #8159 for other elementwise operations (set() may be viewed as an elementwise assignment operation). This will work equally well for vectors, matrices, and tensors.1
function setup() {
  let v = createVector(1.01, 1.01, 5);
  v.set(1, 1);
  /* Error: A 3D vector can only be set in two possible ways:
  (a) with exactly 3 elements (as a list of numbers, an array, or a `p5.Vector` object)
  (b) with a single element (its value will be used for all 3 components). 
  To fix this error, extra elements may be passed directly to `set()`, 
  or if a `p5.Vector` object is passed, it may be extended with `pad()`.
  */
}function setup() {
  let v = createVector(1.01, 1.01);
  v.set(1, 1, 0);
  /* Error: A 2D vector can only be set in two possible ways:
  (a) with exactly 2 elements (as a list of numbers, an array, or a `p5.Vector` object)
  (b) with a single element (its value will be used for all 2 components). 
  To fix this error, fewer elements may be passed directly to `set()`, 
  or if a `p5.Vector` object is passed, it may be cropped with `crop()`.
  */
}The examples above prevent unintended side effects, in favor of more useful methods that unambiguously mutate dimension, such as crop() and pad(), which have already been proposed as a convenient "repair toolkit" to help users fix errors.
Standard broadcasting also facilitates a new, very common use case:
function setup() {
  let v = createVector(0, 0, 0, 0, 0);
  v.set(1);
  // Output: `[1, 1, 1, 1, 1]`
  console.log(v.toString());
}Next steps (blocking issues)
- Reach a consensus on the general broadcasting policy proposed in #8159.
-  Reach consensus on the API proposed in #8152, as it includes the set()method.
-  Reach a consensus on applying the broadcasting policy to set(), as proposed here.
The error messages indicated above also reference pad() and crop() methods, which do not exist yet. However, that doesn't necessarily need to block progress on set(); a separate issue could be opened to update the error messages at a later time.
Edit: Added "Next steps" section.
Footnotes
- 
This approach is also similar to the set()method ofp5.Image, which can set a single pixel or the whole image. However, the single pixel is not broadcast. In a future 3.0 release, we could potentially create a more intuitive API by providing e.g.setPixel()for the one-pixel case to match thesetElement()method of vectors, matrices, tensors, series, and sheets. (Here,setElement()is a proposed API for setting an individual element.) Theset()method ofp5.Imagecould then support broadcasting like the otherset()methods. ↩
Metadata
Metadata
Assignees
Type
Projects
Status