8

In ActionScript I can use ... in a function declaration so it accepts arbitrary arguments:

function foo(... args):void { trace(args.length); }

I can then call the function passing an array:

foo.apply(this, argsArray);

I'd like to call the function with arguments of unknown type and count. Is this possible in Haxe?

Gama11
  • 31,714
  • 9
  • 78
  • 100
meps
  • 579
  • 2
  • 17

4 Answers4

7

According to the Haxe documentation, you can use a Rest argument:

If the final argument of a macro is of type Array<Expr> the macro accepts an arbitrary number of extra arguments which are available from that array:

import haxe.macro.Expr;

class Main {
  static public function main() {
    myMacro("foo", a, b, c);
  }

  macro static function myMacro(e1:Expr, extra:Array<Expr>) {
    for (e in extra) {
      trace(e);
    }
    return macro null;
  }
}
Gama11
  • 31,714
  • 9
  • 78
  • 100
  • 1
    This is the correct answer if you are wanting to write your own method that takes an arbitrary number of arguments. Not every Haxe compiler target supports "Rest" arguments, but you can emulate it at compile time using macros. – Jason O'Neil Feb 07 '15 at 23:04
5

You could use Reflect.callMethod():

class Test {
    static function main() {
        var console = js.Browser.window.console;
        var fn = console.log;
        Reflect.callMethod(console, fn, [1, 2, "three", [4]]);
    }
}
Gama11
  • 31,714
  • 9
  • 78
  • 100
Andrew
  • 1,282
  • 6
  • 11
  • 1
    This is the correct answer if you are calling an existing method (in a native environment or an extern) which can take an arbitrary number of arguments. – Jason O'Neil Feb 07 '15 at 23:03
4

Starting with Haxe 4.2, Haxe will have native support for rest arguments:

function f(...args:Int) {
    for (arg in args) {
        trace(arg);
    }
}

f(1, 2, 3);

...args:Int is simply syntax sugar for rest:haxe.Rest<Int>. Only the last argument of a function can be a rest argument.

You can also use ... to "spread" an array when calling a function with a rest argument:

final array = [1, 2, 3];
f(...array);
Gama11
  • 31,714
  • 9
  • 78
  • 100
3

Just to add to this, if you're describing an extern for an external JavaScript library (or Python, Lua, or any target language that supports the rest parameter, e.g. ...rest), there is a specific Haxe type, haxe.extern.Rest, to express this.

Here's an example showing that the JavaScript Math.max function handles varargs: http://try.haxe.org/#4607C

class Test {
  static function main() {
    trace("JS Math.max takes varargs:");
    trace(MyMath.max(1,2,3,4)); // 4
    trace(MyMath.max(5,6));     // 6
  }
}

@:native("Math")
extern class MyMath {
  static function max(a:Float,
                      b:Float,
                      rest:haxe.extern.Rest<Float>):Float;
}

Note that the Haxe standard library does not define Math.max with Rest, as its goal is cross-platform compatibility.

Gama11
  • 31,714
  • 9
  • 78
  • 100
Jeff Ward
  • 16,563
  • 6
  • 48
  • 57