2010-09-17 19 views
18

Ben bir ağ çağrı başarısız olursa yeniden deneme kolaylaştırmak için kullanılan bir özyinelemeli fonksiyon çağrısı var, aşağıda yer snippet'ine (Amazon SimpleDB bazen 503 dönmek ve yeniden deneme gerektirecektir.)Scala neden özyinelemeli işlevler için bir dönüş türü gerektiriyor? kodunda

Ben derlemeye çalıştığınızda Scala recursive method simpledb_update needs result type'dan şikayet ediyor.

// sends data to SimpleDB. Retries if necessary 
def simpledb_update(name: String, metadata: Map[String,String], attempt: Int) = { 
try { 
    db(config("simpledb_db")) += (name, metadata) 
} catch { 
    case e => 
    // if it fails, try again up to 5 times 
    if(attempt < 6) 
    { 
    Thread.sleep(500) 
    simpledb_update(name, metadata, attempt + 1) 
    } else 
    AUlog(name + ": SimpleDB Failed") 
    } 
} 

Bu neden yineleme işlevleri için gereklidir? Benim düşüncem, derleyiciyi tatmin etmek için doğru/yanlış bir boole döndürmek ... aşağıdakileri derler.

// sends data to SimpleDB. Retries if necessary 
def simpledb_update(name: String, metadata: Map[String,String], attempt: Int): Boolean = { 
try { 
    db(config("simpledb_db")) += (name, metadata) 
    true 
} catch { 
    case e => 
    // if it fails, try again up to 5 times 
    if(attempt < 6) 
    { 
    Thread.sleep(500) 
    simpledb_update(name, metadata, attempt + 1) 
    } else 
    AUlog(name + ": SimpleDB Failed") 
    false 
    } 
} 
+1

Benzer: http://stackoverflow.com/questions/2209179/type-inference-on-method-return-type – missingfaktor

+4

Psst, eğer 2.8 kullanıyorsanız, 'try: Int = 0' kullanın, böylece orijinal çağrınız yapmaz ' t sıfır girişimi olduğunu belirtmem gerekiyor! Ayrıca, derinlemesine tekrarlayan bir şey yaparsanız, yığının taşmasına neden olabilirsiniz (6, elbette iyidir). Scala'nın yığını kullanmamasını kontrol edip edemediğini kontrol etmek için, 'def' yerine '@ annotation.tailrec 'ile not ekleyin. Kuyruk özyinelemeli değilse, yığın kullanılmalı ve Scala bir hata atar - en azından ek açıklamaları kaldırdığınızda ne ile uğraştığınızı bilirsiniz. –

+0

Ruby'den geliyor, bu benim ilk eğilimimdi. Ne yazık ki, 2.7'de ... desteksizim! Yükseltme zamanı, sanırım. – Joshua

cevap

16

Anladığım kadarıyla, özyinelemeli işlevler bir tür döndürme türüne ihtiyaç duyar, çünkü tür çıkarım algoritması tüm özyinelemeli işlevler için geri dönüş türlerini belirlemek için yeterince güçlü değildir. Ancak, bir dönüş türü oluşturmanıza gerek yok, yalnızca kullandığınız iade türünü bildirmeniz yeterlidir: Birim. Ünite sadece bir element() ile özel bir türüdür. Ayrıca, Scala'daki çoğu "deyim" türü ve herhangi bir şey döndürmeye gerek olmayan, ancak yalnızca kendi yan etkileri (sizinki gibi) için çalıştırılan yöntemler için beyan edilen dönüş türüdür. Sen birimi dönen gibi yöntemini ilan edebilir ya yapacağınız diğer tür

def simpledb_update(name: String, metadata: Map[String,String], attempt: Int):Unit = { 
Daha deyimsel Scala sadece dönüş türü atlanıp Eşittir işareti, Birim-dönen yöntemleri için özel bir sözdizimi sağlar

def simpledb_update(name: String, metadata: Map[String,String], attempt: Int){ 

scala tarzı kılavuzuna göre eşittir işaretini kullanmayı tercih etmelidir

http://docs.scala-lang.org/style/declarations.html

+1

neden çıkarım algoritması tüm özyinelemeli işlevler için dönüş türlerini belirlemek için yeterince güçlü değil? – CuiPengFei

+0

Tam anlamıyla "Sabırsızlık için Scala" alıntı: Bazı programlama dilleri (ML ve Haskell gibi), Hindley-Milner algoritmasını kullanarak özyinelemeli bir işlev türetebilir. Ancak, bu nesne yönelimli bir dilde iyi çalışmıyor. Hindley-Milner algoritmasını genişleterek alt türlerini ele alabilmek için hala bir araştırma problemidir. – amorales

+0

http://people.inf.ethz.ch/trayteld/papers/aplas11-coercions/coercions_short.pdf – amorales

10

Sadece = satırdan kaldırın ve Birim dönecektir, bu, herhangi bir şey döndürmeniz gerekmediği anlamına gelir.

def simpledb_update(name: String, metadata: Map[String,String], attempt: Int) { 

Ben tüm tekrarlama yolları doğru tip olduğundan emin olmak için, dönüş türleri ihtiyacını inanıyoruz. Normal bir işlevde, tür tüm dönüş noktalarından çıkar.

+0

Ahhh ... mükemmel bir anlam ifade ediyor. – Joshua

+2

Geri dönüş noktalarından en az biri, yalnızca sonuç çıkarmaya çalıştığınız türe sahip olduğundan, yalnızca tür dönüş noktalarından çıkamazsınız. –

+3

@Jorg - Aslında, çıkması zor değil (ama isteyebileceğinden daha zor). Yinelemeli dönüş değeri olmayan her yol dönüş değeri türünü alırsanız, bu dönüş değeri türü olmalıdır. Ancak, karşılıklı olarak tekrarlanan fonksiyonlara itildiğinde bu karmaşıklaşır. –

İlgili konular