Skip to content

Breaking changes in Haxe 5.0.0

Rudy Ges edited this page Feb 14, 2024 · 4 revisions

bind typing with optional arguments

Haxe 4 hides trailing optional arguments when using bind on a function:

function f(notOpt:Int, ?opt:String) {}

function main() {
  var fBind = f.bind(1);
  $type(fBind); // () -> Void
}

In Haxe 5, this is now typed as (?opt : Null<String>) -> Void which might cause unification errors.

There are two ways to address this, depending on your use case:

Trigger Haxe 5 behavior in Haxe 4

The easiest way to address this is to use explicit _ for all trailing optional arguments:

function f(notOpt:Int, ?opt:String) {}

function main() {
	var fBind = f.bind(1, _);
	$type(fBind); // (?opt : Null<String>) -> Void
}

This gives the same result in both Haxe 4 and 5.

Haxe 4 typing compatibility with Haxe 5

In Haxe 4, due to trailing optional arguments being hidden, using bind on a function with optional arguments where a function with no such arguments is expected would work:

function f(notOpt:Int, ?opt:String) {}
function foo(cb:Void->Void) {}

function main() {
  var fBind = f.bind(1);
  $type(fBind); // () -> Void
  foo(fBind); // Ok
}

In Haxe 5, compiler will complain with (?opt : Null<String>) -> Void should be () -> Void.

This can be fixed by explicitly adding null for optional args:

function f(notOpt:Int, ?opt:String) {}
function g(notOpt:Int, alsoNotOpt:Bool, ?opt:String) {}
function foo(cb:Void->Void) {}
function bar(cb:Bool->Void) {}

function main() {
  var f1 = f.bind(1, null);
  $type(f1); // () -> Void
  foo(f1); // Ok

  // And if you need to skip arguments:
  var g1 = g.bind(1, _, null);
  $type(g1); // (alsoNotOpt : Bool) -> Void
  bar(g1); // Ok
}

You can also use a lambda instead of bind:

function f(notOpt:Int, ?opt:String) {}
function foo(cb:Void->Void) {}

function main() {
  var fLambda = () -> f(1);
  $type(fLambda); // () -> Void
  foo(fLambda); // Ok
}

Those solutions work in both Haxe 4 and 5.