Swift 2 Интроспекция

Преобразувам някакъв „стар“ Swift код в Swift 2.0 и попадам на грешка, от която не мога да се отърва.
Моята функция получава масив от тип (какъвто и да е) и връща нов масив от същия тип.

Този код вече не работи в Swift 2.0:

func makePattern1<T>(var list: Array<T>) -> Array<T> {
    let theType = list.dynamicType
    var result = theType()
    for i in 1..<list.count {
        result.append(list[i])
        result.append(list[i-1])
    }
    return result
}

дава съобщение за грешка: „Инициализирането от стойност на метатип трябва изрично да препраща към „init“.

Коригирането на кода с: var result = theType.init() дава грешка „Типът на израза е двусмислен без повече контекст“.

Какво ми липсва?


person popisar    schedule 08.12.2015    source източник
comment
Има ли причина да правите това? Изглежда, че това, което искате, може да бъде постигнато много по-лесно с map.   -  person Code Different    schedule 08.12.2015
comment
Също така, какво ви спира да кажете просто var result = Array<T>()?   -  person 0x416e746f6e    schedule 08.12.2015
comment
var result = Array<T>() работи добре, благодаря.   -  person popisar    schedule 08.12.2015
comment
Можете ли да дадете пример с map?   -  person popisar    schedule 08.12.2015


Отговори (2)


Този код е написан на Swift 2.1 и използва функцията map, както поискахте в коментарите.

func makePattern1<T>(list: [T]) -> [T] {
    return list[0..<list.count-1]
        .enumerate()
        .map { [list[$0.index+1], list[$0.index]] }
        .flatten()
        .map { $0 as T }
}

Актуализация #1

(благодаря на Мартин Р)

func makePattern1<T>(list: [T]) -> [T] {
    return list[0..<list.count-1]
        .enumerate()
        .flatMap { [list[$0.index+1], list[$0.index]] }
}

Актуализация #2

func makePattern1<T>(list: [T]) -> [T] {
    return [Int](1..<list.count).flatMap { [list[$0], list[$0-1]] }
}

Тест

makePattern1([1,2,3,4,5]) // > [2, 1, 3, 2, 4, 3, 5, 4]
person Luca Angeletti    schedule 08.12.2015
comment
.map + flatten могат да бъдат комбинирани до flatMap и след това можете също да премахнете окончателното изкуствено .map { $0 as T } - person Martin R; 08.12.2015

Просто за забавление: Алтернативно решение:

func makePattern2<T>(list: [T]) -> [T] {
     return zip(list.dropFirst(), list).flatMap { [$0, $1] }
}

let m = makePattern2([1,2,3,4,5])
print(m) // [2, 1, 3, 2, 4, 3, 5, 4]

Забележки:

  • list.dropFirst() е последователност от всички елементи на масива освен първия.
  • Тогава zip(list.dropFirst(), list) е поредица от (list[$0.i+1], list[$0.i]) кортежи.
  • flatMap { [$0, $1] } отново комбинира тези кортежи в единичен масив.
person Martin R    schedule 08.12.2015
comment
Много добре. Затварянето на това flatMap използва само параметрите на самото затваряне. Това е чисто функционално решение. - person Luca Angeletti; 08.12.2015