2014-06-05 11 views
5

Rozważmy następujący zestaw funkcji:Pomijanie niejawne powraca w Swift

func testFunc(someFunc: (Int[]) ->()) { 
    someFunc([1, 2, 3]) 
} 

func someFunc<T>(arr : T[]) -> T[] { 
    return arr 
} 

func someOtherFunc<T>(arr : T[]) { 
    println(arr) 
} 

// case 1 - ERROR 
testFunc() { 
    someFunc($0) 
} 

// case 2 - no error 
testFunc() { 
    println("whatever") 
    someFunc($0) 
} 

// case 3 - no error 
testFunc() { 
    someOtherFunc($0) 
} 

Wygląda jak w przypadku 1, Swift stara się niejawnie powrócić z zamknięciem od funkcji someFunc() zwraca wartość. Robi to tylko wtedy, gdy w zamknięciu znajduje się tylko jedna linia (Implicit Returns from Single-Expression Closures) - dlatego przypadek 2 działa. Nie robi tego, jeśli funkcja, jak w przypadku 3, jest Void, tj. Nie zwraca wartości.

Moje pytanie brzmi, czy istnieje sposób, aby powstrzymać to zachowanie, tak, że mogę mieć funkcję z wartością zwracaną jako jedno-wierszowe wyrażenie w zamknięciu, które nie ma wartości zwracanej.

+1

"someFunc ($ 0); return"? Co jest nie tak z dwiema liniami – sanz

+5

To wygląda jak błąd. (@tony nie ma powodu, dla którego powinieneś/powinnaś dodawać dodatkowe linie dla tego przypadku.) Wnioskowanie o typ powinno wychwycić fakt, że 'testFunc' przyjmuje zamknięcie, które niczego nie zwraca' ->() 'i powinno odpowiednio tłumić automatyczny powrót zamknięcie pojedynczej ekspresji. Zgłoś go do https://bugreport.apple.com/ –

+0

Błąd ma więcej sensu ... Myślałem, że zwariowałem. Raport o błędzie przesłany, dzięki! –

Odpowiedz

1

UPDATE: Po Swift 1.2, nie jest to już problem

Ten błąd nadal istnieje w Xcode beta6, mam nadzieję, że będzie naprawione w wersji 1.0, przed tym, że jest to obejście

testFunc() { 
    someFunc($0) 

    // The explicit return statement corrects the wrong return type of the auto implicit return. 
    // It makes more sense than printing nonsense strings 
    return //TODO: remove after the bug is fixed 
} 
+0

Dlaczego uważasz, że to "błąd"? Robi dokładnie to, co mówi specyfikacja. – newacct

+0

@newacct przeczytaj komentarz NicholasH pod pytaniem, zgadzam się z nim. –

+0

@newacct Jeszcze jedno źródło, na GitHub jest podobny problem spowodowany niejawnymi zwrotami, ktoś powiedział, że faceci Apple potwierdzili, że to błąd kompilatora https://github.com/robb/Cartography/issues/9 –

6

Oprócz wymienionych rozwiązań:

testFunc { someFunc($0); return() } // returning Void explicitly (with or without parenthesis) 

testFunc { someFunc($0); 42 } // or, indeed, just adding a second expression 

można również spożywać wartość zwracana:

testFunc { let x = someFunc($0) } 

lub po prostu:

testFunc { _ = someFunc($0) } 

Wartość zwracana zawsze musi być typu obiecanej podpisem funkcji, a sprawa niejawna zamian nie jest inaczej. To nie jest błąd. Po prostu niejawne powroty są tak często tak elegancką składnią, że mniej częsty przypadek niedopasowanych typów trochę przełamuje zaklęcie. Nie oznacza to, że ładne syntaktyczne rozwiązanie nie byłoby mile widziane, przynajmniej gdy oczekiwane jest Void. Być może coś tak prostego jak:

testFunc { someFunc($0) ; } // with the trailing semicolon 

Kiedy to irytuje mnie najbardziej to, kiedy moja własna funkcja zmusza mnie do tańca wokół niego. Kilka razy uciekam się do wyraźnego ignorowania typu zwrotu:

func testFunc<Ignored>(someFunc: [Int] -> Ignored) { 
    someFunc([1, 2, 3]) 
} 

testFunc { someFunc($0) }