2015-01-31 24 views
6

için in çevrimde her bir iterasyon:Sayaç normal için in-döngü, (bu durumda <code>number</code>) sayacı bir sabittir kullanırken

for number in 1...10 { 
    // do something 
} 

Bu, number değişiklik anlamına gelir döngüde:

for number in 1...10 { 
    if number == 5 { 
     ++number 
    } 
} 

// doesn't compile, since the prefix operator '++' can't be performed on the constant 'number' 

bir değişken olarak number bildirmek için bir yol döngü önce ilan veya (başlatma, durumu ve artışla birlikte) dongu normal kullanmadan, var mı?

+1

:

ne istediğini (C giriş for veya while başvurmadan) döngü, sizin daha iyi bahis belli yinelemeleri atlamak için ise

ilgili değerleri atlar bir jeneratör kullanmaktır 'for' için yineleyici genellikle kötü kod olarak kabul edilir. 'in' için hiçbir yineleyici yoktur,' sayı 'bir yineleyici değildir. Değeri, döngüyü herhangi bir şekilde etkilemez. – Sulthan

cevap

12

i neden değiştirilemediğini anlamak için for…in'un ne anlama geldiğini bilmek gerekir. for i in 0..<10 aşağıdaki derleyici tarafından genişletilir:

var g = (0..<10).generate() 
while let i = g.next() { 
    // use i 
} 

döngü etrafında her zaman, i taze bildirilen değişken, jeneratör üzerinde next aramasını sonraki sonucu unwrapping değeridir. while böyle yazılır edilebileceğini Şimdi

:

while var i = g.next() { 
    // here you _can_ increment i: 
    if i == 5 { ++i } 
} 

ama tabii, bu yardımcı olmaz - g.next() hala döngü etrafında 5 dahaki sefere oluşturmak için gidiyor. Vücuttaki artış anlamsızdı.

Bu nedenle, for…in, var sözdizimini, döngü günlüğü sayacısını bildirmek için desteklemiyor - nasıl çalıştığını anlamadıysanız çok kafa karıştırıcı olurdu.

(neler olup bittiğini görebileceğiniz where'dan farklı olarak var işlevselliği bazen func f(var i) modelinin nasıl olabileceğine benzer şekilde yararlıdır). Değiştirme

// iterate over every other integer 
for i in 0.stride(to: 10, by: 2) { print(i) } 

// skip a specific number 
for i in (0..<10).filter({ $0 != 5 }) { print(i) } 

let a = ["one","two","three","four"] 

// ok so this one’s a bit convoluted... 
let everyOther = a.enumerate().filter { $0.0 % 2 == 0 }.map { $0.1 }.lazy 

for s in everyOther { 
    print(s) 
} 
+0

Sadece harika cevaplar veriyorsunuz! –

+0

Swift 3, döngüler için var. Bununla birlikte, her dönüşte üzerine yazılır. – Etan

2

Cevap "hayır", ve bu iyi bir şey. Aksi takdirde, böyle bir fena halde kafa karıştırıcı davranış mümkün olacaktır:

for number in 1...10 { 
    if number == 5 { 
     // This does not work 
     number = 5000 
    } 
    println(number) 
} 

sözde 1 10 olsa dahil bir dizi bağlı bir döngü çıkışında sayısı 5000 gören bir karışıklık düşünün.

Ayrıca, Swift 5000'in bir sonraki değeri olarak ne seçerdi? Durur mu? Ödevden önceki aralıktaki bir sonraki sayıya devam edilsin mi? Aralık dışı atamaya bir istisna atmalı mı? Her üç seçeneğin de kendileri için bir geçerliliği vardır, dolayısıyla net bir kazanan yoktur.

Böyle durumlardan kaçınmak için Swift tasarımcıları, döngü döngülerinde döngü değişkenlerini değiştirdi.

+0

Bu 'in' için ortak bir 'for' döngüsünün tamamen farklı bir yapı olduğunu düşünmek gerçekten faydalı. 'sayı' bir yineleyici değil, her yinelemede çağrılan bir işlev/bloğun bir parametresidir. – Sulthan