Jeff Ward
Jeff Ward

Reputation: 19026

How to force Haxe macro return type to Array / Iterable?

I want to write a macro that returns an (expression of an) Array -- but I can't seem to convince the compiler that my returned value will be typed as an Array. I always get "you can't iterate on a Dynamic value", even though I've tried:

  1. Explicitly typing the return as: ExprOf<Array<Whatever>>
  2. Inserting a type hint in the output

http://try-haxe.mrcdk.com/#D7D82

import haxe.macro.Context;
import haxe.macro.Expr;

class Test {
  static function main() {
    trace("Haxe is great!");
    // ERROR: You can't iterate on a Dynamic value
    for (val in Macro.someArrayExpr()) {
      trace(val);
    }
  }
}

class Macro
{
  public static macro function someArrayExpr():ExprOf<Array<String>>
  {
    // Neither of these works:

    // Try to insert a type hint:
    // return Context.parse('([]:Array<String>)', Context.currentPos());

    return macro [];
  }
}

Upvotes: 3

Views: 186

Answers (1)

Jeff Ward
Jeff Ward

Reputation: 19026

Uh oh, it looks like it's a side effect of defining my Macro class in the same module (file) as my invocation. Separating the classes into separate files makes it work!

http://try-haxe.mrcdk.com/#57801

Test.hx:

class Test {
  static function main() {
    trace("Haxe is great!");
    // Hooray, it works!
    for (val in Macro.someArrayExpr()) {
      trace(val);
    }
  }
}

Macro.hx:

import haxe.macro.Context;
import haxe.macro.Expr;

//use this for macros or other classes
class Macro
{
  public static macro function someArrayExpr():ExprOf<Array<String>>
  {
    return macro ["a", "b", "c"];
  }
}

The technical explanation for this (thanks to Juraj): the Test class is being typed in the macro context. In that case, it's calling the macro from a macro, which is always typed Dynamic, hence the error. So another solution is to exclude the class Test from being compiled into the macro context: http://try-haxe.mrcdk.com/#1f3b2

Upvotes: 4

Related Questions