The new Map syntax in Haxe 3

I was using the Haxe3 Release Candidate for well over a month before I realised that the new Map data structures could be created with a nice syntax.  The basic gist is this:

var map1 = [ 1=>"one", 2=>"two", 3=>"three" ];

Like Arrays, but you use the “=>” operator to define both the key and the value.  And Haxe’s type inference is as strong as ever.  Here’s what the compiler picks up:

var map1 = [ 1=>"one", 2=>"two", 3=>"three" ];
$type (map1); // Map<Int, String>

var map2 = [ "one"=>1, "two"=>2, "three"=>3 ];
$type (map2); // Map<String, Int>

var map3 = [
    Date.now() => "Today",
    Date.now().delta(24*60*60*1000) => "Tomorrow",
    Date.now().delta(-24*60*60*1000) => "Yesterday"
];
$type (map3); // Map<Date, String>

var map4 = [
    { name: "Tony Stark" } => "Iron Man",
    { name: "Peter Parker" } => "Spider Man"
];
$type (map4); // Map<{ name : String }, String>

var map5 = [
    [1,2] => ["one","two"],
    [3,4] => ["three","four"],
];
$type (map5); // Map<Array<Int>, Array<String>>

So it’s pretty clever.  If for some reason you need to type explicitly to StringMap, IntMap, or ObjectMap, you can:

var stringMap:StringMap<Int> = [
    "One" => 1,
    "Two" => 2
];
$type(stringMap); // haxe.ds.StringMap<Int>

var intMap:IntMap<String> = [
    1 => "One",
    2 => "Two"
];
$type(intMap); // haxe.ds.IntMap<String>

var objectMap:ObjectMap<{ name:String }, String> = [
    { name: "Tony Stark" } => "Iron Man",
    { name: "Peter Parker" } => "Spider Man"
];
$type(objectMap); // haxe.ds.ObjectMap<{ name : String }, String>

But if you try to do anything too funky with types, the compiler will complain.  Haxe likes to keep things strictly typed:

var funkyMap = [
    { name: "Tony Stark" } => "Iron Man",
    { value: "Age" } => 25
]; // Error: { value : String } has no field name ... 
   // you are a bad person, and your items are not comprehensible 
   // to Haxe's typing system

Finally, Haxe won’t let you do define duplicate keys using this syntax:

var mapWithDuplicates = [
    1 => "One",
    2 => "Two",
    1 => "uno"
]; // Error: Duplicate Key ... previously defined (somewhere)

If you’re using an object map, it’s only a duplicate if you’re dealing with the exact same object, not a similar one.  For example, this is allowed:

var similarObjectKeys:ObjectMap<Array<Int>, String> = [
    [0] => "First Array object",
    [0] => "Second Array object"
]; // Works, you now have 2 items in your map.

But if you use the exact same object, Haxe will pick it up:

var key = [0];
var sameObjectKey = [
    key => "First Array object",
    key => "Second Array object"
]; // Error: Duplicate Key ...

So there you have it.  A nice feature that I didn’t see mentioned anywhere else.  Thanks Haxe team!

….

Update:

It’s worth mentioning that once you have created your map, you can use array access (“[” and “]”) to read or modify entries in your map.

var map = [ 1=>"one", 2=>"two", 3=>"three" ];

// Reading a value
map[1];   "one"
var i = 2;
map[i];   "two"
map[++i]; "three"

// Setting a value
map[4] = "four";
map[1] = "uno";
map[i] = "THREE";
map;   // [ 1=>"uno", 2=>"two", 3=>"THREE", 4=>"four" ]

8 thoughts on “The new Map syntax in Haxe 3

  1. The new map syntax with “=>” operators also makes it much easier to write macros!

    var mapExpr = macro [ $a{ [ $v{ “key” ] => $v{ “value” } } ];

  2. Been wondering: Can you use maps to locate maps?

    Say, I put example:Map

    For example, I make a game where certain weapons have certain bonuses against certain armors. So, it would be easy for me to have one map with data about damages and another map, where I put used weapon name and it brings the map for bonuses.

  3. Hi Mandemon, you would use something like:

    // create the overall map
    var bonuses = new Map<Weapon, Map<Armour,Bonus>>();

    So essentially the first map uses the weapon as a key, and returns another map, specific to that weapon, where the armous is the key, and the value is the bonus.

    You could set your values like so:

    // Create sub-maps
    bonuses[sword] = new Map();
    bonuses[spear] = new Map();
    // Set bonuses for weapon/armour combinations
    bonuses[sword][leather] = 30;
    bonuses[sword][iron] = 5;
    bonuses[spear][leather] = 30;
    bonuses[spear][iron] = 5;

    And then you can fetch them with:

    var bonus = bonuses[someWeapon][someArmour];
    var bonus = bonuses[sword][leather];
    var bonus = bonuses[spear][iron];

    etc…

    • Check out EnumValueMap:

      http://api.haxe.org/haxe/ds/EnumValueMap.html

      You should be able to use it like so:

      var objects:Map = new Map();
      objects[Red] = “rose”;
      objects[Green] = “grass”;
      objects[Grey(200)] = “cement”;

      According to the docs:

      Keys are compared by value and recursively over their parameters. If any parameter is not an enum value, Reflect.compare is used to compare them.

Leave a Reply

Your email address will not be published. Required fields are marked *