Return Structures from Javascript Patch

bonerton's picture

I'm trying to input a variable length structure of strings into a javascript patch, concatenate it's members into subdivisions of n, and output the new 'compressed' structure, but this javascript isn't returning anything:

function (__structure arrOut) main (__structure arrIn, __number n)
{
   var result = new Object();
   var out = [];
 
   if(!_testMode) {
      for(var i = 0; i < arrIn.length(); i += n) {
         out.push(arrIn.slice(i, i+n).join(" "));
      }
      return out;
   }
 
   result.arrOut = out;
   return result;
}

It's not throwing up any errors. I was getting an "expression arrIn [null] is not an Object" error, until i checked for testMode. Any help would be greatly appreciated. Thanks!

Comment viewing options

Select your preferred way to display the comments and click "Save settings" to activate your changes.

usefuldesign.au's picture
Re: Return Structures from Javascript Patch

Don't see that you need this line b/w the braces:

      }
      return out;
  }

for safety I'd just use:

 var out = new Array();

not sure about this line:   out.push(arrIn.slice(i, i+n).join(" "));

I'd be filling a two dimensional array out [i] [j] and then just converting each level 2 set of the array into a string with

Array_Out [i] = out [i].toString() or something along those lines. No time to test for correct syntax, apologies.

bonerton's picture
Re: Return Structures from Javascript Patch

thanks for the reply! i'm not sure if i quite follow you with the two-dimensional array? this updated straight javascript works just how i'd like it to in a browser, i'm just having trouble translating it for QC:

var arrIn = new Array("one","two","three","four","five","six","seven","eight","nine","ten","eleven");
var arrOut = new Array();
var n =  4;
 
// all elements of arrOut are grouped in strings of 4 or less, joined by a space
for (var i = 0; i < arrIn.length; i +=n) {
arrOut.push(arrIn.slice(i,i+n).join(" "));
}

bonerton's picture
Re: Return Structures from Javascript Patch

So when I declare the array inside the javascript patch, it works fine like so:

function (__structure arrOut) main (__number n)
{
   var poop = new Array("one","two","three","four","five","six","seven");
   var result = new Array();
 
   if(!_testMode) {
      for(var i = 0; i < poop.length; i += n) {
         result.push(poop.slice(i,i+n).join(" "));
      }
   }
 
   return result;
}

but when i try to pass in a structure (which is basically an array right?), there is no result and it's not throwing up any errors?

function (__structure arrOut) main (__structure arrIn, __number n)
{
   var result = new Array();
 
   if(!_testMode) {
      for(var i = 0; i < arrIn.length; i += n) {
         result.push(arrIn.slice(i,i+n).join(" "));
      }
   }
 
   return result.arrOut;
}

wudupwitdat? i figure i must be doing something wrong with inputing/outputting the structure?

cwright's picture
Re: Return Structures from Javascript Patch

I'm sorry, I can't watch this anymore.

result = new Object();

Result is always an Object, never an array. Never a number, never a var, never a function. An Object. always.

Junk you return is always a property of the result object (i.e. "arrOut" is result.arrOut, which is the array.)

If you decide to return a non-Object from the javascript function, QC will happily spend all the CPU time executing your script, and then immediately throw away the results. So when you return result with it created as an array, it's pretty much guaranteed to not do what you're intending.

Think of it this way: Your function can return exactly 1 value: QC wants this value to be an Object, which it can then interrogate to break out the various output values for the patch. Thus, an Object is used, because it is a single value that can hold an arbitrary number of values for later digestion.

bonerton's picture
Re: Return Structures from Javascript Patch

thanks for the thorough reply. i started out returning as an Object because that's that's how the example in the patch does it, but after no luck, i tried Array. so my updated code is this (amongst countless other failed variations), yet it's still not returning anything:

function (__structure arrOut) main (__structure arrIn, __number n)
{
   var result = new Object();
   var arrNew = new Array();
 
   if(!_testMode) {
      for(var i = 0; i < arrIn.length; i += n) {
         arrNew.push(arrIn.slice(i, i+n).join(" "));
      }
   }
 
   result.arrOut = arrNew;
   return result;
}

while, this one, with an array declared within the patch, works perfectly:

function (__structure arrOut) main (__number n)
{
   var result = new Object();
   var poop = new Array("one","two","three","four","five","six","seven");
   var arrNew = new Array();
 
   if(!_testMode) {
      for(var i = 0; i < poop.length; i += n) {
         arrNew.push(poop.slice(i,i+n).join(" "));
      }
   }
 
   result.arrOut = arrNew;
   return result;
}

usefuldesign.au's picture
Re: Return Structures from Javascript Patch

try    n =  arrNew.push(poop.slice(i,i+n).join(" "));

Also use the Log statement to get an X-ray of what's going on inside you code. Eg.

 
var a = b + c
Log ("This is what I think I'm calculating as b+c:" +a)

View Log statements in the Draw under the viewer the Graph Foundation Log (Hidden Prefs … Option Key and MENU>Prefernences…) Or Consule app.

Also check out Cybero's JS reference for QC, it's invaluable while learning JS inside QC. Quartz Composer JavaScript Reference

bonerton's picture
Re: Return Structures from Javascript Patch

SOLVED thanks to everyone's help here and on the QC irc channel, fsk in particular. I just needed to loop through the initial input structure and declare it as an array that way. Here's the code if it helps anyone:

function (__structure arrOut) main (__structure arrIn, __number n)
{
   var result = new Object();
   var arrNew = new Array();
   var arrTemp= new Array();
   if(!_testMode) {
       for(i=0;i<arrIn.length;i++)
       {
          arrTemp[i]=arrIn[i];
       }
      for(var i = 0; i < arrTemp.length; i += n) {
         arrNew.push(arrTemp.slice(i, i+n).join(" "));
      }
   }
 
   result.arrOut = arrNew;
   return result;
}