Tag Archives: haxe

thx: error

The thx.error package contains a bunch of classes to manage errors in your applications. The base class is Error and is a lightweight container for error messages. The nice thing about it is that it separates the message itself from its parameters allowing to format it in a meaningful way:

var error = new Error("invalid import {0:C}", 0.123);
trace(error);
// trace results is: invalid import $0.12

If you provide the needed infrastructure you can also use an instance of ITranslation to deliver your messages:

// Translated Error
var translator = new DictionaryTranslation(ItIT.culture);
translator.addSingular("invalid import {0:C}", "importo invalido {0:C}");
trace(error.translate(translator));
// trace result is: importo invalido € 0,12

I often use to mark my abstract methods so that at least at runtime I have a feedback that the implementation is missing and I do that using the AbstractMethod error class (the NotImplemented error class is functionally equivalent but has a different semantic).

// AbstractMethod / NotImplemented
// in a real world context this will be an instance method and not an inline function

function notImplemented() throw new NotImplemented();
try
{
	notImplemented();
} catch (e : Dynamic) {
	trace(e);
}

The nice thing is that I don’t have to type any message into the constructor because all the info I need are already in there; this is the trace:

method Main.notImplemented() needs to be implemented

Finally the NullArgument error class has a couple of static constructors that helps me check for null arguments. Using macros the argument name is extracted so that you don’t need to type it as a string; that spares you some typing but better yet avoids annoying and error prone repetitions.

// NullArgument
function toUpperCase(text : String)
{
	NullArgument.throwIfNull(text);
	return text.toUpperCase();
}

try
{
	toUpperCase(null);
} catch(e : Dynamic)
{
	trace(e);
}
// trace result is: invalid null argument 'text' for method Main.toUpperCase()

The NullArgument.throwIfNullOrEmpty works similarly but also test for emptiness … this works on Strings, Lists, Arrays (length) and objects (no fields). Note that the type discovery is made at compile time and not at runtime:

// null or empty
function pop(arr : Array) : String
{
	NullArgument.throwIfNullOrEmpty(arr);
	return arr.pop();
}

try
{
	pop([]);
} catch(e : Dynamic)
{
	trace(e);
}

// trace result is: invalid null or empty argument 'arr' for method Main.pop()

thx: parsing dates

One of the latest additions to thx is thx.dates.DateParser. It is obviously a date parser, the nice thing about it is that it tries to be fuzzy and to extract a date whenever possible. You can try it yourself here:

Examples of expressions:

  • today
  • now
  • tomorrow
  • next april
  • last sunday
  • three weeks ago plus 5 minutes
  • tomorrow in the evening
  • 6/27
  • 27/6

To produce this tiny demo you just need a bunch of lines of code:

import thx.date.DateParser;
import thx.js.Dom;
import js.Dom;
class Main
{
  static function main()
  {
    Dom.select("#date").onNode("keyup", function(n : HtmlDom, _) {
      var t : Text = cast n;
      var result = try {
        Dates.format(DateParser.parse(t.value), "DT");
      } catch (e : Dynamic) {
        Std.string(e);
      }
      Dom.select("#processed")
        .html().string(result);
    });
  }
}

Surely the expression grammar can be improved but it works for my needs right now and it is already very flexible.

thx : Arrays

In thx there are many helper methods. The convention is that if a class is not meant to be instantiated and its only purpose is to add functionalities to other types than it will be named after the type it enhances but in the plural form. So it is now pretty obvious that Arrays is a helper class for the Array type as Strings is a helper class for String.

So far I am really focused to add (and to improve) features and I am not really worry about file size or performances. Some of the helper classes are pretty dense and refers to other dense definitions which can add some weight to your output. This issue will be addressed at some point by improving thx compatibility with haxe DCE (Dead Code Elimination) or maybe splitting the classes.

Back on the post topic, I’d like to introduce a few of the options you can find in Arrays. So I assume for the following examples that using Arrays; is always in place since that makes the programmer life even easier.

Arrays adds some functions to enhance method chaining, for example you can write:

var arr = [].add(1).add(2).addIf(value > 2, 3).remove(2);

Many methods in Arrays derive from the Lambda class found in the std library but tend to be more flexible and the definitions are also repeated in Iterators and Iterables to make your life easier. Whenever is possible inline is used to prevent adding a new level of indirection. Note that if a method returns a list, it always returns an Array, even if you are using the Iterator or Iterable type. Arrays are pretty fast on all the platforms and are a lot more flexible than the iterators.

