[erlang-questions] Dialyzer vs. Weird List Comprehensions
James Churchman
jameschurchman@REDACTED
Sat Mar 5 02:19:38 CET 2011
Is it not just the Dialyzer doing its job?
I have been hit once or twice by list comprehensions, as they don't behave like the rest of erlang with regards to let it crash, which is very useful in some cases ... a pain in others
eg i have a tuple, then loop over with a list comprehension :
{item,Elem1,Elem2}
Then in a different function / module i have a function that does say :
[ Elem1 || {item,Elem1,Elem2} <- List ]
later i modify the tuple ( / maybe other data structure) to
{item,Elem1,Elem2,Elem3}
and all is fine.. the code won't crash etc.. except it's totally broken. the match will never happen and i will always have an empty list
this is great for user supplied data but makes using tuples with LC's a real annoyance ( i realise i could use a record but lots of extra records just to pack up an extra value or two from a return seems unnecessary)
in my opinion maybe it should crash... or at least there should be a crashing and non crashing list comprehension
apart from the record syntax it's the one other big problem i feel erlang has
i would have :
InputList = [ {item1,item2} , {item1} ]
[ Item || { Item1 , Item2 } <- InputList ] %% would act like a list filter for anything but double tuple and will not crash (as it does at the moment)
[ Item ||| { Item1 , Item2 } <- InputList ] %% notice the triple ||| : will crash on any non-matching input
this would save quite a few "i gave my system some input and got an empty list out" type situations, as it would just crash
i don't know the in's and out's but i think the Dialyzer is working out that your passing something that always results in the list comprehension producing an empty list.. which is not the usual use of a list comprehensions so attempting to warn you as this is ( i guess) a common fault in erlang programming. Can't you just not call the function in this case?
ps does anybody think my suggestion is useful, and have they had the same experiences? i always hate the lists:map(fun) etc... it seems like unnecessary module redirection and is set to wreak havoc if i ever compile just that module with hype (well, i think it will :-) )
James
On 4 Mar 2011, at 23:23, Robert Virding wrote:
> One guess is that might depend on the fact that dialyzer works on Core erlang, an internal compiler format, and at that stage list/binary comprehensions have already been expanded into local recursive functions. These comprehension functions will contain a clause which against the head of a list. Dialyzer will then detect that the comprehension function is only called with a [] and then warn that the pattern in this clause can never match.
>
> But this is just a guess.
>
> Robert
>
> --
> Robert Virding, Erlang Solutions Ltd.
>
> ----- "Fernando Benavides" <fernando.benavides@REDACTED> 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 <- []].
>>
>> Now, you can compile and run it:
>>
>> 1> c(listcomp).
>> {ok,listcomp}
>> 2> listcomp:sample().
>> []
>>
>> 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)
>>
>>
>> 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.
>>
>> What do you think? Is it a bug? Should I modify my code not to use
>> list
>> comprehensions on that case?
>>
>> Cheers!!
>>
>>
>>
>> ________________________________________________________________________
>> Fernando
>> Benavides
>>
>>
>> fernando@REDACTED
>
> ________________________________________________________________
> erlang-questions (at) erlang.org mailing list.
> See http://www.erlang.org/faq.html
> To unsubscribe; mailto:erlang-questions-unsubscribe@REDACTED
>
More information about the erlang-questions
mailing list