2016-08-11 2 views
2

Возможно, это Xcode 8 бета проблема, однако, до версии 2.2 var ключевое слово разрешено предварять параметры сигнатуры функций:Как обозначить изменяемые параметры в замыканиях с Swift> 2.2?

func (var stringName: String) { ... } 

Это с тех пор является устаревшим, вместо там быть мало пользы над inout

func (stringName: inout String) { ... } 

Я попытался следующим в map закрытии, и хотя я не получаю предупреждение устаревания умеренно ожидаемое я должен, ошибка была скорее segmentation fault: 11

let demoString = ["hi", "there", "world"].map { (var word) -> String in 
    let firstChar = word.remove(at: word.startIndex) 
} 

Ошибка удаляется, как только я пытаюсь мутировать переменную (предположительно изменяемую) word.

Я попытался использовать другие варианты, например. используя inout

let demoString = ["hi", "there", "world"].map { (word: inout String) -> String in 
    let firstChar = word.remove(at: word.startIndex) 
} 

Но компилятор жалуется, что это ошибочно изменяет подпись закрытия вообще и не будет компилироваться.

Очевидно, что обходной путь просто скопировать переменную к локальной внутри крышки:

let demoString = ["hi", "there", "world"].map { (word) -> String in 
    let tempWord = word 
    let firstChar = tempWord.remove(at: tempWord.startIndex) 
} 

Однако, мне интересно знать, если ожидается, что это функциональность & ли или нет способ мутация параметра, переданного непосредственно в замыкание?

+0

ли ваш вопрос был дан ответ? – Alexander

ответ

3

Затворы могут видоизменяться inout аргументы просто отлично:

var str1 = "Pine" 
var str2 = "Juniper" 

let closure = { (s1: inout String, s2: inout String) -> Void in 
    s1 = "Oak" 
    s2 = "Chestnut" 
} 

closure(&str1, &str2) 

print(str1, str2) 

Проблема вы облицовкой Array.map не имеют подпись метода, которая включает параметр inout ,

Единственный способ обойти это, что я могу думать о том, чтобы расширить массив и добавить map метод себя:

extension Array { 
    func map<T>(_ closure: (inout T) -> Void) -> Array<T> { 
     var arr = [T]() 
     for i in 0..<self.count { 
      var temp : T = self[i] as! T 
      closure(&temp) 
      arr.append(temp) 
     } 
     return arr 
    } 
} 

var hi = "hi", there = "there", world = "world" 
var demoStrings = [hi, there, world] 
var result = demoStrings.map { (word: inout String) in 
    word.remove(at: word.startIndex) 
} 

print(result) // ["i", "here", "orld"] 
0

По SE-0003var параметров больше не существует в Swift 3.

Фундаментально, вы не должны быть мутируете параметры, данные из map, во всяком случае. Вместо этого: используйте не мутирующие функции или создайте локальную изменяемую копию.

В этом случае нет оснований для использования remove(_:), чтобы получить первый символ. Это потребовало бы копирования памяти String (опускание первого символа), только для того, чтобы получить символ, который был удален. Это довольно неуклюже.

В этом случае, вы можете просто получить переменную first экземпляра (из протокола Collection) на characters экземпляра имущества String.

Попробуйте это:

let demoStrings = ["hi", "there", "world"] 

let firstLetters = demoStrings.map {(word: String) -> String in 
    return word.characters.first 
} 

или сокращенно:

let firstLetters = demoStrings.map{ $0.characters.first } 
+0

Спасибо за комментарий. Я действительно не ищу способ переписать выражение. Это просто для демонстрационных целей. Я пытаюсь выяснить, могут ли параметры, передаваемые в замыкания, быть мутированными. FYI 'word.characters.first', если все, что вам нужно, это первая буква. –

+0

О, конечно, я понятия не имею, почему '.первый' не приходило в голову lol – Alexander

+0

У вас могут быть закрытие с параметрами' inout', но вы не можете использовать такое закрытие для 'map', из-за объявления закрытия карты (которая не использует 'inout') – Alexander

Смежные вопросы