// Ints.range(10) returns an array of int from 0 to 9
var arr = Ints.range(10)
  .filter(function(d) return 0 == d % 2)
  .map(function(d,i) return d*d);
// arr is [0,4,16,36,64]

Since hxculture has been included inside thx, you can format many types (and Array is not an exception) to string in a localized fashion. So far you can use 2 formats with array J for “join” and C for “count”.

trace(arr);  //  [0,4,16,36,64]
trace(arr.format("J")); // 0, 4, 16, 36, 64
// the first parameter is for the format of each individual value
trace(arr.format("J", ["D"]));  //  0.00, 4.00, 16.00, 36.00, 64.00
// the second parameter is for empty array
trace([].format("J", ["D", "-"]));  //  -
// the third parameter is the separator
trace(arr.format("J", ["D", "-", "; "]));  //  0.00; 4.00; 16.00; 36.00; 64.00
// the fourth parameter is the max number of elements to display
trace(arr.format("J", ["D", "-", "; ", "3"]));  //  0.00; 4.00; 16.00 ...
// the fifth parameter is for the remaining elements after max
trace(arr.format("J", ["D", "-", "; ", "3", " and more"]));  //  0.00; 4.00; 16.00 and more

trace(arr.format("C"));  //  5

You can also create a format function using var f = Arrays.formatf("J", ["D"]); and after that f([1,2,3]);

Functions like .all()/.any() permits to check if all or at least one of the elements of the array matches a certain rule. The rest of the functions in Arrays are pretty obvious to catch but if you have any doubt I will be glad to five more insights.

thx: color

thx is really growing fast and since it is not yet documented I want to start giving users some hints on the classes included.

The thx.color package is the first set of features I will introduce since the API is pretty stable and I use it a lot.

Creating a color from its channels is really easy:

var color = new Rgb(255, 0, 0); // RGB values are integers from 0 to 255

Of course you can use alternatives to create a Rgb color:

color = Rgb.fromInt(0xFF000);

or

color = Rgb.fromFloats(1.0, 0.0, 0.0);

… but if you are as lazy as I am you can use:

color = NamedColors.red;

or even

color = Colors.parse("red");

Note that Colors.parse() will try everything to find a matching color, infact you can pass a:

  • color name, as defined in NamedColors; names with spaces are accepted aswell (ei: “dark sea green“)
  • css color: #ff0000
  • rgb definition: rgb(255,0,1)
  • hsl definition: hsl(0,1,0.5)
  • cmyk definition: cmyk(0,1,1,0)

Other than Rgb you can define colors in the following colorspaces: Hsl, Grey, Cmyk

I find Hsl particularly useful when you want to create smooth interpolations:

using thx.colors.Hsl;
// ...
var midcolor = Hsl.interpolate(NamedColors.red.toHsl(), NamedColors.blue.toHsl(), 0.5);

If you want to recycle the interpolation and generate an array of colors you can use:

using Arrays;using thx.colors.Hsl;
// ...
var f = Hsl.interpolatef(NamedColors.red.toHsl(), NamedColors.blue.toHsl()),	len = 10;
var colors = Ints.range(len).map(function(_, i) return f(i / (len-1)));

The interpolate/interpolatef methods in Colors will do the same but starting from string definitions.

This can be very handy when you want to interpolate a CSS color. The Rgb.contrast/constrastBW methods are also pretty useful. The former will try to find a pastel color that contrasts with the passed one while the latter will always return white or black. The algorithm of contrastBW uses the grey equivalent of the passed color to estabilish the better contrast for the human vision.

ufront/uform/thx demo from haxecon 2011

Eventually I’ve found the time to put everything together and here come my demos from haxecon 2011.

You can play with it live or you can download the project and compile/run it on your machine.

To compile the project you must have installed through haxelib the following libraries (be sure you are using the correct version because the API will probably change before the 1.0 release):

Note that uform is included in the project and you don’t need to install anything for it.

To run the example on your machine you will probably have to tweak a couple of things:

  • Main.hx: if you use mod_rewrite you will have to create your .htaccess file and change the parameter in the Config constructor from “false” to “true”. Also, if you run the demo from a subfolder different then demo you will have to change that parameter too; if you plan to run in root just put “/” in the path argument.
  • demo/Config.hx: Change your connection settings for your Mysql database and be sure to create a table in the DB with the structure described in the same file.

