views:

90

answers:

1

Hi,

I am trying to implement an algorithm I found in C# in javaScript and am facing some issues.

Basically I am finding it difficult to pass by reference in JS. I have broken down the problem I have to the following example code, let say you have the following C#:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace ConsoleApplication1
{
    class Program
    {
        static void Main(string[] args)
        {
            wordPoco[] myArray = new wordPoco[4] { 
                new wordPoco {word="This"},
                new wordPoco {word="is"},
                new wordPoco {word="a"},
                new wordPoco {word="test"}};

            Console.WriteLine("Values Before Recursion");
            MyRecursiveFunction(ref myArray);

            Console.Read();
        }

        private static void MyRecursiveFunction(ref wordPoco[] myArray)
        {
            if (myArray.Length <= 0) {
                Console.WriteLine();
                Console.WriteLine("Values After Recursion");
                return;
            }

            wordPoco[] newArray = (wordPoco[])myArray.Clone();

            Console.Write("ArrayValue: ");
            for (int j = 0; j < newArray.Length; j++)
            {
                Console.Write(newArray[j].word + " ");
            }
            Console.WriteLine();

            //popping in js
            wordPoco[] poppedArray = new wordPoco[newArray.Length - 1];
            Array.Copy(newArray, poppedArray, newArray.Length - 1);

            newArray = (wordPoco[])poppedArray.Clone();

            MyRecursiveFunction(ref newArray);

            myArray = (wordPoco[])newArray.Clone();

            Console.Write("ArrayValue: ");
            for (int j = 0; j < myArray.Length; j++)
            {
                Console.Write(myArray[j].word + " ");
            }
            Console.WriteLine();
        }
    }

    public class wordPoco {
        public string word;
    }
}

That produces the output:

Values Before Recursion
ArrayValue: This is a test
ArrayValue: This is a
ArrayValue: This is
ArrayValue: This

Values After Recursion
ArrayValue:
ArrayValue:
ArrayValue:
ArrayValue:

Shouldn't the following JS produce the same result?

$(document).ready(function() {

    var debugBox = $("#debug");
    var myArray = [{ word: "This" }, { word: "is" }, { word: "a" }, { word: "test"}];

    debugBox.append("<b>Values Before Recursion</b><br/>");
    MyRecursiveFunction(myArray);

    function MyRecursiveFunction(myArray) {
        if (myArray.length <= 0) { debugBox.append("<b>Values After Recursion</b><br/>"); return false; }

        var newArray = $.extend(true, [], myArray);

        debugBox.append("ArrayValue: ");
        for (var j = 0; j < newArray.length; j++)
            debugBox.append(newArray[j].word + " "  );
        debugBox.append("<br/>");

        newArray.pop();
        arguments.callee(newArray);

        myArray = $.extend(true, [], newArray);

        debugBox.append("ArrayValue: ");
        for (var j = 0; j < myArray.length; j++)
            debugBox.append(myArray[j].word + " ");
        debugBox.append("<br/>");
    }
});

The result I am getting is actually:

Values Before Recursion
Value: This is a test 
Value: This is a 
Value: This is 
Value: This 
Values After Recursion
Value: 
Value: This 
Value: This is 
Value: This is a

Thanks so much for your time, Kevin

+2  A: 

The simplest answer is to change it from being a void method to one which returns the array.

So the C# declaration would change to:

private static wordPoco[] MyRecursiveFunction(wordPoco[] myArray)

When you recurse you'd do:

newArray = MyRecursiveFunction(newArray);

and you'd just return myArray at the end of the method.

That will make it easy to port without using pass-by-reference.

Jon Skeet
Thanks fro the answer,Unfortunately that won't work as the algorithm I am porting from C#, passes multiple arrays by reference.
Kevin
I guess I could go and bundle them arrays together and return on big object but ideally I would not want to this...
Kevin
@Kevin: This doesn't sound like terribly nice code. Ref parameters should be relatively rare... it sounds like you *should* encapsulate them all together.
Jon Skeet
As an alternative, write yourself a type "RefToArray" which has operations "GetArray" and "SetArray". Then pass around a RefToArray object. Change everything which sets the value of a ref parameter to call SetArray, and change everything which gets the value of a ref parameter to call GetArray.
Eric Lippert
@Jon, Indeed it isn't the best, I was trying to port it as literally as possible which was daft. I am going to go with your suggestion as now I step back from the problem it makes perfect sense. Thanks for your help. Cheers, K
Kevin