<html>
<head>
<meta content="text/html; charset=ISO-8859-1"
http-equiv="Content-Type">
</head>
<body bgcolor="#FFFFFF" text="#000000">
I really, really want to recommend option 5: not using parametrized
modules.<br>
<br>
Dialyzer is the first of your concerns. Next up, you'll be having
trouble with code tracing, which is also messed up due to the arity
issues. Then what about function guards?<br>
<br>
There are a few valid use cases for parametrized modules, and
Richard Carlsson can demonstrate them well, but I would generally
advise against it (a lot of it is personal preferences, I got to
admit). Shadowing, messed up arities, different semantics, etc. all
annoy me a bit.<br>
<br>
Here's a quick list of the problems, based on the following module:<br>
<br>
<blockquote><tt>-module(pmo</tt><tt>d,[Arg]).<br>
-compile(export_all).<br>
f() -> Arg.<br>
</tt></blockquote>
Using it in a shell started as:<br>
<blockquote><tt>1> c(pmod).</tt><br>
<tt>{ok,pmod}</tt><br>
<tt>2> M = pmod:new(hello).</tt><br>
<tt>{pmod,hello}</tt><br>
</blockquote>
1. function building is broken:<br>
<blockquote><tt>3> fun M:f/0. <br>
** exception error: bad argument<br>
in function erlang:make_fun/3<br>
called as erlang:make_fun({pmod,hello},f,0)</tt><br>
</blockquote>
You can't get the above to work without either forgetting about
parametrized modules (passing the argument to the function) or
wrapping it in an anonymous function as <tt>fun() -> M:f() end</tt>,
although this one has the problem of potentially being purged during
code reload, which a proper pmod anonymous function wouldn't.<br>
<br>
2. Tracing is broken due to changes in arity:<br>
<blockquote><tt>4> dbg:tp({M, f, 0}, []).<br>
** exception error: no case clause matching {pmod,hello}<br>
in function dbg:do_tp/3 (dbg.erl, line 141)<br>
5> dbg:tp({pmod, f, 0}, []).<br>
{ok,[]}<br>
6> dbg:tp({pmod, f, 1}, []).<br>
{ok,[]}<br>
</tt></blockquote>
The first one plainly doesn't work, the second one will never match
anything, and the third one is actually the valid one.<br>
<br>
3. Tricky pattern matching.<br>
If I add the following function definition to the pmod module:<br>
<blockquote><tt>id(Arg) -> Arg.</tt><br>
</blockquote>
And then try to use it, see what can happen:<tt><br>
</tt>
<blockquote><tt>7> c(pmod).</tt><br>
<tt>{ok,pmod}</tt><br>
<tt>8> pmod:id(4).</tt><br>
<tt>** exception error: undefined function pmod:id/1</tt><br>
<tt>9> M:id(4). </tt><br>
<tt>** exception error: no function clause matching
pmod:id(4,{pmod,hello}) (pmod.erl, line 6)</tt><br>
<tt>10> M:id(hello).</tt><br>
<tt>hello</tt><br>
</blockquote>
The way you name the variable will impact pattern matching. Although
it <b>is</b> likely the best behaviour available, it is weird to
have this behaviour happening, you need to watch yourself. This kind
of stuff won't happen if you use pmods with great care, but I'm a
pessimist on these questions.<br>
<br>
Related to this, this isn't the most intuitive kind of error to
debug in the middle of a larger file. If you add:<br>
<blockquote><tt>y() -> fun(Arg) -> Arg end.<br>
</tt></blockquote>
You get compiler warnings telling you <i>pmod.erl:8: Warning:
variable 'Arg' shadowed in 'fun'</i>, still a scoping issue for
the distracted programmer. Imagine using the same variable in a <tt>case
... of</tt> match without thinking of it. Some programmers get it
wrong with the normal scoping rules, nevermind with parametrized
arguments on top of it.<br>
<br>
4. They don't work well with tools like Dialyzer, as you found out.<br>
<br>
Those are the ones I got from the top of my head. I know people will
defend Parametrized modules, that they have valid use cases (I can
admit to a few!), that a lot of these issues are implementation
details that can be fixed, but as of now, they aren't, and they mess
stuff up.<br>
<br>
Sorry, I know this isn't the kind of answer you want to such a
question.<br>
<br>
<div class="moz-cite-prefix">On 12-08-14 4:41 AM, VegaS wrote:<br>
</div>
<blockquote
cite="mid:CAPMh89AkavyPKjiREvqV2a=-fA8tXSYwa_nyLVVfSTmYm+6esg@mail.gmail.com"
type="cite">Hello all!
<div><br>
</div>
<div>We are using parametric modules in our project and were quite
happy with them unless we have started using Dialyzer.</div>
<div>Dialyzer fails on parametric modules because functions in
parametric modules are expanded with module params argument on
compilation stage - so function's specs are unmatched.</div>
<div><br>
</div>
<div>I know that parametric modules not the official part of
Erlang, but I'd like to get both parametric modules and dialyzer
working. I have tried to do some work on this:</div>
<div>1. Try to fix specs on parametric module's functions with
parse_transform - simply extend specs on this stage, but this
won't work, code just won't compile (because of specs for
unknown functions)</div>
<div>2. More complicated approach - try to implement parametric
modules with parse_transform (create "new" function and extend
all module functions and specs). This looks working unless some
code like</div>
<div>
SomeFun = local_fun/1, SomeFun(Arg) and some variations
like this local function is assigned to record field.</div>
<div>3. Decided that there no way out besides patching OTP sources
or not using parametric modules at all. After looking at OTP
sources I have found, that parametric modules are expanded on on
"<span
style="line-height:16px;color:rgb(51,51,51);font-size:12px;white-space:pre-wrap;font-family:Consolas,'Liberation
Mono',Courier,monospace">expand_module</span>" compiler pass.
And on that stage specs are not expanded. I Have patched this
stage with specs expand. All were correct, but dialyzer fails
with message like specs were not fixed, so no luck... This
happend because dialyzer using "abstract_code" from beam to
extract specs and pass "<span
style="line-height:16px;color:rgb(51,51,51);font-size:12px;white-space:pre-wrap;font-family:Consolas,'Liberation
Mono',Courier,monospace">save_abstract_code</span>" is just
before "<span
style="line-height:16px;color:rgb(51,51,51);font-size:12px;white-space:pre-wrap;font-family:Consolas,'Liberation
Mono',Courier,monospace">expand_module</span>" pass.</div>
<div>Simple changing these passes order broke dialyzer at all.</div>
<div>4. The last attempt were to patch dialyzer - on the stage,
when it extracts specs info from beam's abstract_code section.
At this place I insert function's specs expanding with last
parametric parameter - and it works!</div>
<div><br>
</div>
<div>So the question is what the rigth way to make both parametric
modules and dialyzer working?</div>
<div>At my opinion there are no way except OTP sources patching -
but what the rigth place for making such patch? </div>
<div><br>
</div>
<div>I can attach my patch here but it is little ugly (I were
tired by previous explorations) and I think I have chosen not
rigth place for changing.</div>
<div> </div>
<div><br>
</div>
<div>Thanks,</div>
<div>
Lihanov Alexandr</div>
<br>
<fieldset class="mimeAttachmentHeader"></fieldset>
<br>
<pre wrap="">_______________________________________________
erlang-questions mailing list
<a class="moz-txt-link-abbreviated" href="mailto:erlang-questions@erlang.org">erlang-questions@erlang.org</a>
<a class="moz-txt-link-freetext" href="http://erlang.org/mailman/listinfo/erlang-questions">http://erlang.org/mailman/listinfo/erlang-questions</a>
</pre>
</blockquote>
<br>
</body>
</html>