I then add some functions that use ets matchspecs or a fun2ms transform and have to fill in fields with dummy values as required by the API (e.g. '_' and '$1'):
> find_by_colour(Colour) when is_atom(Colour) ->
> ets:lookup(myrecords, ets:fun2ms(fun (#myrecord{roses=C})
> when C =:= Colour ->
> object()
> end)).
Dialyzer complains that this function can't succeed:
> rec_example.erl:10: Function find_by_colour/1 has no local return
> rec_example.erl:11: Record construction #myrecord{field::'_',roses::'$1'} violates the declared type of field field::integer() and roses::'blue' | 'red'
To me this seems like reasonable code to want to write, but dialyzer hates it. The two (terrible) solutions I've found to avoid the dialyzer warnings are to add the dummy values to the record type spec:
Clearly none of these options are good - what's a better way to have record type specs and matchspecs and no dialyzer warnings? Or is there something I'm missing that replaces my use of matchspecs and avoids the problem?
On Tue, May 22, 2012 at 01:39:10PM -0700, Geoff Cant wrote:
> Hi all, I have hit this problem with my code and dialyzer a few times now and wonder what everyone else does to avoid it.
> I have record definitions with type specifications as follows:
> I then add some functions that use ets matchspecs or a fun2ms transform and have to fill in fields with dummy values as required by the API (e.g. '_' and '$1'):
> > find_by_colour(Colour) when is_atom(Colour) ->
> > ets:lookup(myrecords, ets:fun2ms(fun (#myrecord{roses=C})
> > when C =:= Colour ->
> > object()
> > end)).
> Dialyzer complains that this function can't succeed:
> > rec_example.erl:10: Function find_by_colour/1 has no local return
> > rec_example.erl:11: Record construction #myrecord{field::'_',roses::'$1'} violates the declared type of field field::integer() and roses::'blue' | 'red'
> To me this seems like reasonable code to want to write, but dialyzer hates it. The two (terrible) solutions I've found to avoid the dialyzer warnings are to add the dummy values to the record type spec:
> Clearly none of these options are good - what's a better way to have record type specs and matchspecs and no dialyzer warnings? Or is there something I'm missing that replaces my use of matchspecs and avoids the problem?
> I came across this same issue yesterday, anyone from the dialyzer team want
> to comment on a better way to deal with records in matchspecs?
Currently, there is really good way to deal with this problem....
(However note that the problem appears *only* if you type records.)
In my opinion, whoever added match specs in the language clearly was not thinking straight. They overloaded some random terms, namely the atoms '_', '$1', '$2', ... which, although admittedly quite uncommon, are perfectly valid Erlang atoms that applications can freely use if they want to to mean something completely different than they do in matchspecs. Sooner or later, this was bound to surface as a problem...
Nowhere else in the language is there specified that these atoms cannot be used by applications as regular atoms. Consequently, dialyzer does not (and will not!) treat them specially. In my opinion, there should be a DSL for matchspecs that does not clash with the rest of the Erlang language.
In the meantime, the best "solution" I see to this problem is to define the following type:
> On Tue, May 22, 2012 at 01:39:10PM -0700, Geoff Cant wrote:
>> Hi all, I have hit this problem with my code and dialyzer a few times now and wonder what everyone else does to avoid it.
>> I have record definitions with type specifications as follows:
>> I then add some functions that use ets matchspecs or a fun2ms transform and have to fill in fields with dummy values as required by the API (e.g. '_' and '$1'):
>>> find_by_colour(Colour) when is_atom(Colour) ->
>>> ets:lookup(myrecords, ets:fun2ms(fun (#myrecord{roses=C})
>>> when C =:= Colour ->
>>> object()
>>> end)).
>> Dialyzer complains that this function can't succeed:
>>> rec_example.erl:10: Function find_by_colour/1 has no local return
>>> rec_example.erl:11: Record construction #myrecord{field::'_',roses::'$1'} violates the declared type of field field::integer() and roses::'blue' | 'red'
>> To me this seems like reasonable code to want to write, but dialyzer hates it. The two (terrible) solutions I've found to avoid the dialyzer warnings are to add the dummy values to the record type spec:
>> Clearly none of these options are good - what's a better way to have record type specs and matchspecs and no dialyzer warnings? Or is there something I'm missing that replaces my use of matchspecs and avoids the problem?
> On 06/21/2012 07:27 PM, Anthony Molinaro wrote:
>> I came across this same issue yesterday, anyone from the dialyzer team
>> want
>> to comment on a better way to deal with records in matchspecs?
> Currently, there is really good way to deal with this problem....
I obviously meant "Currently, there is really NO good way to ..."
in the above.