2016-01-23 40 views
4

假設我在錫蘭有幾個嵌套for環路。如何打破了所有的循環:在錫蘭打破多個循環

variable Integer? something = null; 
for (i in 0:3) { 
    for (j in 0:3) { 
    for (k in 0:3) { 
     something = someFunction(i,j,k); 
     if (something exists) { 
     // break out of everything, we found it 
     } 
    } 
    } 
} 

回答

6

一種方式來做到這一點是包裝在一個封閉整個事情,然後使用回當你想擺脫一切稱之爲:

Integer? doLoops() { 
    for (i in 0:3) { 
    for (j in 0:3) { 
     for (k in 0:3) { 
     Integer? something = someFunction(i,j,k); 
     if (something exists) { 
      return something; 
     } 
     } 
    } 
    } 
    return null; 
} 
Integer? something = doLoops(); 

由於錫蘭支持關閉,您還可以在定義範圍doLoops的範圍內讀取和寫入函數外的其他值。

3

另一種方法是使用在for循環else塊:

shared void run() { 
    variable Integer? x = null; 
    for (i in 0:3) { 
     for (j in 0:3) { 
      for (k in 0:3) { 
       value n = i*j*k; 
       if (n > 18) { 
        x = n; 
        break; 
       } else { 
        continue; 
       } 
      } else { 
       continue; 
      } 
      break; 
     } else { 
      continue; 
     } 
     break; 
    } else { 
     x = null; 
    } 
    print(x); 
} 

一般來說,放置

else { 
    continue; 
} 
break; 

for收盤括號後面。

(注:理想情況下,變量被分配 - x在我的例子,something在你的 - 不需要是variable,因爲它正好分配有一次不過,目前can’t prove that的typechecker。)

如何它工作嗎?如果該循環運行到完成而沒有任何break,則在執行for循環後執行else。在這種情況下,我們也想要continue外層循環;否則 - 也就是說,如果我們從內部循環中解脫出來 - 我們也想從外部循環中獲得break

這可以在ceylon/ceylon#3223提出以下語法寫得更簡潔:

for (a in b) { 
    for (x in y) { 
     if (something) { 
      break; 
     } 
    } then { // opposite of else: runs iff there was a break in the inner loop 
     break; 
    } 
} 

我不會推薦這種解決方案,原因有三:

  • 它甚至更少可讀比你的封閉解決方案。 for {} else {}功能相當模糊,如果您不熟悉這一功能,其意義就不明顯了,這使得臨時讀者無法理解代碼。
  • 它在每個周圍的循環中膨脹了很多代碼(不僅僅是一次),也使其不可讀。
  • 如果你想在內部循環之後的外部循環中有代碼,你必須複製它:else塊和它後面的代碼都需要一個副本。
5

您可以使用理解和流處理語法來代替:

Iterable<Integer?> stream = { 
    for (i in 0:3) for (j in 0:3) for (k in 0:3) someFunction(i,j,k) 
}; 

Integer? = stream.coalesced.first; 

這將如預期,因爲{ for ... }理解創建一個Iterable是懶洋洋地評估。

iterable的coalesced屬性返回另一個惰性迭代,它跳過原始中的所有null值。

然後只要求剩下的可迭代的第一個值,那就是你的答案。