COMMUNITY

Cast enum after Json conversion?


(Aartzrc) #1

I have some data coming in after being parsed by Javascript JSON.parse via an extern. I don’t have control over the external code but I need to clean up enum values to do some comparisons. EnumValueTools.equals doesn’t seem to handle it properly, but other calls do. Is there a way to do a cast or other parsing to clean things up?

Here’s an example to demonstrate:

using haxe.EnumTools.EnumValueTools;

class Test {
  static function main() {
    var i1 = Val;
    var i2 = Val;
    doCompare(i1, i2); // OK
    
    // Convert to json and back
    var i3:Something = haxe.Json.parse(haxe.Json.stringify(i2));
    doCompare(i1, i3); // Not OK    
  }
  
  static function doCompare(a:Something, b:Something) {
    trace(a.equals(b)); // This fails sometimes
    trace(a.getIndex() == b.getIndex()); // This works for shallow comparison
    
    // This works but gets messy and hard to maintain
    switch(b) {
        case Val:
        	trace("works");
    }
    
    // Any way to cast?
    var bcast = cast(b, Something);
    trace(bcast);
  }
}

enum Something {
  Val;
}

Something that bothers me is that EnumValueTools.equals doesn’t work when the other comparison methods do. Does anyone out there know a way to validate an enum before doing the comparison?

update

After various tests it seems like casting an Enum isn’t possible, but doing an EnumValueTools.match call is the shortest/safest way to clean things up besides a switch:

var a = Val;
var b = haxe.Json.parse(haxe.Json.stringify(a));
trace(a.match(b)); // This works!

(Aartzrc) #2

Ok, not to beat this one to death but I’ve realized switch seems to be the only way to accurately do searches in enums. I’m hoping someone out there can help me, I’m doing searches through arrays of enum instances and I can’t seem to find a clean solution.

Take a look at this (http://try-haxe.mrcdk.com/#94736):

using Lambda;

class Test {
    static function main() {
        var items:Array<ItemType> = [ SomeType("good"), SomeType("bad") ];
        
      	var matchItem = SomeType("good");
      	
        switch(matchItem) {
            case SomeType(matchVal):
              trace(matchVal);
              trace(matchVal == "good");
              trace(items.filter(function(i){ 
            		return i.match(SomeType(matchVal)); // Direct match fails because matchVal is a runtime value?
        			}));
            	trace(items.filter(function(i){ 
                  return switch(i) {
                    case SomeType(val):
                      val == matchVal; // Have to extract the value and compare manually
                } 
        			}));
            	trace(items.filter(function(i){ 
            		return i.match(SomeType("good")); // This works because "good" is handled at compile time?
        			}));
        }
      	
    }
}

enum ItemType {
  SomeType(withVal:String);
}

Enum.match() just doesn’t work with a runtime variable from what I can tell, any ideas? Thanks!


(Alexander Blum) #3

Have you tried using Type.enumEq?
It’s not super fast, so if you have thousands of enum instances to compare, you might want to keep that in mind.


(Aartzrc) #4

Thanks for the response, Type.enumEq is a good thing to be aware of! It doesn’t quite do the trick I need however because it can’t take a pattern. Take a look at this example:

http://try-haxe.mrcdk.com/#6600a

I’m trying to do a generic ‘lookup’ on the array using SomeType(matchVal1, _) but I think the problem is I can’t create the match pattern at run time so I have to iterate and compare instead.

I love the Haxe enum system, it comes in handy for so many things. This one just threw me off that there isn’t a direct way to match patterns using run time values. In other words, this isn’t a rant I’m just hoping to find a clean solution for doing a run time pattern match.