The project is divided into 3 separate projects:

  • web-pages (both php and neko), use the haxecon.php.hxml or haxecon.neko.hxml to compile
  • colors example page (js), compile using haxecon.d3colors.hxml
  • d3.js port examples (js), compile using haxecon.d3examples.hxml

The live demo on this website is running on neko which is way faster than the php version.

Friend types are slow … really?

If you followed the post about friend types or the discussion about that topic on the haXe mailing list started by Michael Baczynski, you may believe that friend types can be slow. This is true (we are talking about targeting flash 9 here) if you use a temporary variable to “cast” the friend instance, but there is a workaround for that.

So suppose you have this class:

class Test
{
  var value : Int; // this is the private field we want to expose as friend
  public function new() {
    value = 1;
  }
}

The friend type is:

typedef TestFriend = {
  private var value : Int;
}

So what are your options?

The simple one:

var test = new Test();
var friend : TestFriend = test;
var v = friend.value;

This is not fast because test needs to be converted to a dynamic type to be used like that. Here is the alternative, first create an utility method as such:

class TestUtil {
  public static inline function getValue(t : TestFriend) {
    return t.value;
  }
}

Then use it:

var test = new Test();
var v = TestUtil.getValue(test);

Does it perform better? A lot (even faster that untyped). Is it type safe? Sure … no need for untyped.

Using “using” makes it even nicer:

using TestUtil;
// ...
var test = new Test();
var v = test.getValue();

About perfomances, I’ve made a test on 2.000.000 iterations (average on 5 cycles) and here are the results:

  • using a temp var (reassigned on each iteration): reference time (454.0 ms)
  • using a temp var (assigned once): 14% faster (397.8 ms)
  • untyped46% faster (310.6 ms)
  • using the static getValue() function: 50% faster (301.8 ms)

 

Attributes with haXe (AKA Metadata or Annotations)

Many languages support metadata in the form of additional information attached to classes, methods or variables. In this post I provide a sample implementation to produce such a thing in haXe.
I created a class Attributes (source code attached to this post) with the following signature:

class Attributes {
public static function of(cls : Class, ?field : String) : Attributes;
public var parent(default, null) : Attributes;
public function exists(key : String) : Bool;
public function get(key : String, ?alternative : String) : String;
public function set(key : String, value : String) : Void;
public function isInherited(key : String) : Bool;
public function keys() : Iterator;
public function iterator() : Iterator;
public function toString() : String;
}

Instances of the class cannot be created directly but they must be obtained using the static method Attributes.of(). The first parameter is the type of the class we want to retrieve attributes, the second optional parameter is a field of that class (it works with either static or instance members). The class is very similar to Hash with the exception that attributes are inherited; so class B that extends class A can inherit or redefine the attributes of B.

Let’s see how we can use the class.

import attributes.Attributes;
import haxe.rtti.Infos;

/**
* @author Franco Ponticelli
* @year   2009
*/
class Main implements Infos {
/**
* @role entry point
*/
static function main() {
trace("attributes of Main: " + Attributes.of(Main));
trace("attributes of Main.main: " + Attributes.of(Main, "main"));
}
}

The output is:

Main.hx:15: attributes of Main: { author : Franco Ponticelli, year : 2009 }
Main.hx:16: attributes of Main.main: { role : entry point }

In the first case we have retrieved the attributes of the class Main while in the second the attributes of its method main().

If you want to try you can’t forget about two things: classes that provide attributes must implement haxe.rtti.Infos and you must add the directive -D use_rtti_doc when you compile your project. The latter informs the compiler that nodes must be included in the generated code.

One nice thing about attributes is that they are both “code” and documentation. Attributes can have a lot of applications, in ORM they can be used to wire a class name to a SQL table name or to map fields and relations to columns; in controllers they can be used to bind a method to certain credentials or templates; in a unit testing system they could be used to mark the functions that are test methods.

There is one thing are a couple of things to consider before embracing this technique, rtti info are stored as XML in the code and the parsing can be slow (the provided implementation caches the results to speed things up) and there is currently a bug in the -D use_rtti_doc: overrode methods do not bring their documentation so attributes attached to them are simply discarded. Hopefully the latter problem will be addressed soon. (bug fixed in CVS, version 2.05 will be bug free)

download here: Attributes.v.1.0

Friendly types with haXe

If you are experienced with haXe you’ll know that its type system permits to catch a lot of errors at compile time simply veryfing that parameter/member types are correctly used in your application. Members can only have two access modifiers: public or private. But what if you want to emulate something like the “friend” modifier that exists in other languages?

Let’s see a practical example.

