Use of Arguments like in JS?

Is there a way to do something like this in Unity JS?

Calling a function from another function:

function test(){
     test2(arg1, arg2, arg3);
}

function test2(){
     print (arguments[0]);
     print (arguments[1]);
     print (arguments[2]);
}

The thought here is to blindly pass arguments and then decompose them from an arguments array that is passed along with a function call. In Javascript this was really nice when working with AddEventListener etc.

Any ideas?

Thanks.

– Clint

In C# you can pass an array to a function using params:

public void Test(params int[] myArray)
{
  int a = myArray[0];
}

I don’t know if something like that is possible in JS, but I don’t think so.

But as for your example of sending arguments without creating your own array, I doubt it as it would be a lot slower if Unity JS had to figure out what you were doing.

-Jeremy

Yeah, the same thing can be done in JS:

function test(){ 
     test2([arg1, arg2, arg3]); 
} 

function test2(arguments : Object[]){ 
     print (arguments[0]); 
     print (arguments[1]); 
     print (arguments[2]); 
}

At least, that -should- work, I haven’t tried it with the generic Object class, only an array of strings.

That is not quite the same thing… the params keyword in C# will eat up the arguments and automatically convert them to an array.

Boo does support a similar construct, but I am afraid the fature has not made it into javascript yet.

If you are adventurous, you could use ducktyping and IQuackFu to implement something aking to the arguments feature. Take a look at ExpandoObject and MixupGO on the UnifyWiki to see examples on how to implement IQuackFu

Could IQuackfu be used to automaitcally wrap getcomponents so I could do

MyComponent.myVector.x = 1

instead of

GetComponent (MyComponent).myVector.x = 1

?

Sadly, you have to reference a ducktyped variable at the start of the statement. MixupGO does something similar, so you can do:

me.MyComponent.myVector.x = 22;
me.OtherComponent.text = "yehaw";

Or even, if the property/field names are unique*):

me.myVector.x = 22;
me.text = "yehaw";

Not quite the same, but similar. (me.xxx is shorter than GetComponent(xxx))

*) It will in fact use the first component attached that has a property or field with the given name, so it even works with ambiguous names… You can’t just know which property you will be modifying :smile: :twisted:

Thanks for the input all!

Though I am not sure I am asking the question correctly. I am not asking about passing an array and I do think the params example from C# is close.

The thing I am really looking for is to pass parameters to a function without them having to be identified as arguments of the function. In normal Javascript you can use the arguments property of a function which will contain a list of the arguments passed.

That MixUpGo looks promising. One of the things I am looking to do is write a class that would Extend GameObject so that I could do something like:

GameObject.addListener(“blah”);

If I am reading correctly, this is what MixUpGo will do… Is that correct?

Thanks.

– Clint

Not quite. You can’t extend GameObject directly. What MixupGO does is that it wraps it up in another object that proxies all calls to the game object or its components.

Ah, okay I see now.

Thanks for the clarification freyr!

Regards.

– Clint

To be completely clear, I was not suggesting that using MixupGO directly would solve your problem, but only as an example on how you could use IQuackFu.QuackInvoke, which in your case could be used to implement a function that takes an arbitrary number of arguments.

Here’s some code you could use to simulate the arguments variable in Javascript: (As always 100% untested and guaranteed to include bugs and even syntax errors.)

//MonoBehaviourEx.js -- use this as a base class instead of normal MonoBehaviour
import System.Reflection;
 
class MonobehaviourEx extends MonoBehaviour, Boo.Lang.IQuackFu {
    protected var arguments : Object[] = [];

    function QuackInvoke(name : String, args : Object[]) : Object {
        var t : System.Type = this.GetType();
        var at = new System.Type[args.Length];
        for (var i=0;i<args.Length;i++)
            at[i]=args[i].GetType();
        
        arguments=args; // Allows accessing the arguments array from the function
        
    
        // First test if the method is defined with arguments defined
        var mi : MethodInfo = t.GetMethod(name, at);

        if(mi) {
            var result= mi.Invoke(this, args);
            arguments = []; // Clear the arguments array
            return result;
        }

        // Then if there is one without any arguments
        mi = t.GetMethod(name, []);
        if(mi) {
            var result= mi.Invoke(this, []);
            arguments = []; // Clear the arguments array
            return result;
        }

        // If not -- throw an error.
        var s = "(";
        for (var j=0;j<at.Length;j++)
            s+=at[j]+((j<at.Length-1)?", ":"");
        s+=")";
        
        throw System.MissingMethodException("Method '"+name+s+"' not found in class "+this.GetType());
    }
    
    function QuackGet(name : String) : Object {
        var t : System.Type = this.GetType();
        var fi : FieldInfo = t.GetField(name);
        
        // First test if the field is defined statically
        if (fi) {
            return fi.GetValue(this);
        }
        throw System.MissingMethodException("Field '"+name+"' not found in class "+this.GetType());
    }
    
    function QuackSet(name : String, value : Object) : Object {
        var t : System.Type = this.GetType();
        var fi : FieldInfo = t.GetField(name);
        
        // First test if the field is defined statically
        if (fi) {
            fi.SetValue(this, value);
            return value;
        }
        throw System.MissingMethodException("Field '"+name+"' not found in class "+this.GetType());
    }
 
}

Then use it like this

class Mybeaviour extends MonoBehaviourEx{
    
  function test(){ 
     this.test2(arg1, arg2, arg3); // Note explicit this. required to let DuckTyping kick in
  } 

  function test2(){ 
     print (arguments[0]); 
     print (arguments[1]); 
     print (arguments[2]); 
  } 
   
}

That is excellent freyr! I will give it a go…

I gotta learn more about Boo and IQuackFu because there seems to be some cool things you can do with it!

Appreciate the help!

– Clint

You’re welcome. My middle name will henceforth be known as IQuackFu.


Keli IQuackFu Hlodversson :stuck_out_tongue:

:slight_smile:

I am running into a problem with this line:

class MonobehaviourEx extends MonoBehaviour, Boo.Lang.IQuackFu {

The compiler is freaking on the comma between MonoBehaviour, Boo.Lang.IQuackFu

I am not sure how to even extend this way… Any ideas?

Thanks.

– Clint

I’m not sure either. I was betting on the comma. Either leave out the comma or replace it with another “extends”.

Edit: Just read some specs… it’s supposed to readclass MonoBehaviourEx extends MonoBehaviour implements Boo.Lang.IQuackFu {

I tried without the comma and with an additional extends with no luck… :frowning:

Any other thoughts?

Thanks,

– Clint

The spec says “class classname extends base_class implements interface1, interface2, … {”

The implements is throwing an error in the compiler:

“Unexpected token : implements.”

I am also getting an Unexpected token error for “protected” which is also in the spec. :frowning:

hhhmmmm…

– Clint

I guess this is a missing feature in the compiler then. You could get around it by translating MonoBehaviourEx into C# or Boo. You should still be able to use it from Javascript.

Btw. The error on “protected” is probably due to the compiler being confused after seeing the “implements” keyword.