2015-05-04 7 views
0

Я хочу, чтобы обеспечить соблюдение (во время компиляции) массив из 5 элементов определенного типаSwift - создать массив фиксированной длиной вынужденный во время компиляции

я не смог найти решение, чтобы прибегли к обходному пути, создавая кортеж

(Это оскорбительно я знаю)

typealias FiveElementArray = (MyType,MyType,MyType,MyType,MyType) // mock array by using typed tuple 

Он работает для моих потребностей - пока мне не нужно для доступа к элементу по индексу во время выполнения.

Например:

var DB = FiveElementArray // the tuple of 5 elements 

tableView(tableView : UITableView,cellForRowAtIndexPath:indexPath) -> UITableViewCell { 
// would like to populate with the value at index 
DB[indexpath.row] // no such syntax for tuples 

} 

Так как я могу использовать правильный быстрый массив со статически типизированных длиной

+0

Вы пытались назначить массив через 'let' вместо этого? – luk2302

+0

Если вы создаете массив, набор или словарь и назначаете его переменной, создаваемая коллекция будет изменяться. Это означает, что вы можете изменять (или мутировать) коллекцию после ее создания путем добавления, удаления или изменения элементов в коллекции.И наоборот, если вы назначаете массив, набор или словарь константе, эта коллекция неизменна, а ее размер и содержимое не могут быть изменены. Из https://developer.apple.com/library/ios/documentation/Swift/Conceptual/Swift_Programming_Language/CollectionTypes.html – luk2302

+0

@ luk2302 Он не отвечает на вопрос (это не относится). – Moritz

ответ

7

Способ предотвращения нежелательных изменений на тип значения (например, массив), чтобы положить didSet наблюдатель от него, чтобы действовать в качестве охранника:

var arr = [1, 2, 3, 4, 5] { 
    didSet { 
     if arr.count > 5 {arr = oldValue} 
    } 
} 
arr.append(6) 
println(arr) // [1, 2, 3, 4, 5], that change was illegal 
arr[2] = 100 
println(arr) // [1, 2, 100, 4, 5], that change was legal 

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

struct FiveElementArray<T> { 
    private var arr = Array<T>() 
    // methods for access go here 
} 

«Методы доступа» могут включать в себя реализации всех способов модификации этого массива, который вы разрешаете (например, subscriptip) и может просто не реализовывать все способы, которые вы не разрешаете (например, добавлять и продлевать).

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

+0

Мысль об этом, но я хочу быть в состоянии гарантировать, что метод, возвращающий массив, всегда будет содержать 5 элементов. Например, func doSomething() -> FiveElementArray –

+0

Ну, тогда вам нужно будет определить свой собственный тип коллекции (что почти то, что вы сейчас делаете), или обернуть свою коллекцию в структуру, которая действует как охранник. – matt

+0

Но я бы потерял статическую проверку времени компиляции. –

0

Возможно, вы ищете Dependent Types: он позволяет вам закодировать некоторое значение (длину массива) в самом типе. К счастью, в Swift можно использовать зависимые типы to some extent.

@oisdk также написал a blog post, где он создает эффективную структуру типизированной коллекции, вы также можете прочитать статью во время взаимодействия с кодом в the Playground version.

Пример использования:

func onlySameLength<A, B, L : Nat>(lhs: ConstArray<A, L>, rhs: ConstArray<B, L>) {} 

let twoLong = emptyArray() +| 1 +| 2   // [1, 2] 

let twoChar = emptyArray() +| "a" +| "b"  // ["a", "b"] 

onlySameLength(twoLong, rhs: twoChar) 

let threeInts = emptyArray() +| 1 +| 2 +| 3 // [1, 2, 3] 

//Uncomment for an error 
//onlySameLength(twoLong, rhs: threeInts) 

Я настоятельно предлагают использовать определение типа Свифта для этого в качестве типа ConstArray с элементами String и считать 3 бы ConstArray<String, Succ<SuccSucc<<Zero>>>>

Ладно, что-то вроде [1, 2].lazy.filter {$0 == 1 }.flatMap{ [$0] } имеет тип LazyCollection<FlattenCollection<LazyMapCollection<LazyFilterCollection<Array<Int>>, [Int]>>>, так что я думаю ConstArray не так уж плохо: P

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

  • Нет связанных вопросов^_^