2016-04-15 22 views
5

Diyaliz Cihazı Bu işlevinDialyzer neden bu basit hatayı yakalamıyor?

-spec myfun(integer()) -> zero | one. 
myfun(0) -> zero; 
myfun(1) -> one; 
myfun(2) -> other_number. 

dönüş türü tutarsızlık işaret etmez ama neden böyledir

myfun(_) -> other_number. 

olmanın son satırında durumunda algılar? Yukarıda çok basit bir durum olmalı, ben ...

Teşekkür

inanıyoruz

cevap

5

"Diyaliz Cihazı yapmaz neden ..." Olması için tasarlanmıştır çünkü" olan tipte sorulara kolay bir cevap Her zaman "ya da" yi düzeltin çünkü hiçbir şeyin ya da belirli bir şeyin yakalanacağına söz vermez.


Daha karmaşık bir yanıt için, sorunuzu daha da belirtmeniz gerekir.

-module(bar). 

-export([myfun1/1, myfun2/1]). 

-spec myfun1(integer()) -> zero | one. 

myfun1(0) -> zero; 
myfun1(1) -> one; 
myfun1(2) -> other_number. 

-spec myfun2(integer()) -> zero | one. 

myfun2(0) -> zero; 
myfun2(1) -> one; 
myfun2(_) -> other_number. 

Ve ister Dialyze: Ben bir modül içinde örnek yazarsanız ne bir "hata" dır çünkü

$ dialyzer bar.erl 
    Checking whether the PLT /home/stavros/.dialyzer_plt is up-to-date... yes 
    Proceeding with analysis... done in 0m0.64s 
done (passed successfully) 

... ne tutarsızlık, 'tespit' olduğu. Bu, kodun bazı yönlerden daha genel olması (ekstra değerler döndürmesi) ve bazı şekillerde daha kısıtlayıcı olması (sürüm 1 için her bir tamsayı ele alma) özelliğinden kaynaklanmaktadır.

ikinci sürümün sorun

-Woverspecs ile bulunabilir:

$ dialyzer -Woverspecs bar.erl 
    Checking whether the PLT /home/stavros/.dialyzer_plt is up-to-date... yes 
    Proceeding with analysis... 
bar.erl:11: Type specification bar:myfun2(integer()) -> 'zero' | 'one' is a subtype of the success typing: bar:myfun2(_) -> 'one' | 'other_number' | 'zero' 
done in 0m0.58s 
done (warnings were emitted) 

uyarı Spec kodundan daha kısıtlayıcı olduğunu tam olarak açıklar.

, her iki sorunun da -Wspecdiffs son derece olağandışı tarafından tespit edilebilir: operasyonun

$ dialyzer -Wspecdiffs bar.erl 
    Checking whether the PLT /home/stavros/.dialyzer_plt is up-to-date... yes 
    Proceeding with analysis... 
bar.erl:5: Type specification bar:myfun1(integer()) -> 'zero' | 'one' is not equal to the success typing: bar:myfun1(0 | 1 | 2) -> 'one' | 'other_number' | 'zero' 
bar.erl:11: Type specification bar:myfun2(integer()) -> 'zero' | 'one' is a subtype of the success typing: bar:myfun2(_) -> 'one' | 'other_number' | 'zero' 
done in 0m0.61s 
done (warnings were emitted) 

Ne -Woverspecs ne de -Wspecdiffs modunda bir şey belirtilen ediliyor" ve türleri genelleme olacaktır edebilirsiniz dialyzer tip analizi gibi, teşvik, bu yüzden edilir daha kısıtlayıcı bir yol "genelleme sonucu olabilir.

Ayrıca, bu işlevlerin yalnızca 0 ve 1 ile argümanlar olarak çağrılmasını istediğinizi de söz konusu olabilir; bu durumda, bu durumda, 'tamam' olur.

+0

"Dialyzer'ın tip analizi, türlerini genelleştirebilir ve genelleştirebilir ..." diye açıklayabilir misiniz? – mljrg

+0

Örnek 1: Her zaman "<= 0" olacak bir argümanı olan bir başka çağrınızı çağırdığınızı varsayalım. Dialyzer her zaman böyle bir aramanın sonucunun sadece “sıfır” olabileceğini düşünmez. Örnek 2: Tüm çift sayılar için çalışan bir işleviniz olduğunu varsayalım. Dialyzer, tüm tamsayılar için çalışacağını çıkaracaktır. Ve böylece ... – aronisstav

+0

Eğer, -Woverspecs 've' -Wspecdiffs 'seçenekleri potansiyel bir problemin varlığını (doğrudan ya da dolaylı olarak) tespit etmek için kullanılabiliyorsa, onların kullanımı neden cesaretlendirilmiyor? Bence bu seçenekleri kaldırırsınız, ya da insanlar bunları kullanmaya eğilimlidir ... – mljrg

İlgili konular