[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