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 replies on “The new Map syntax in Haxe 3”
Really nice feature !
You should really add it into the wiki, if it’s not already there.
Really nice work documenting it too, also.
The new map syntax with “=>” operators also makes it much easier to write macros!
var mapExpr = macro [ $a{ [ $v{ “key” ] => $v{ “value” } } ];
Aw darn, macro typo. I’ll try that again:
var mapExpr = macro [ $a{ [ $v{ “key” } => $v{ “value” } ] } ];
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.
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…
Thanks! That’s a lot more useful than the original “Go search through numerous arrays” I had used.
How do enums work as keys in a Map? Do they use the Type.enumEq to compare the enums?
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.