Sneaky feature showcase: overloads in haxe 4.2!

Haxe 4.2 added initial support for function overloads, I just want to share my excitement for them to anyone who may have missed that feature addition!

Huge thanks to the people working on this stuff (ncannasse, simn, ReallyUniqueName, Gama11, nadako and many others!)

Overloads let you specialize functions based on their argument types. For example, say you’re writing a document library and you want a function to append content. Content might be in the form of text, images or tables, each of which you handle differently when appending. With overloads, you can write a single function called ‘append’ that behaves different depending on the type it’s called with:

append(image: Text)
append(image: Image)
append(image: Table)

In haxe 4.2, you can implement this with the overload keyword. The present limitations are:

  • The overload functions must be inline
  • The overload functions must be extern (However, the new overload feature is not just for externs! This is a requirement right now to ensure the compiler really does inline)

So append would look like:

overload extern inline function append(image: Text) { /* append-text implementation */ }
overload extern inline function append(image: Image) { /* append-image implementation */ }
overload extern inline function append(image: Table) { /* append-table implementation */ }

Here’s a try-haxe for this example

(I imagine we can shorten that keyword list in future iterations of overload)

This enables something I’ve wanted in a programming language for a long time: the ability to write mathematical operations with the expressiveness of shader-code! For example, in shader-code, functions like sin and cos work with any vector type as well as numbers, which is a lot nicer than having sin(x), sinVec2(v), sinVec3(v) and sinVec4(v). With overload this is now possible in haxe too!

Taking this shader example to completion, we can write a vector library that matches the GLSL-specification (including compile-time swizzling!). This lets you compile expressions like this as haxe:

var speed = sin(vec2(Math.random(), Math.random()));
var tangent = speed.yx * vec2(-1, 1);
var transformedTangent = mat2(2) * tangent;
trace('length: ${length(transformedTangent)}');

Into efficient target code like this (for js):

let x = Math.random();
let tangent_x = Math.sin(Math.random()) * -1.;
let tangent_y = Math.sin(x);
let transformedTangent_x = 2. * tangent_x + 0. * tangent_y;
let transformedTangent_y = 0. * tangent_x + 2. * tangent_y;
console.log("Test.hx:8:","length: " + Math.sqrt(transformedTangent_x * transformedTangent_x + transformedTangent_y * transformedTangent_y));

Inlining and haxe’s analyzer means that no vector or matrix objects are allocated here, which has historically been an issue with trying to write expressive math libraries in languages like JavaScript. So you can now have both expressive math and great performance :haxe:

You can play with this example on try-haxe here: Try Haxe !

Or install vector-math from haxelib

haxelib install vector-math

More details on the vector-math github page

* this is similar to Hxsl, the haxe shading language in heaps but the new feature here is you can now generate target source code instead of shader-code

18 Likes

Hej !

Thanks for the post and the examples, but I don’t understand why we must add the extern keyword since it works now for all ?
Is it just for fit the actual compiler requirements and we can imagine remove this keyword in futur Haxe versions ?

Gama11 explained this to me earlier, I believe inline is more of a hint, and haxe can choose to not inline in some circumstances. Whereas extern tells the compiler this function really doesn’t exist anywhere at runtime so it must be inlined.

As this is a first-pass at the feature I think it’s likely that in future versions these limitation will be improved: e.g. overload could imply extern or haxe could generate multiple function definitions with different names so overload doesn’t require inlining

I don’t know anything about this for sure tho – I’m excited for the upcoming talks this month to hear from the team themselves: The First HaxeIn of 2021 Is Just Around the Corner

Thanks for your answer George !
Ok it’s what I’ve understood, just wanted to be sure.
It’s really a good feature, thanks for the contributors !

1 Like

Thanks to the compiler team for implementing it, ant do you for pointing this out, George!
Will be great in static extensions, for example…

Excellent contribution @haxiomic . I’m so happy that the ecosystem keeps developing. I’m betting big on Haxe :slight_smile: … been tinkering for 3 years in my spare time with a rather huge project. Overloads are very welcome, even if the inline/extern requirement is somewhat limiting. Do you think they will eventually be lifted? (maybe not the best place to ask this but maybe you know what’s coming)

Hey @Kyliathy! Betting on haxe here too, I do think many people would choose it if only they knew about it.

I’ve asked around and yes, it does seem the extern-inline limitation will be lifted in the future - either by implying inlining or by generating additional functions for platforms that don’t allow overload natively. Cannot give you a timeline however. I expect overload extern inline will keep working in the future when the next iteration of overload comes out