[erlang-questions] Must and May convention

zxq9 zxq9@REDACTED
Thu Sep 28 10:27:02 CEST 2017


On 2017年09月28日 木曜日 10:01:12 you wrote:
> > I really wish Dialyzer accepted (and checked) explicit declarations of
> purity.
> 
> i could not agree more
> that would be useful feature and amazing time saver!
> 
> I am currently working on a toll that creates DB of function properties,
> and motivation was exactly finding non pure functions in any given
> project.

I've messed around with this a bit and, not liking syntaxtic additions
(for the most part), I've played around a little with this idea. The one
I've come up with that allows building a checkable graph is what I'm doing
already:

-pure([f/1, g/0, h/3]).

So that works just like an -export attribute and when the compiler rolls
over it you actually get a nice list in module_info:

1> zuuid:module_info(attributes).
[{vsn,[161185231735429547750212483364357911358]},
 {author,"Craig Everett <zxq9@REDACTED>"},
 {behavior,[application]},
 {pure,[{v3,1},
        {v3,2},
        {v3_hash,2},
        {v5,1},
        {v5,2},
        {v5_hash,2},
        {read_uuid,1},
        {read_uuid_string,1},
        {read_mac,1},
        {read_mac_string,1},
        {string,1},
        {string,2},
        {binary,1},
        {binary,2},
        {strhexs_to_uuid,1},
        {strhexs_to_mac,1},
        {strhexs_to_integers,1},
        {bins_to_strhexs,1},
        {binary_to_strhex,1}]}]

Quite easy to build a graph around this sort of data. And it comes only at
the cost of actually including a -pure declaration.

The problem, of course, is actually making a -pure declaration and keeping
it in sync with the module code over time -- and that this is invisible to
Dialyzer right now.

That said, if no unsafe calls or actions are taken in a function Dialyzer
could infer which functions are pure and help generate such a list. Even
better, of course would be if it knew the difference and examined each
function to build the graph of pureness automatically...

But I digress.

Save the (maybe not easy) task of making Dialyzer able to infer purity
(and this is impossible anyway when Dialyzer hits a wall of ambiguity
such as a call to M:F(A) or apply(M, F, A) -- which are pretty important!),
it would even nicer if we had a pure function spec declaration form.

-pure f() -> term().

And just leave the original

-spec f() -> {ok, Value :: term()} | {error, Reason :: term()}.

form alone.

That shouldn't break any old code, and leave a safe path to updating the
stdlib and internals of existing projects... without anything significant
changing until people are ready for it.

And no new syntax.

Where a new bit of syntax may be nice is if, for example, a way to declare
*what* side effects a function has or might have. I haven't any good idea
how to go about that because I've never thought of it or seen a system that
declares categories of side-effects... but its an interesting idea that
might help make "unit testing" of modules that have side effects actually
mean something (for once) and move it closer to the usefulness of actual
user testing (which is amazing at finding the boneheaded, easy to fix,
90% of bugs that are concrete and repeatable that unit tests are for some
reason consistently blind to).

-Craig



More information about the erlang-questions mailing list