The moon-core
lib is the result of accumulated codes over the years from freelancing, hobby, and professional work. The cross-platform/general stuff goes into this project.
Any with deepEquals, Bits abstract for bit manipulations, Compare for easy comparisons and sorting. Range for Pythonesque Int Iterator. Future, Signal and Observable as events primitives. Pair and Tuple for ordered values, each with its own type. Sugar for short lambdas and other conveniences.
Text is a String
abstract with operator overloading (eg. multiply with Int
to repeat). Also some functions to display text in fixed width, with options to align left/right/center.
Seq is an abstract Iterable
, with automatic conversions from Iterator
, Vector
, String
, Void->Iterator
and Void->Seq
. It has all of Lambda methods, plus many more. Actually, I've implemented almost every method less some overloads from .NET's LINQ Enumerable class. Like .NET's Enumerable, a number of the query methods have deferred execution. This will pave way for a LINQ-like Haxe macro when I get around to doing it. Seq works best as a static extension (so sequences of sequences can have additional methods).
Generator and Fiber for easy writing of asynchronous code using @yield
expression to stop running a function, which can later be resumed. This is done with Async to transform regular functions into a state machine. Not every Haxe expression is supported yet. For example, variable capture from a switch case isn't working. Array comprehension is also not working. In some special cases, if
and switch
may be detected incorrectly if they're expressions or statements. You can manually annotate with @void
or @expr
to avoid such compilation errors.
PBKDF2 for password hashing, Jwt (JSON Web Tokens) for signed tokens. Arc4 symmetric cipher, Rsa asymmetric crypto (Oaep padding not fully implemented).
HyperArray for creating multi-dimensional array at run-time. MultiArray for an efficient multi-dimensional array, where all calculations are pre-calculated and inlined at compile-time. NestedArray for multi-dimensional arrays that can be jagged.
There's a bunch of different iterators, including IterableIterator and IteratorIterator for iterating through nested sequences as if they're a single linear sequence.
LruCache (Least-Recently-Used Cache) which behaves like a StringMap
except that it has limited capacity, and the least-recently used item will get kicked out when inserting a new item when full. It's implemented using DoubleLinkedList. Histogram for tallying stuff, and Set for unique collections.
BigInteger, BigRational, and BigBits for dealing with numbers of arbitrary size. BigInteger is used for implementing Rsa (done for fun -- it's slow, not fully tested, so don't use).
Stats for computing stuff like mean, median, mode, variance, standard deviation, zScore etc...
There's a number of seedable pseudo-random number generators to use, such as MersenneTwisterRandom, LcgRandom (Linear Congruent Generator), XorShiftRandom, and a few others. Any of these PRNG algorithms could be assigned to a Random abstract, where you'll get many more methods like shuffling arrays, random sample, n-dice rolls, and so on. You can also generate random numbers that follows a specific distribution like triangular, exponential, gamma, chi-squared, and a number of others.
Units (work-in-progress!) uses Haxe abstracts to give meaning to numbers by typing it with a unit. Automatic conversions between units when you assign to a compatible type. TODO: Only allow units of the same type for add/sub. Dimensionless numbers can be multiplied/divided with a dimensioned number. Type conversion when two units are multiplied/divided.
FutureProxy is like AsyncProxy
for Haxe remoting, but it returns a Future instead. Future is from moon-lib and not to be confused with the one from tink_core.
DamerauLevenshtein for checking edit distances between two strings. Inflect to convert from string cases like kebab-case to camelCase etc... HashCode has several different algorithms for calculating hash codes of strings.
These are all meant to be used as a static extension.
ArrayTools lets you zip and unzip like in python. Also has some set operations between arrays. FloatTools to round, truncate, clamp, interpolate, format numbers. FunctionTools to memoize functions. IteratorTools has all the methods from Seq, except that it doesn't defer execution. TextTools is like Text, but as a String
static extension instead of an abstract.
Template is a compile-time templating system that allows you to write with ASP-like tags using Haxe as the language. Since it's a compile-time system, you get all the type checks from the Haxe compiler, and there's no special parsing at run-time. It works on all targets, even on those without sys.io.File
.
Router is a general routing class, that can be used as an alternative to haxe.web.Dispatch
. It's general, and so it has no dependency on haxe.web.Request
, making it available on all targets. There's an option to use a macro for defining routes using meta annotations on methods.
Url can be used to break up a URL into its individual components.
You can now easily write asynchronous cooperatively-multitasking codes in Haxe! Unlike threads, you don't need to worry about locking, and this is especially useful to write asynchronous codes on single-threaded targets.
Here are some information on what generators/fibers are:
This works just like the generator functions in JavaScript, Python, and C#. If a function or method contains a @yield x
or @await f
expression, then it is automatically transformed into a generator function.
NEW: @await f
where f is a Future<T>
.
@yield x
expressionYou can type the generator function with a valid async type, to get that type when the generator is called. In the following example, it's an Iterator<String>
, but it could be other async types too.
function names():Iterator<String>
{
@yield "alice";
@yield "bob";
@yield "carol";
@yield "dave";
}
for (x in names())
trace(x);
In this example, we want a Generator<Int, String>
instead. Int
is what this generator produces. String
is what this generator accepts via send(value)
. This is like in JavaScript and Python where you can also send values back into the generator.
function greet(a:Int, b:String):Generator<Int, String>
{
for (i in a...10)
{
if (i == 5)
trace("yo" + @yield 999);
else
trace(b + @yield i);
}
}
var it = greet(3, "hi");
var m = 10;
while (it.hasNext())
{
var out = it.send(" " + m++);
trace("out: " + out);
}
@await f
expression@await f
is syntactic sugar for an expression of @yield
. It's mainly useful in Fibers, but it can be used in Generators too. @await f
is equivalent to:
{
while (f.state == FutureState.Awaiting)
@yield __current;
switch(f.state)
{
case FutureState.Success(v): v;
case FutureState.Failure(e): throw e;
case FutureState.Awaiting: throw "assert";
}
}
Here's an example of it being used:
var someFuture = new Future<Int>();
function example():Iterator<String>
{
@yield "foo";
var x:Int = @await someFuture;
trace('value of x is $x');
@yield "bar";
}
var it = example();
var i = 0;
while (it.hasNext())
{
// trigger completion when i is 5
if (i == 5) someFuture.complete(5318008);
trace(i + ": " + it.next());
++i;
}
// output
// 0: foo
// 1: foo
// 2: foo
// 3: foo
// 4: foo
// value of x is 5318008
// 5: foo
// 6: bar
So what else is valid besides Iterator and Generator? Here's a complete list:
You can define your own async types, for less verbose code. There are 2 ways you can do that.
Method 1: static fromAsync
method in class
class CustomWrapper<T>
{
public var foo:Iterable<T>;
public function new()
{
foo = [];
}
// Iterable<A> can be any valid async type
public static function fromAsync<A>(it:Iterable<A>):CustomWrapper<A>
{
var obj = new CustomWrapper<A>();
obj.foo = it;
return obj;
}
}
Method 2: static extensions with @asyncType
meta
class WhateverTools<T>
{
// Iterable<A> can be any valid async type
@asyncType public static function whatever<A>(it:Iterable<A>):CustomWrapper<A>
{
var obj = new CustomWrapper<A>();
obj.foo = it;
return obj;
}
}
After that, you can do this:
function custom():CustomWrapper<String>
{
@yield "aaa";
@yield "bbb";
@yield "ccc";
}
for (x in custom().foo)
trace(x);
Method 2 is useful when you don't have access to the class, for example, in 3rd party libraries. This gives you the flexibility to use, for example, tink_core's Future instead of the Future from this library.
Async generator types are simply iterators. You need to manually iterate through them. Async fiber types are iterators added into a Fiber
object. The fiber Processor
is usually added to your game loop or some interval/update function, and the processor will take turns switching between different fibers every loop.
function think(self:Entity):Fiber<Int>
{
// some long-running algorithm
var i = 0;
for (e1 in entities)
for (e2 in entities)
{
self.doSomething(e1, e2);
if (++i % 10 == 0)
@yield i; // allow other fibers to run
}
}
// these fibers are automatically added to Processor.main
var fiberA = think(a);
var fiberB = think(b);
var fiberC = think(c);
// this while loop represents your game loop/update
while (Processor.main.hasNext())
{
// run the next 7 fibers.
// this number is arbitrary.
Processor.main.run(7);
}
The processor will automatically remove fibers that has terminated. You can manually kill a fiber using fiber.kill()
.
There are 2 ways to use this async macro. One is by calling the Async.async(function()...)
macro. The other, preferred, way is to add a @:build(moon.core.Sugar.buildAsync())
to your class (or build
instead of buildAsync
for other stuff like short lambdas too). The second way results in cleaner looking code.
See AsyncExamples for more generator function examples using Async.async()
.
See AsyncSugaredExamples for the examples that uses @:build
.
Running the async examples:
haxe -main AsyncSugaredExamples -cp src -cp test -neko async.n
neko async
See ASYNC.md
I need help to iron out some issues related to the async stuff.
moon.macros.async.AsyncTransformer.hx
and change DEBUG_OUTPUT_TO_FILE
to true
.Feel free to contribute. Contributions, bug fixes, and feature requests are welcomed.
Most of the lib was written by me, however, some portions of it was ported from other open source codes. Some are not ported, but are adaptations or implementations based on ideas and algorithms from articles and online discussions.
BigInteger and BigRational moon.numbers.big
(port)
Peter Olson: https://github.com/peterolson/BigInteger.js/blob/master/BigInteger.js
Template moon.web
(inspired by)
John Resig: http://ejohn.org/blog/javascript-micro-templating/
RandomDistributions moon.numbers.random
(port)
NumPy developers: https://github.com/numpy/numpy/blob/master/numpy/random/mtrand/distributions.c
Quarternion moon.numbers.geom
(port)
Will Perone: http://willperone.net/Code/quaternion.php
NeuralNetwork moon.ai.nnet
(port)
Juan Calaza: https://github.com/cazala/synaptic
MersenneTwisterRandom moon.numbers.random.algo
(port)
Sean Luke: http://www.cs.gmu.edu/~sean/research/mersenne/MersenneTwister.java
Sean McCullough via Makoto Matsumoto and Takuji Nishimura: https://gist.github.com/banksean/300494
DamerauLevenshtein moon.strings.metric
(port)
Kevin L. Stern: https://github.com/KevinStern/software-and-algorithms/blob/master/src/main/java/blogspot/software_and_algorithms/stern_library/string/DamerauLevenshteinAlgorithm.java
Parser moon.peg.grammar
(reference, ideas)
Warth, Douglass, Millstein: http://www.vpri.org/pdf/tr2007002_packrat.pdf
Mark Engelberg: https://github.com/Engelberg/instaparse
Inflect moon.strings.inflect
(ideas)
Aura PHP developers: https://github.com/auraphp/Aura.Framework/blob/develop/src/Aura/Framework/Inflect.php
MIT