Macro tutorials

347 views
Skip to first unread message

Benjamin Dubois

unread,
Feb 12, 2015, 1:56:31 AM2/12/15
to haxe...@googlegroups.com
If the true potential of haxe is in its macros, there is a a real lack of tutorial.

I acknowledge the manual being everyday better and I found few interesting tutorials but
the truth is that
still  I can not understand most macro when I see one. I mean, I can get the idea but I'm not capable of saying what would fail or why it would. Making me the worst macro coder ever.

Unless there is a macro for that ?

Axel Huizinga

unread,
Feb 12, 2015, 2:33:41 AM2/12/15
to haxe...@googlegroups.com
I experience exactly the same
Unless there is a macro for that ?
--
To post to this group haxe...@googlegroups.com
http://groups.google.com/group/haxelang?hl=en
---
You received this message because you are subscribed to the Google Groups "Haxe" group.
For more options, visit https://groups.google.com/d/optout.


Juraj Kirchheim

unread,
Feb 12, 2015, 5:02:40 AM2/12/15
to haxe...@googlegroups.com
What would such a tutorial look like? I'd love to help, but I generally shun tutorials, making me the worst tutorial writer ever ;)

Are you actually missing information? Or is it not rather a lack of practice?

Best,
Juraj

--

Franco Ponticelli

unread,
Feb 12, 2015, 11:48:01 AM2/12/15
to haxe...@googlegroups.com
Juraj, you should write a book, not a tutorial :)

Sven Bergström

unread,
Feb 12, 2015, 1:15:34 PM2/12/15
to haxe...@googlegroups.com
I have written an initial introduction to macros with some links to other examples/tutorials here;
http://notes.underscorediscovery.com/haxe-compile-time-macros/

I have a second post in draft which has a lot more concrete example/tutorial as well, so keep an eye out :)
Hope that helps.

Marcelo de Moraes Serpa

unread,
Feb 12, 2015, 1:23:27 PM2/12/15
to haxe...@googlegroups.com
+1 for a book by Juraj ;)

Marcelo de Moraes Serpa

unread,
Feb 12, 2015, 1:25:45 PM2/12/15
to haxe...@googlegroups.com
<offtopic>
Seriously, if a great intermediate/advanced (and updated) book for Haxe is written I’d pre-buy it if needed. Don’t want to deviate from the main question by the OP, but since we already touched the subject ;) I’d also contribute to a crowdsourcing campaign if one is created.
</offtopic>

Benjamin Dubois

unread,
Feb 12, 2015, 3:56:23 PM2/12/15
to haxe...@googlegroups.com
I have no idea what it should look like. And yes I lack of practice since I can't get where to start with macro.

Thank you Sven I'll read that.

As for what I don't understand :
- I don't understand what I can do and when, for instance I often see macro using non macro function (to make tests for instance) but I have hard time to understand how the non macro function is already available at macro time.
- Since one can modify the code, I suppose one can modify the modified code and so on ? And maybe and up doing it in an infinite loop ? How do you handle / detect that ?
- I've found only sparse use of macro for metadata
- There are macro (or macro like) stuff pre-build with haxe compiler, for instance @:require. How do you know what is evaluated first ? How do you hack require behavior (if possible) ?

Hope it clarifies what confuses me

JLM

unread,
Feb 13, 2015, 5:43:49 AM2/13/15
to haxe...@googlegroups.com
I think most of us have tried a simple macro, but beyond that we don't really have an overview of the whole approaches. 

I think if you just recorded your screen as you showed how to move runtime code into macros that would really help, any examples relating to visual code would keep the topic from being too dry so something on using Macros for UI and graphics processing. 

For instance could we calculate fractal bitmaps or draw commands using Macros ( I know you enjoy maths so I am sure fractals would be fun ). 

I guess others might be less curious about visual examples but some graphics would open it up for a wider audience.  I guess the other alternative would be creating complex Spod commands with Macros... or something - at which point my eyes would probably glaze over, I think you would be far better showing how to create them for tweens starting from penners tutorial/chapter on basic tweens. I am always more excited if I can see visual potential and some nice pixels.

VLC is quite easy to record screen I can explain it's use for this over irc sometime if needed.

Juraj Kirchheim

unread,
Feb 13, 2015, 2:58:52 PM2/13/15
to haxe...@googlegroups.com
On Thu, Feb 12, 2015 at 9:56 PM, Benjamin Dubois <bubbl...@gmail.com> wrote:
I have no idea what it should look like. And yes I lack of practice since I can't get where to start with macro.

I think you should first decide what you want to do, and then we can see how to go about it.

As for what I don't understand :
- I don't understand what I can do and when, for instance I often see macro using non macro function (to make tests for instance) but I have hard time to understand how the non macro function is already available at macro time.

This is the tricky bit. What is important to understand is that to use macros, your code is compiled *twice* into two different contexts, let's call them macro context and output context. In the macro context, `#if macro` applies and the method bodies of `macro` functions are compiled.  In the output context, `#if macro` is skipped and `macro` functions are entirely virtual. They only exist in the type system. 

As the compiler performs the typing - which converts the AST (what the parser parsed) into the tAST (the typed version, where types are checked, identifiers are resolved, methods are inlined, accessors are applied, etc. - it can encounter a call to a `macro` function. In that case, the compiler will invoke the function of the same global name in the macro context, passing the argument list into it (the expressions, not the values!) and taking the returned expression, which is then used to substitute the original call expression.

The macro context is an almost fully fledged Haxe context. You have everything that you also have in a normal Haxe program, except support for macros (macro-in-macro support is limited) and a central entry point (the code in the macro context being entered as the typer of the output context requires it).

Take this simple Haxe module:

  class Main {
    #if !macro
    static function main() {
      test();
    }
    #end  
    macro static function test() {
      return makeHelloWorld();
    }
    #if macro
    static function makeHelloWorld() {
      return macro trace('hello world');
    }
    #end
  }

In the macro context it looks like this:

  class Main {
    macro static function test() {
      return makeHelloWorld();
    }
    static function makeHelloWorld() {
      return macro trace('hello world');
    }
  }

In the output context it looks like this:

  class Main {
    static function main() {
      test();
    }
    macro static function test();
  }

And as I explained, the becomes this:

  class Main {
    static function main() {
      trace('hello world');//this is what was returned by Main.test() called in macro context
    }
  }

It's generally not advisable to put your macro and output code into the same module, as that will hurt your brain badly. But I hope this starts to clarify things.

Beyond expression level macro function calls, there is a couple of other ways for macros to be invoked. Those that matter are:

1. `--macro <expr>` as a compiler argument, which evaluates `expr` in the macro context (from which you can use `haxe.macro.Context` to do all kind of fancy stuff)
2. `@:build(<expr>)` metadata (and `@:autoBuild` and `@:genericBuild`), which evaluates `expr` in the macro context, expecting the result to be of type `Array<haxe.macro.Expr.Field>` and uses that to modify the type that you have annotated with this directive.

- Since one can modify the code, I suppose one can modify the modified code and so on ? And maybe and up doing it in an infinite loop ? How do you handle / detect that ?

There is no straight forward answer to that. It's a general programming problem. Recursion can run to deep, loops can run indefinitely, dependencies or events can be circular and so on. A clean and simple design is the best way to avoid running into this. I've been using macros extensively since they appeared 4 years ago. You wouldn't believe how many stack overflow I've seen ;)
 
- I've found only sparse use of macro for metadata

Sorry, what is the question here?
 
- There are macro (or macro like) stuff pre-build with haxe compiler, for instance @:require. How do you know what is evaluated first ? How do you hack require behavior (if possible) ?

Actually, none of the compiler metadata is implemented with macros anymore. Simn did so to prototype things, but because macro-in-macro doesn't work very well, the implementation has been moved into the compiler.

What is it that you would like to achieve?

Best,
Juraj

Benjamin Dubois

unread,
Feb 13, 2015, 3:45:29 PM2/13/15
to haxe...@googlegroups.com
Wow, thank you, that is, I believe, a really good introduction to macro.

What I'm trying to do is similar to what Andy made for it's jQueryExtern :
@:jQueryVersion({ added : "1.3", deprecated : "1.7", removed : "1.9" })

However, I'd like to use an enum as acceptable version name like
@:libVersion({ added : v1, deprecated : v2, removed : versionIV })

Of course I want code completion to display only available function in the macro and display an error message if one tries to use something not available.

I've tried to mimic Andy's work but he is doing much more than just that in the related function and I had hard sorting it out
https://github.com/andyli/jQueryExternForHaxe/blob/master/jQuery/haxe/Config.hx (in the build function "// filter and group the fields").

That's it

--

Mark Knol

unread,
Feb 14, 2015, 11:33:21 AM2/14/15
to haxe...@googlegroups.com
I also wrote a macro tutorial, hope this helps explaining some stuff (where you *could* use macros for, how the syntax works etc)
http://blog.stroep.nl/2014/01/haxe-macros/

It would be nice to collect several tutorials and create a macro cookbook with snippets etc.

Benjamin Dubois

unread,
Feb 15, 2015, 4:22:08 AM2/15/15
to haxe...@googlegroups.com
Thank you, I had already read this one.

It makes clear what you can do with macro when working with the OS. The macro itself is even useful.
But after reading it I was still not capable of doing my own macro.


It would be nice to collect several tutorials and create a macro cookbook with snippets etc.
Indeed :)

Simon Krajewski

unread,
Feb 15, 2015, 4:45:16 AM2/15/15
to haxe...@googlegroups.com
Am 15.02.2015 um 10:21 schrieb Benjamin Dubois:
Thank you, I had already read this one.

It makes clear what you can do with macro when working with the OS. The macro itself is even useful.
But after reading it I was still not capable of doing my own macro.

Argh... you're the kind of person that is going to complain about any amount and quality of documentation. No tutorials are going to help you as long as you're stuck in that "macros are so hard" mindset and don't really try to implement something in the first place. Just go ahead and do it, then come back with questions on concrete problems.

Simon

Benjamin Dubois

unread,
Feb 15, 2015, 5:35:04 AM2/15/15
to haxe...@googlegroups.com
No no you read it wrong or I wrote it wrong.
The tutorial is good and crystal clear, I was just unable of making my own macro base on that. That's it.

And I'm not stuck in a "macro are so hard" mindset : I'm asking for the help I need. If I believed they are too hard I wouldn't even ask.
Plus I tried some basic macro that worked but I failed as soon as was trying more complex things, that why I think there are stuff I didn't understand correctly in the first place.

--

Juraj Kirchheim

unread,
Feb 15, 2015, 5:54:17 AM2/15/15
to haxe...@googlegroups.com
To be fair, the explanation of the two different contexts is nowhere to be found in the manual and I do think it's important for really understanding macros.

So while Simn's premise is a bit off, his conclusion is bang on: get started and write code that you would expect to do what you want to do and then we can look into why it doesn't do it. What you're after is not particularly hard, but giving you the implementation is really no guarantee that you would suddenly start to understand macros. Practice is irreplaceable. Wax on, wax off! 

So just do it already. Make a gist or a github repo, because we cannot help you with code that we don't see. Have a sample use case and write a build macro for it. Have it walk through the Context.getBuildFields, check them for the @:libVersion metadata and if it doesn't match the constraints, not include them in the returned array. That's it. Checking the constraints is the trickiest bit, but we can help you with problems as they arise ;)

Best,
Juraj

On Sun, Feb 15, 2015 at 10:45 AM, Simon Krajewski <si...@haxe.org> wrote:

--

Mark Knol

unread,
Feb 15, 2015, 6:04:28 AM2/15/15
to haxe...@googlegroups.com
You know what would help? If you start creating some macro code based on the tutorials you've read, then write a tutorial yourself. I may speak for myself, but I learn the most when I write stuff down, try to be accurate. It helps if you are curious what happens and to see what that means. This is not only related to macros, but this helps me with learning programming and understanding libraries too for example. And its nice to share it with others.
Reply all
Reply to author
Forward
0 new messages