P5.js choosing randomly from an array of functions

hi, first post!
i have declared an array of functions like

funx = [func1, func2, ...];

in the draw loop i want to call theese randomly like

funx[random(funx)]();

it works when i call the functions by index like

funx[0]();

would need some help to accomplish this.
thanks

1 Like

Hello, @okkobroderson, and welcome to the Processing Forum!

For starters, try this:

// define three functions.
function func1() {
  background(255, 0, 0);
}

function func2() {
  background(0, 255, 0);
}

function func3() {
  background(0, 0, 255);
}

let funcs = [func1, func2, func3];

function setup() {
  frameRate(2); // slow frame rate.
}

function draw() {
  random(funcs)(); // during each frame, select a function randomly and call it.
}

thank you very much @javagar

random(funcs)();

did the trick:)

1 Like

Yes, and you can pass an argument to the selected function, as follows, provided that the function was defined to accept an argument:

  random(funcs)(frameCount);

ah, that’s good to know!
opens up some more possibilities…

…but also brings up more qustions.
in case the different functions require different sets of arguments.
how can we know about which function was picked by random(funcs), to provide the right arguments?

1 Like
1 Like

Another possibility, especially if the functions require various combinations of numbers and types of arguments, is to create an object, with the names of the functions as strings that serve as keys, and the types of arguments, as Arrays of strings associated with each key. Then choose randomly from the keys in the object, and use the Array of argument types associated with that key to assemble an appropriate function call. It may be complicated, but it could be fun. :slight_smile:

EDIT (2x on November 22, 2021):

For yet another strategy, try the code below. It randomly chooses functions paired with their arguments.

// three functions that draw shapes
function rect_maker(x, y, r, g, b) {
  fill(r, g, b);
  rect(x, y, 40, 40);
}

function ellipse_maker(x, y, w, h) {
  fill(random(256), random(256), random(256), random(256));
  ellipse(x, y, w, h);
}

function line_maker() {
  line(random(width), random(height), random(width), random(height));
}

function setup() {
  createCanvas(240, 240);
  strokeWeight(4);
  stroke(0);
  frameRate(1);
  rectMode(CENTER);
}

function draw() {
  // array of arrays of functions with randomly-valued arguments for each
  let funcs_and_args = [
                        [rect_maker, [random(width), random(height), random(256), random(256), random(256)]],
                        [ellipse_maker, [random(width), random(height),random(width / 4), random(height / 4)]],
                        [line_maker, []]
                       ];
  // randomly choose a function with arguments pair
  let f_and_a = random(funcs_and_args);
  // call the chosen function, passing its arguments to it; use destructuring
  f_and_a[0](...f_and_a[1]);
}

funcs_with_args

To understand this line …

  f_and_a[0](...f_and_a[1]);

… see …

thanks you! @GoToLoop

1 Like

wow, that’s cool!
thank you very much for your efforts @javagar

that should provide enough fun for long winter evenings:)

1 Like

Below is another scheme that utilizes an array of anonymous functions, each of which calls one of the named functions with a set of required arguments.

This pattern may be easy to revise and maintain, since adding a new function call to the array merely requires copying one of the existing elements of the array and applying some modifications. It would also be simple to add a new named function by defining it, and then by following one of the existing patterns in the array to add an appropriate function call.

p5.js Code:

// three named shape maker functions with various numbers of arguments
function rect_maker(x, y, r, g, b) {
  fill(r, g, b, 128);
  rect(x, y, random(20, 40), random(20, 40));
}

function ellipse_maker(x, y, w, h) {
  fill(random(256), random(256), random(256), random(256));
  ellipse(x, y, w, h);
}

function triangle_maker() {
  fill(random(256), random(256), random(256), 16);
  triangle(random(width), random(height), random(width), random(height), random(width), random(height));
}

// array of anonymous functions, each of which can call one of the above named functions
let function_runners = [
  () => {rect_maker(random(width), random(height), random(256), random(256), random(256));},
  () => {ellipse_maker(random(width), random(height),random(width / 4), random(height / 4));},
  () => {triangle_maker();}
];

function setup() {
  createCanvas(200, 200);
  noStroke();
  frameRate(1);
  rectMode(CENTER);
  background(240);
}

function draw() {
  // randomly choose and execute a function with arguments
  random(function_runners)();
}

Image:

rfwa

Edited on November 23, 2021 to revise some of the explanatory text.

thank’s again for this new approach @javagar.
indeed it seems easy to maintain and extend with new ideas for functions.

greetings

1 Like