This is me

Tuesday, 10 June 2008

"Dynamic" module generation with compile-time macros

Over on the Erlang Questions mailing list, Jacob Perkins asked:

"I have a few files that are basically lists of words. What I want to do is generate a module whose functions will return each list of words. So if I have two files named "adjectives" and "nouns", then the generated module (let's call it 'grammar') should have two functions, adjectives() and nouns(), that return their respective list of words.

How can I do this?"

If I had some method of running Erlang code at compile-time - and I do - then I could write a program to slurp in those adjective and noun files and generate the appropriate functions.






-export([nouns/0, adjectives/0]).
-compile({parse_transform, emp2}).

-macro({grammar_macro, generate, [nouns]}).
-macro({grammar_macro, generate, [adjectives]}).



generate(NameFun) ->
{ok,Fd} = file:open(atom_to_list(NameFun) ++ ".txt", [read]),
generate(Fd, NameFun, []).

generate(Fd, NameFun, Words) ->
case io:get_line(Fd, "") of
eof ->
io_lib:format("~w() -> ~w.~n", [NameFun, lists:reverse(Words)]);
Word -> generate(Fd, NameFun, [Word | Words])

And in the Erlang shell:

1> c(grammar_macro), c(grammar).
2> grammar:nouns().
3> grammar:adjectives().

Obligatory legal stuff

Unless otherwise noted, all code appearing on this blog is released into the public domain and provided "as-is", without any warranty of any kind, express or implied, including but not limited to the warranties of merchantability, fitness for a particular purpose and noninfringement. In no event shall the author(s) be liable for any claim, damages, or other liability, whether in an action of contract, tort or otherwise, arising from, out of or in connection with the software or the use or other dealings in the software.