ListTools is a collection of utility methods for dealing with "list-type" collections. Each method will typically accept any sort of Iterable, and produce ListTypes in return. The method documentation is located here.


A ListType is a typedef used by the ListTools API. Under normal use, the typedef is a simple alias for the base Haxe List class. However, if the Haxe code is compiled with the argument "-D sugarlist", the typedef switches to a different List implementation called a SugarList. SugarList extends List, so it is acceptable anywhere a List is. However, it forms links through reference fields, rather than the array based reference used in the base List class. This makes iteration much faster in the SWF targets. The typedef switch itself occurs in IterTools, which ListTools requires.

Method Notes

ListTools is fairly complex due to its optional alternate List implementation, as well as its approach towards handling recursive collections as arguments. The following goes into more detail on both of these topics.

Wrapping IterTools

Many of the ListTools functions simply save the result of an identically named IterTools function as a new ListType. In fact, in many cases it may be best to create light-weight Iterators that allow you to iterate programmatically over collections without resorting to creating List datastructures.

Duplicated Lambda Methods

As part of its method list, ListTools also duplicates the entire Lambda method set. This was done to ensure that the basic map operations would create the appropriate List/SugarList types.

Recursive Collection Type Handling

In many instances, it is necessary to accept and typecheck arguments of Iterable<Iterable<T>>, such as an Array of Arrays, Hash<List<A>>, etc. Unfortunately, Haxe does not recursively type Iterables, so performing a type check on these arguments in the typical fashion will either produce a compiler error, or behave differently than intended.

Many functional methods used in other languages, such as zip() and chain() accept an Iterable of Iterables as an argument. Mimicking this behavior in Haxe is possible, but a bit more complicated because of the differences in type checking. Any such function that handles an Iterable of Iterables is implemented as follows:

First, any Iterable<Iterable<T>> argument is typed as Iterable<Dynamic>. This has the side effect of allowing Iterables of non-Iterables. To handle this problem, A second function called "nonIterableBehavior" is taken as an argument. It accepts Dynamic types, and produces Iterable<Dynamic> types.

Therefore, the basic operation of most Iterable<Iterable<T>> argument functions is to acquire the Iterable<Dynamic> argument, and loop through it. The individual Dynamic elements are checked for a corresponding iterator field. If this field is not present, then an Iterable is created from them using the nonIterableBehavior function. Depending on the intent of the function, this behavior can be to ignore the non-iterable element (by returning null), or by repeating it one or more times (by returning the result of a repeat() call). Certain methods have different default behaviors for the nonIterableBehavior function. For instance, consider the following array:

var arr = [ [1, 2], [3 ,4], 5 ];
// traces {1,2,3,4,5}

The first two elements ([1, 2] and [3, 4]) are iterable, while the third (5) is not. However, the default behavior of chain() is to create an iterator that repeats non-iterable elements once, so 5 is handled as if it were actually an Iterable containing 5. If this is not the desired behavior, it can be changed by passing in a nonIterableBehavior function. For instance, if you wanted to drop the non-iterable elements, you could create a function that simply returns null:

var arr = [[1,2],[3,4],5];
var f = function(x) return null;
trace(ListTools.chain(arr, f));
'//'traces {1,2,3,4}''

Which Iterable Type Should I Use?

See more detail on the design rationale of ListTools on Which Iterable Type Should I Use?.
version #6272, modified 2009-06-28 20:52:44 by jjdonald