Thx.core
Super-charged standard library for Haxe.
Install / Use
/learn @fponticelli/Thx.coreREADME
thx.core
Generic multi-purpose library. thx.core aims to be the lodash library for Haxe.
Data Structures
thx.core provides a few data types to complete the standard library.
AnonymousMap
Wraps an anonymous object in Map<String, T> compatible structure.
var map = new AnonymousMap({ name : "Franco" });
map.get("name"); // "Franco"
The intention of this class is not to encourage anonymous objects as data containers but to simplify the approach to untyped data like JSON results.
Either
Either is a value container. It can contain values from two different types but only one per instance. It can be handy when you want to manage values that can be in one of two possible states. A classic example is a Result where the wrapped value can be either a success or a failure.
typedef MyResult = Either<Error, String>;
var result : MyResult = Left(new Error("something smells"));
var result : MyResult = Right("the answer is 42");
Note that thx.Result is an abstract on top of Either with some additional features.
NOTE: Haxe v.3.2.0 introduces its own haxe.ds.Either type. It is 100% compatible with the one provided by thx. For that reason, thx adopts the official one when available. In the future thx.Either will probably be deprecated.
Nil
Nil is a special enum that only contains one constructor nil that takes no parameter. It denotes the absence of a value. It is very handy when you want to work on functions of arity 1 and you don't want to special case them to support an empty list of arguments.
function do<T>(arg : T) { /* do magic */ }
do(nil) { /* ... */ } // use `do` with an empty argument
typedef F<T> = T -> String;
// the following function satisfies the typedef above
function myF(_ : Nil) : String { /* ... */ }
Result
Result is a wrapper (abstract) on top of thx.Either. It semantically represents the result of an operation that can either a success or a failure.
var success : Result<String, String> = Right("victory!");
success.isSuccess; // true
success.isFailure; // false
success.value(); // "victory!"
success.error(); // null
success.optionValue(); // Some("victory!")
success.optionError(); // None
var failure : Result<String, String> = Left("oh, no ...");
failure.isSuccess; // false
failure.isFailure; // true
failure.value(); // null
failure.error(); // "oh, no ..."
failure.optionValue(); // None
failure.optionError(); // Some("oh, no ...")
thx.promise.Future always bring a result and thx.promise.Promise extend the concept by adding the possibility of a failure.
Set
A Set is a list of unique values. Values are unique in a way that no duplicates can exist in the same Set. Note that uniqueness is enforced by strict phisical equality. That means that is perfectly possible to have a Set of class instances where the instances contain exactly the same values but are referring different objects. Primitive values like Int, Float, String do not incur in such cases.
Set<T> is an abstract built on top of Array<T>. Like Array, it is a mutable structure and shares with it most of its methods with.
var set = Set.createInt([1,2]);
set.add(3);
set.add(1); // again one!
set.length == 3; // true!
A Set can be easily created from an Array:
var s : Set<Int> = [1,2,3,1]; // note that the repetead value will be removed
Set supports boolean operations like union, intersection and difference:
var s = ([1,2,3] : Set<Int>).union([2,3,4]).difference([2,3]);
// s contains [1,4]
Note that boolean operations return new Set instances and do not change the original instances.
Tuple
A Tuple is a value containing multiple values of potentially different types. All tuples are immutable; that means that any tuple operation that seems to change the Tuple it is creating a new structure instead.
A Tuple0 contains no value and it is equivalent to thx.Nil.nil.
A Tuple1 contains one value and it is a wrapper to the value type itself.
A Tuple2, the most conventional of the tuples, is an abstract wrapper around an object of type { _0 : T0, _1 : T1 }.
var t = new Tuple2("thx", 1);
t._0; // "thx", same as t.left
t._1; // 1, same as t.right
t.flip().left; // `flip` inverts the terms of the tuple and `left` is now 1
t.dropRight(); // return a Tuple1 which in this case results in "thx"
t.with("0.123") // appends a new value to the right creating a new Tuple3
Tuple3, Tuple4, Tuple5 and Tuple6 work much like Tuple but bring more values.
Type Helpers
thx.core also contains a lot of useful helper classes to simplify dealing with a lot of types from the standard library.
Most methods described below assume that the respective types have been required using using and are used as type extensions.
Arrays/Iterators/Iterables
Similarly to Lambda, Arrays/Iterators/Iterables provide extension methods to work with collections. They share most of the methods and are repeated to avoid useless casting or conversions and to provide optimizations where possible.
Some examples of the common features:
[1,2,3].all(function(i) return i > 1); // false
[1,2,3].any(function(i) return i > 1); // true
// filter works for any Iterator/Iterable like the normal Array.filter
[1,2,3].filter(Ints.isOdd); // [1,3]
[1,2,3].filter.fn(_ != 2); // equivalent to [1,2,3].filter(function(i) return i != 2)
[1,2,3].isEmpty(); // false
[1,2,3].map.fn(_ * 2); // [2,4,6]
Arrays
Beside the usual methods to traverse, reduce, slice and arrange arrays, Arrays contains peculiar things like:
compactto filter out null valuescrossto create cross products between 2 arraysequalsto compare each element of two arraysflatMapandflattento reduce nested arrays into flat arraysgroupByto createMapfrom arrayssampleandsampleOneto extract random elements from one arrayshuffleto reorder randomly an arrayzip/unzipto create/deconstruct arrays ofTuple
In the thx.Arrays module are also defined a few specialized operations for specific type of arrays: ArrayFloats, ArrayInts and ArrayStrings. The numeric array variations provide methods for average, sum, min and max (plus compact for Float that removes non-finite numbers).
Iterators
it.isIterator() // checks that the instance has the right members to be an Iterator
Iterables
it.isIterable() // checks that the instance has the right members to be an Iterable
Floats
Floats contains extension methods to work with Float values. Some examples:
canParsechecks if a string can be safely parsed into aFloat. Useparsefor the final conversionclamprestricts a value within a given rangecomparereturns a value suitable for comparisoninterpolatedoes exactly that :)nearEqualscompare two values with a small margin to account for floating precision issueswrapensure that the passed valeu will be included in the boundaries. If the value exceedsmax, the value is reduced byminrepeatedely until it falls within the range. Similar and inverted treatment is performed if the value is belowmin
Functions
Extension methods for functions. Methods are roughly distributed between Functions, Functions0, Functions1, Functions2 and Functions3 where the number suffix denotes the arity (number of arguments) of the function that are going to be extended.
afterreturns a function that wraps the passed function. The original function will be executed only after it has been calledntimescomposereturns a function that calls the first argument function with the result of the following one.equalityperforms strict physical equalityidentityis a function that returns its first argumentjoincreates a function that calls the 2 functions passed as arguments in sequencememoizereturns a new version of the argument function that stores the computation from the function and recycles it whenever called againnegatereturn a new version of a function that returns aBooland transforms it so that it will return the negation of its resultnoopits a function that performs no computations and doesn't return a valueoncewraps and returns the argu
