ReferenceError for custom function arguments

Hi everyone,

I tried testing a bunch of custom functions I want to use in a PsychoPy study on Pavlovia. I wrote Python & JS Code, I tested the JS code in a compiler and it works as intended. But as soon as I try to use it in my study, I get reference errors for my function arguments:

When I check it in the dev tools, I get the following messages:

And my script looks like this:

Does anyone know what’s happening here? As sampling_list is only one of the function arguments with an array as the input value, I don’t get why it’s treated like an undefined variable.

Thanks in advance for any hints / help with this!
Merle

PS: Here’s my code:

// extend()
// concatenate 2 arrays, return as new array
extend = function(array1, array2){
    return array1.concat(array2);
}
console.log("defined extend function");

// random.sample()
// this function is using the Fisher-Yates shuffle and 
// taking a part of the resulting array to create the random sample
random_sample = function(arr, k) {
    // with arr = some sample to draw from and k = sample size
    var shuffled = arr.slice(0), i = arr.length, min = i - k, temp, index;
    while (i-- > min) {
        index = Math.floor((i + 1) * Math.random());
        temp = shuffled[index];
        shuffled[index] = shuffled[i];
        shuffled[i] = temp;
    }
    return shuffled.slice(min);
}
console.log("defined random.sample function");


// from random import shuffle
random_shuffle = function(array) {
  let currentIndex = array.length,  randomIndex;
  // While there remain elements to shuffle...
  while (currentIndex != 0) {
    // pick a random element
    randomIndex = Math.floor(Math.random() * currentIndex);
    currentIndex--;
    // and swap it with the current element
    [array[currentIndex], array[randomIndex]] = [
      array[randomIndex], array[currentIndex]];
  }
  // return shuffled array
  return array;
}
console.log("defined shuffle function")


// repeat()
repeat = function(value, times) {
    // if you want to repeat a single value
    if (typeof value === 'string' || value instanceof String){
        // just repeat value and return as array
        return Array(times).fill(value); 
    }
    // if you want to repeat an array
    else if (Array.isArray(value)){
        // save value array you want to append & mutate the original one
        var add_value = value
        for (var i = 0; i < times-1; i++){
            value = extend.call(this, array1 = value, array2 = add_value);
        }
        // return concatenated arrays
        return value;  
    }
}
console.log("defined repeat function");


draw_without_replacement = function(sampling_list, sample_size) {
    // set variables
    var rep_sampling_list, rep_times;
    // repeat colour_codes_list as often as needed
    rep_times = Math.floor((sample_size / sampling_list.length));
    rep_sampling_list = repeat.call(this, value = sampling_list, times = rep_times);
    // check if we need some more values, if yes, draw some randomly 
    // from colour_codes and append to our list
    if ((rep_sampling_list.length < sample_size)) {
        rep_sampling_list = extend.call(this, array1 = rep_sampling_list, array2 = random_sample.call(this, sampling_list, k = (sample_size - rep_sampling_list.length)));
    }
    // shuffle everything
    rep_sampling_list = random_shuffle.call(this, rep_sampling_list);
    return rep_sampling_list;
}
console.log("defined sample w/o replacement function");

// test function:
var test = draw_without_replacement.call(this, sampling_list = ["red", "blue", "green"], sample_size = 4);
console.log(test);

And you can try running the experiment here: language_nback_t2 [PsychoPy]

Hi @Merle,

so, I am no js pro by any means. But what I guess is that it has something to do with running “strict mode” or not (got this idea from here). I copied your code to https://jsfiddle.net/ (where it worked fine) and prefaced it with “use strict” (which broke it), then changed the code until all warnings were gone. Copying the result to the builder and running the output PsychoJS throws no errors anymore and logs the correct outputs to the console. As to why exactly your code runs in strict mode in PsychoJS you have to ask real js users. Maybe you are one of them :smiley:. Anyway, this is the code that works:

// extend()
// concatenate 2 arrays, return as new array
var extend = function(array1, array2){
    var array1
    var array2
    return array1.concat(array2);
}

console.log("defined extend function");

// random.sample()
// this function is using the Fisher-Yates shuffle and 
// taking a part of the resulting array to create the random sample
var random_sample
random_sample = function(arr, k) {
    // with arr = some sample to draw from and k = sample size
    var shuffled = arr.slice(0), i = arr.length, min = i - k, temp, index;
    while (i-- > min) {
        index = Math.floor((i + 1) * Math.random());
        temp = shuffled[index];
        shuffled[index] = shuffled[i];
        shuffled[i] = temp;
    }
    return shuffled.slice(min);
}
console.log("defined random.sample function");


// from random import shuffle
var random_shuffle = function(array) {
  let currentIndex = array.length,  randomIndex;
  // While there remain elements to shuffle...
  while (currentIndex != 0) {
    // pick a random element
    randomIndex = Math.floor(Math.random() * currentIndex);
    currentIndex--;
    // and swap it with the current element
    [array[currentIndex], array[randomIndex]] = [
      array[randomIndex], array[currentIndex]];
  }
  // return shuffled array
  return array;
}
console.log("defined shuffle function")


// repeat()
var repeat = function(value, times) {
    // if you want to repeat a single value
    if (typeof value === 'string' || value instanceof String){
        // just repeat value and return as array
        return Array(times).fill(value); 
    }
    // if you want to repeat an array
    else if (Array.isArray(value)){
        // save value array you want to append & mutate the original one
        var add_value = value
        for (var i = 0; i < times-1; i++){
        var array1
        var array2
            value = extend(array1 = value, array2 = add_value);
        }
        // return concatenated arrays
        return value;  
    }
}
console.log("defined repeat function");


var draw_without_replacement = function(sampling_list, sample_size) {
    // set variables
    var rep_sampling_list, rep_times;
    // repeat colour_codes_list as often as needed
    rep_times = Math.floor((sample_size / sampling_list.length));    
    var value
    var times
    rep_sampling_list = repeat(value = sampling_list, times = rep_times);
    // check if we need some more values, if yes, draw some randomly 
    // from colour_codes and append to our list
    if ((rep_sampling_list.length < sample_size)) {
    var array1
    var array2
    var k
        rep_sampling_list = extend(array1 = rep_sampling_list, array2 = random_sample(sampling_list, k = (sample_size - rep_sampling_list.length)));
    }
    // shuffle everything
    rep_sampling_list = random_shuffle(rep_sampling_list);
    return rep_sampling_list;
}
console.log("defined sample w/o replacement function");

// test function:
var sampling_list
var sample_size
var test = draw_without_replacement(sampling_list = ["red", "blue", "green"], sample_size = 4);
console.log(test);
1 Like

Thanks so much @ajus, it works now! :heart_eyes: