[erlang-questions] Pattern-matching function?

Richard Carlsson richardc@REDACTED
Thu Oct 30 09:30:29 CET 2008


Francois De Serres wrote:
> Thank you Richard. 
> Any way to overcome this with parsing/binding/eval magic, even cumbersome ?

Depending on what you need, in terms of efficiency (is the code going to
be a bottleneck, or just executed occasionally?), and if you really need
to do metaprogramming (often a big *if*), there are several options:

 - Output the code as plain text to a .erl-file and call the compiler.
   (Dead simple, and quite flexible - can use macros and includes for
    "template" stuff so you don't need to generate that as well.)

 - Generate the code as text in memory, call the scanner and parser, and
   pass the result to compile:forms/2. You can't use the preprocessor
   this way (it only works on files), but you don't have to go to disk,
   and you don't need to learn about the syntax tree representation.

 - Generate the syntax trees directly and pass to the compiler. Fiddly,
   unreadable and hard to maintain, but low-overhead and full control.

But doing compilation on the fly might not be suitable if you are going
to do it a million times (unless you can reuse the same module name, you
will have to generate unique module names for each new compilation, and
who will then be responsible for deleting unused modules?). If the code
you are going to run is short and not a bottleneck, it could be better
to use erl_eval, for example like this:

make_match_fun(Pstr) -> element(2, erl_eval:expr(hd(element(2,
erl_parse:parse_exprs(element(2,
erl_scan:string(lists:flatten(io_lib:format("fun (~s=__P) ->
{matched,__P}; (_) -> fail end.", [Pstr]))))))), erl_eval:new_bindings())).

This will, via erl_eval, produce a fun that can be used like you wanted:

F = make_match_fun("{X,Y}")

F({1,2}) ==> {matched, {1,2}}

F({}) ==> fail

    /Richard



More information about the erlang-questions mailing list