I don't know of a way to achieve that with the built-in Array
type.
What you could do is to define a custom ConstantArray
type
which contains an array and has only immutable accessor methods
(which are all forwarded to the contained array):
struct ConstantArray<T> {
private let elements : [T]
// Create with an empty array.
init() {
elements = []
}
// Create with some sequence, e.g.
// let constArray = ConstantArray([1, 2, 3])
init<S : SequenceType where S.Generator.Element == T>(_ s: S) {
elements = Array(s)
}
// Read-only computed property to get the elements.
var array : [T] {
return elements
}
// Some properties you might want to implement:
var count: Int { return elements.count }
var isEmpty: Bool { return elements.isEmpty }
var first: T? { return elements.first }
var last: T? { return elements.last }
}
extension ConstantArray : ArrayLiteralConvertible {
// Create with an array literal, e.g.
// let constArray : ConstantArray = [1, 2, 3]
init(arrayLiteral array: T...) {
elements = array
}
}
// Implement sequence prototol, e.g. for enumeration:
// for elem in myConstantArray { ... }
extension ConstantArray : SequenceType {
func generate() -> IndexingGenerator<[T]> {
return elements.generate()
}
}
// Implement read-only subscripting, e.g.
// let elem = myConstantArray[1]
extension ConstantArray: CollectionType {
var startIndex : Int { return elements.startIndex }
var endIndex : Int { return elements.endIndex }
subscript(index: Int) -> T {
return elements[index]
}
}
extension ConstantArray : Printable {
var description: String { return elements.description }
}
Of course this is a different type, but by implementing the
SequenceType
and CollectionType
it can be used quite similarly.
Example:
var myArr : ConstantArray = [1, 2, 3]
myArr.append(42) // error: 'ConstantArray<Int>' does not have a member named 'append'
myArr[2] = 3 // error: cannot assign to the result of this expression
myArr.array[2] = 3 // error: cannot assign to the result of this expression
myArr = [4, 5, 6] // succeeds
println(myArr) // [4, 5, 6]
for elem in myArr {
println(elem)
}
For the mapping, you can use the global map()
function
(or the map()
method of Array
) and convert the result back to a ConstantArray
:
myArr = ConstantArray(map(myArr) { $0 * 2 })
myArr = ConstantArray(myArr.array.map { $0 * 2 })
Or you implement a map()
method for ConstantArray
:
extension ConstantArray {
func map<U>(transform: (T) -> U) -> ConstantArray<U> {
return ConstantArray<U>(elements.map(transform))
}
}
and use it as
myArr = myArr.map { 2 * $0 }
In the same manner, other methods like filter()
and sorted()
can be implemented for ConstantArray
.