class Test {
  static function main() {
    var c = new Container();
    var n1 = c.add(new Item("John"));
    var n2 = c.add(new Item("Jane"));

    trace(c);
    trace(n1);
    trace(n2);
  }
}

class Container {
  public function new() {
    children = new List();
  }
  public function add(n : Item) {
    children.add(n);
    return n;
  }

  public inline function iterator() { return children.iterator(); }
  public inline function count() { return children.length; }

  public function toString() {
    return "[Container] has " + children.length + " children";
  }

  var children : List;
}

class Item {
  public var parent(default, null) : Container;
  public var name(default, null) : String;
  public function new(name : String) {
    this.name = name;
  }
  public function toString() {
    if(parent != null)
      return "[Item] " + name + " has " + (parent.count() - 1) + " sibblings";
    else
      return "[Item] " + name + " has no parent";
  }
}

This flat hierarchy proves my point because something is missing, the Item instances never receive a reference to their container and the field parent is always null. The output trace is:

Test.hx:8: [Container] has 2 children
Test.hx:9: [Item] John has no parent
Test.hx:10: [Item] Jane has no parent

I don’t want to expose parent as public or pass it in the Item constructor because I want my hierarchy to be composed just using the method add (in real life a lot of things can lead to that decision).
With a friend I could just add this to Item:

// friend method
private function setParent(p) {
  parent = p;
}

But how do you call that safely from outside the Item class? It is private so it cannot be invoked directly … you can use untypedto make the compiler skip the types check on that call; but what happens if you want to change the name of setParent toset_parent at a later point and forget to change the untyped call too? The compiler will not spot the error and you’ll only catch it at runtime when some strange behavior will pop.

Here it comes the solution, change the Container.add function this way:

public function add(n : Item) {
  children.add(n);
  var p : { private function setParent(p : Container) : Void } = n;
  p.setParent(this);
  return n;
}

I have created a temporary var p whose type is exactly and only what we need to access the “friend” method. It works without any casting or untyped access because the type of “p” is structurally a sub-type of Item making it implicitly compatible. We can callsetParent from p because typedefs define a structure but do not impose any access limit.

Now the output is what expected at first:

Test.hx:7: [Container] has 2 children
Test.hx:8: [Item] John has 1 sibblings
Test.hx:9: [Item] Jane has 1 sibblings

If and when you will change the name of Item.setParent the compiler will throw an error notifying that Item is no more compatible with the type of p.
Many thanks to Nicolas Cannasse that suggested this unusual way of using typedefs on the haXe mailing list.

 

Optimize cache for autoloading classes in haXe/PHP

The code generated using haXe/PHP uses the PHP autoloading feature to dynamically load classes definitions when they are required. This method has many advantages but a drawback too; the thing is that the autoloading function (hidden in php.Boot) needs to scan the lib folder to look for type definitions. It is not really a big work since only the file names are read without the need to immediately open the files, nevertheless this work is made each time the page is accessed. To reduce the impact of this operation you can simply create a cachefolder at the same level of lib and give it the proper attributes for PHP being able to write files in there. On the next use of your script, a new file haxe_autload.php will be automatically generated and will contain all the info required by the autoloading function.

As you can guess, the impact of this feature is proportional to the number of classes included in your project.

Be warned that it is better to use the cache only on production sites because during development it is quite normal adding new classes and the cache will not include them unless thehaxe_autload.php file is manually deleted. If you need to upgrade your production code, remember to delete that file first!

edit: I’ve made a few informal tests compiling a project that generates 76 files but uses only a few of them to maximize the impact of the cache trick. The results are the following but remember that your mileage may vary greatly and you can also find out that you will not have any benefit from abilitating the cache feature.

Execution time:
198ms no cache
151ms cache activated (31% speed gain)

 

haxe.Stack for PHP

Starting from haXe 2.04 the PHP generator supports the -debug switch. The implementation is almost identical to the haXe/JS one where the function calls are stored in a stack. You can see it working when you have an uncaught exception or using the haxe.Stack methods as in the following example:

import haxe.Stack;
class Test {
  static function main() {
    var f = function() { ref(); };
    f();
  }

  static function ref() {
    throw "error";
  }
}

The output will be:

uncaught exception: error

Called from Test::ref
Called from Test::main@4
Called from Test::main

Note that @4 means that a local function is involved.
You can obtain the same output without generating an exception replacing throw "error" with:

trace(Stack.toString(Stack.callStack()));

Is it appropriate to remove the -debug switch when compiling for deployment since it adds extra code to your output.