[erlang-questions] Dialyzer vs. Weird List Comprehensions
Kostis Sagonas
kostis@REDACTED
Sat Mar 5 20:12:35 CET 2011
Fernando Benavides wrote:
> Hi, I think this question is mostly for the man of the moment, Kostis
> Sagonas ;). But, if everybody else had run into this kind of things
> before, your help is appreciated.
> I have a quite complex module and at one point there is a function that
> uses list comprehensions over one of its parameters. That parameter, may
> eventually be an empty list (a hardcoded empty list - i.e. when know
> that in that particular case it'll be an empty list at compile time).
> So, when I try to run dialyzer on my module, it prints a warning about
> that when in my opinion, it shouldn't.
> To make things easier to understand, I've isolated the problem in this
> rather useless module:
>
> -module(listcomp).
> -export([sample/0]).
> -spec sample() -> [].
> sample() -> [L || L <- []].
>
> It works fine, but if you try to dialyze it...
>
> $ dialyzer ebin/listcomp.beam
> [...]
> listcomp.erl:4: The pattern [L | _] can never match the type []
> done in 0m0.31s
> done (warnings were emitted)
Robert Virding has correctly replied that this warning exists because
dialyzer works at the Core Erlang level where binary comprehensions have
already been expanded to recursive functions by the Core Erlang
translation which has one clause for when the list generator is empty
and one for the cons case.
But I want to point out something more else in your mail:
> First thought is "why are you doing a list comprehension on an empty
> list anyway?". But, for instance, the actual line in my module is
> something like this:
>
> all_friends(Buddies) -> [db:get_buddy(FN) || #buddy{friend_names
> = FNs} <- Buddies, FN <- FNs].
>
> And it's called from a lot of places... one of those looks like this...
>
> all_friends([#buddy{name = "Jim (from 28 days later...)", ...},
> #buddy{name = "Chuck Norris", ...}])
>
> ...and you know... neither of those folks have any friends, so dialyzer
> complains.
But what you described is not precise. It's not only in _one_ of these
places that this happens, it's in *all* of them (within this module).
I am sure of this, or there is some other problem in your code. Chuck
Norris is even more sure of this. (*) Disprove him if you dare by
sending the file that generates this warning!
Cheers,
Kostis
(*) Fact: Chuck Norris can find and understand all bugs in an Erlang
program without seeing the code.
(for more facts see http://www.chucknorrisfacts.com/)
More information about the erlang-questions
mailing list