Haxe 3 allows binding functions with partially applied arguments. Each function type can be considered to have a bind
field, which can be called with the desired number of arguments in order to create a new function. This is demonstrated here:
class Main { static public function main() { var map = new haxe.ds.IntMap<String>(); var f = map.set.bind(_, "12"); $type(map.set); // Int -> String -> Void $type(f); // Int -> Void f(1); f(2); f(3); trace(map); // {1 => 12, 2 => 12, 3 => 12} } }
Line 4 binds the function map.set
to a variable named f
, and applies 12
as second argument. The underscore _
is used to denote that this argument is not bound, which is shown by comparing the types of map.set
and f
: The bound String
argument is effectively cut from the type, turning a Int->String->Void
type into Int->Void
.
A call to f(1)
then actually invokes map.set(1, "12")
, the calls to f(2)
and f(3)
are analogous. The last line proves that all three indices indeed are mapped to the value "12"
.
The underscore _
can be skipped for trailing arguments, so the first argument could be bound through map.set.bind(1)
, yielding a String->Void
function that sets a new value for index 1
on invocation.
By default, trailing optional arguments are bound to their default values and do not become arguments of the result function. This can be changed by using an explicit underscore _
instead, in which case the optional argument of the original function becomes a non-optional argument of the result function.
class Main { static function test(a:Int, ?b:String):Void {} static public function main() { var fn = test.bind(1); $type(fn); // Void->Void fn('foo'); // Compiler error: Too many arguments var fn = test.bind(1, _); $type(fn); // ?String->Void fn('foo'); // works } }
Trivia: Callback
Prior to Haxe 3, Haxe used to know a
callback
-keyword which could be called with a function argument followed by any number of binding arguments. The name originated from a common usage were a callback-function is created with the this-object being bound.Callback would allow binding of arguments only from left to right as there was no support for the underscore
_
. The choice to use an underscore was controversial and several other suggestions were made, none of which were considered superior. After all, the underscore_
at least looks like it's saying "fill value in here", which nicely describes its semantics.