JS Hair Tearing

idlefon's picture

I'm hopeless. I think I know JS a little bit but can not figure out why this code is not working:

function (__structure out) main (__structure input[3])
{
if(!_testMode)
{
   var result = new Object();
   out= new Array();
   out= input[0];
 
   for(i=1;i<3;i++)
      {
      if(input[i].length>1)
         {
         out.concat(input[i]);
         }
      }
 
 
   result.out=out;
   return result;
}
}

whenever input[1] or input[2]'s length is bigger than one the patch stops working, so I guess the "concat" section causes the error.

I'd appreciate it a lot if someone could shed light on this stupid error I'm having.

Comment viewing options

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

cwright's picture
Re: JS Hair Tearing

First let's make the code readable:

function (__structure out) main (__structure input[3])
{
    if(!_testMode)
    {
        var result = new Object();
        out = new Array();
        out = input[0];
 
        for(i = 1; i < 3; i++)
        {
            if(input[i].length > 1)
            {
                out.concat(input[i]);
            }
        }
 
        result.out = out;
        return result;
    }
}

Ok, now let's check it out in depth.

        out = new Array();
        out = input[0];

This DOESN'T DO WHAT YOU THINK (and holy cow this comes up on the list all the time, including yesterday).

you cannot copy arrays by assignment. So the second line (out= input[0];) kills the new Array() you just allocated, and instead now points to an input. Inputs are immutable (cannot be changed).

Luckily, you're not changing the input. Hitting up the docs, we see the following:

http://www.w3schools.com/jsref/jsref_concat_array.asp wrote:
This method does not change the existing arrays, it only returns a copy of the joined arrays.
So concat doesn't actually change anything. instead, it returns a new array with the concatenated results. You're ignoring the return value, which of course won't do anything. you probably want it to say out = out.concat(...). And at that point, it'll be a new array (not an input), so you can mutate it as much as you want.

p.s. smokris, I would totally love a "pimp my code" section on kineme.net ;)

cybero's picture
Re: JS Hair Tearing

concat is used to join two or more arrays together.

having just having looked at cwright's most recent post, try this out

function (__structure out) main (__structure input[3])
{ if(!_testMode)
 
{
 
var result = new Object();
 
out= new Array();
out = out.concat(input[0],input[1],input[2]);
//out= input[0];
 
for(i=1;i<3;i++)
 
    {
    if(input[i].length>input[0].length)
 
        {
        out.concat(input[i]);
        }
    }
 
result.out = out;
 
return result;
} 
 
}

and see attached :-)

PreviewAttachmentSize
concat-structure.qtz39.88 KB

idlefon's picture
Re: JS Hair Tearing

Cheers a lot cwright!

Sorry about the unreadable code. I really couldn't figure out what to type before the code, to put my code in those separate windows.

The thing you mentioned about assigning input arrays and how they are immutable is only for arrays, right? I mean other types of input can be assigned to variables and afterward that certain variable can be mutated, right?

You're right about the concat function. I should check the docs more ofter :D

Thanks again cwright!

idlefon's picture
Re: JS Hair Tearing

Thanks Cybero!

BTW I can not access your site. I get this link instead http://cybero.co.uk/cgi-sys/suspendedpage.cgi .

Your site is a marvelous resource for people like me.

idlefon's picture
Re: JS Hair Tearing

I checked your code and found some problems. Your code acts like kineme struct maker. For instance if I feed three 1d structures, each with 100 members, JS will output a 2d structure with 3 members where each has 100 members. I thought "concat" would make one 1d structure with 300 members (that's actually what I'm after).

I'd appreciate your support Cybero a lot!

noboko's picture
Re: JS Hair Tearing

__structure input is NOT Array, Array-Like Object.
it can not use Array class method.
out = out.concat(input[0],input[1],input[2]);
is concat 3 Objects.
Like
[{input[0]},{input[1]},{input[2]}]

In this case, use Array.prototype.slice.apply(input).
it can convert to Array.

function (__structure out) main (__structure input[3]){
if(!_testMode){
   var result = [];
   result = result.concat(
            Array.prototype.slice.apply(input[0]),
            Array.prototype.slice.apply(input[1]),
            Array.prototype.slice.apply(input[2])
            );
      return{
      out:result
      };
}}

idlefon's picture
Re: JS Hair Tearing

Thanks noboko,

I managed to do what I wanted with the code below. Is your method faster?

function (__structure out) main (__structure input[3]) { if(!_testMode) { var result = new Object(); out= new Array();

for(i=0;i<3;i++) { if(input[i]) { if(input[i].length>1 ) { for (j=0;j<input[i].length;j++) { out.push(input[i][j]); } } } }

result.out=out; return result; } }

noboko's picture
Re: JS Hair Tearing

if rewrite your code .

function (__structure out) main (__structure input[3]) {
 if(!_testMode) {
  var result = new Object();
  var out= new Array();
  var myArray = new Array();
     myArray[0]=Array.prototype.slice.apply(input[0]);
     myArray[1]=Array.prototype.slice.apply(input[1]);
     myArray[2]=Array.prototype.slice.apply(input[2]);
 
for(var i=0;i<3;i++)
    {
    if(myArray[i])
    {
    if(myArray[i].length>1 )
        {
        for (var j=0;j<input[i].length;j++)
            {
            out.push(myArray[i][j]);
            }
        }
    }
    }
 
 
result.out=out;
return result;
} }

OK?

cybero's picture
Re: JS Hair Tearing

Until Wednesday the 2nd next week you can expect my site to be down - lack of funds :-( .

idlefon's picture
Re: JS Hair Tearing

Hope to see it back soon!

idlefon's picture
Re: JS Hair Tearing

Thanks, I get it now!