2012-08-30 21 views
5

"learn you some erlang" adlı çevrimiçi kitapla ilgileniyorum ve anlayışımı kontrol etmek için bazı alıştırmalar yapmaya çalışıyorum. Dialyzer, bu eğlenceli sözleşmenin üst üste binen alanlara sahip olduğunu neden söylüyor?

I (tüm unsurları aynı tip T olması gereken bir fifo)

bir "typed_fifo (T)" tanımlamaya çalışırken, bölüm Tip Özellikleri ve Erlang yılında, FIFO örnek de değişiklik yapılmış

tipim şartname şunlardır:

-spec empty (typed_empty_fifo()) -> true;

(typed_nonempty_fifo(_)) -> false. 

empty({fifo, [], []}) -> true;

empty({fifo, A, B}) when is_list(A), is_list(B) -> false.

dialyze:

-type typed_empty_fifo() :: {fifo, [], []}.

-type typed_nonempty_fifo(A) :: {fifo, nonempty_list(A), list(A)} | {fifo, [],nonempty_list(A) }.

-type typed_fifo(A) :: typed_empty_fifo() | typed_nonempty_fifo(A).

ve aşağıdaki fonksiyon spec kullanıldığında bir r, örtüşen alan nedeniyle belirtimi göz ardı edeceğini söyler.

Birisi bana hata yaptığımı söyleyebilir mi?

Yazılmış bir fifo tanımlamaya çalışmadan önce başka bir noktaya sahibim Güzel bir şekilde çalışan bir versiyonum vardı, Bir Dialyzer bana uygun olmayan listelerin kullanımını engelleyecek hiçbir şey olmadığını gösteriyor. Sürpriz bir şekilde, bir listenin doğru/yanlış karakterini test etmek için basit bir yol (bir gardiyanda kullanabileceğim) bulamıyorum.

Bu gerçekten garip, çünkü bif uzunluk/1 kullandığımda, badarg nedeni ile başarısız olabilir!

23> L=[1,2|3]. ==> [1,2|3]

24> is_list(L). ==> true

25> length(L). ==> exception error: bad argument

in function length/1 

    called as length([1,2|3]) 

Teşekkür

cevap

3

Tür ve özelliklerinizle ilgili hiçbir sorun yoktur. Sorun, Dialyzer'de türlerin gösterimi için kullanılan veri türünün, sağladığınız kadar hassas kalmamasıdır. Özellikle, {fifo, nonempty_list(A), list(A)} | {fifo, [],nonempty_list(A) } birliği, {fifo, list(A), list(A)} no'lu "ezilmiş" dir, çünkü bunlar aynı aritliğe (3) ve ilk atom elemanına (fifo) sahiptir. Dialyzer genellikle, tip analizini daha verimli hale getirmek için aşırı tahminleri yapar (here'u da görebilirsiniz). Bu uyarıyı güvenli bir şekilde ihmal edebilirsiniz.

İkinci soru için, is_list/1 yalnızca, bağımsız değişken olarak geçirilen terimin ilk yapıcısının bir cons hücresi olup olmadığını kontrol eder. is_list([1|2]) bile true değerini döndürür.

Eğer bir argüman böyle bir case ifadede özel bir işlev kullanabilirsiniz uygun bir liste olmasını sağlamak isterseniz:

case is_proper_list(L) of 
    true -> ...; 
    false -> ... 
end 

is_proper_list([]) -> true; 
is_proper_list([_|L]) -> is_proper_list(L); 
is_proper_list(_) -> false. 

Ancak bu bir bekçi yerleştirilir edilemez. Muhafızlarda, aşağıdaki yorumunuzda önerdiğinizi kullanabilirsiniz (length(L) >= 0).

+0

Teşekkür ederim Aronis. Bence Dialyzer'in vermeyi amaçladığı şeyden daha fazlasını istiyorum. Bu spesifikasyonları kullanmanın yararının ne olabileceğini, diyalizcinin ne yapabildiğini ve benim için gayretin ne olduğunu anlamaya çalışıyorum. En azından bu sorunu uygunsuz bir liste ile keşfettim. Bu arada, hala ikinci soruma bir çözüm arıyorum. Ben eğlenceli bir test gibi beklemek var: is_list (X) andalso uzunluğu (X)> -1 çalışır. Ama bir işlevin içine çöker. – Pascal

+0

Cevabı olası bir çözümle düzenledim. Oh ve benim ilk adım Stavros! :-) – aronisstav

0

ikinci soruya gelince, list çalışmak doğru yolu:

1> L = [1,2|[3]]. 
[1,2,3] 
2> is_list(L). 
true 
3> length(L). 
3 

Not sen Taillist (değil int) olduğu hesaplandı [Head|Tail] notasyonu gerektirdiğini .

+0

Cevabınız için teşekkür ederiz. Bunu biliyordum, ama sonunu çok hızlı yazdım. Uygunsuz bir liste oluşturmak için bu görevi amaca yönelik yaptım.Gerçek şu ki, fifo modülüm sadece geçerli bir fifo oluşturacak, ancak hiçbir şey başka bir modülün uygunsuz bir liste üzerine inşa edilmiş bir fifo oluşturmasını engelleyecek hiçbir şey olmadığını ve bunu kontrol etmek istediğimi (tabii ki, tabii ki, gerçek hayatta sdlib one ...) – Pascal

İlgili konular