var bigNum = [2,34,5].remove(at: 2)
Error:
Playground execution failed: error: CalculatorPlayGround.playground:35:14: error: cannot use mutating member on immutable value of type '[Int]'
var bigNum = [2,34,5].remove(at: 2)
But
var bigNum = [2,34,5]
var b = bigNum.remove(at: 2)
is ok.
What is the difference? Why does it work in the second case?
.remove(at:) tries to mutate the array you call it on.
When you create the array like you did in your first example ([1,2,3].whatever), it creates an immutable constant, as if you were to create it like this:
let array = [2, 34, 5] //not mutable
If you force it to create the array as a variable, it is mutable:
var array = [2, 34, 5] //mutable
Note
I don't know exactly what you are trying to do, but bigNum makes me assume you're trying to get a number from the array? Because right now, bigNum would become this array: [2, 34] instead of just a number.
[2,34,5] in itself is a literal, and as such is immutable in Swift (i.e. you can't write [2,34,5].remove(at: 2)). To apply a mutating function, you first need to store your array in a mutable container, using the var keyword:
var bigNum = [2,34,5]
Only after doing so, you can use mutating func .remove(at:) on mutable bigNum.
Related
We all know that [UInt8] type is not equal UnsafePointer<UInt8>,
But why can I pass [UInt8] type to UnsafePointer<UInt8> type parameter:
let p = UnsafeMutablePointer<UInt8>.allocate(capacity: 4)
p.initialize(repeating: 0, count: 4)
let ary:[UInt8] = [1,2,3,4]
p.assign(from: ary, count: 4) // It's OK, why?
As shown above,p.assign method frist parameter type is UnsafePointer<T>, but It's OK when I pass the type [UInt8]...
Why is that? Thanks! ;)
It's just a shortcut.
An unsafe pointer is effectively a C array: what we are pointing at is the first address of a contiguous block of memory. Therefore Swift gives you some nice help for when you have a Swift array from which you want to write to the memory: this Swift array is nothing whatever like a C array, but nevertheless, you can pass a pointer to the Swift array or even the Swift array itself, including an array literal, and Swift will just do the right thing.
Document said:
An in-out expression that contains a mutable variable, property, or subscript reference of type Type, which is passed as a pointer to the address of the left-hand side identifier.
A [Type] value, which is passed as a pointer to the start of the array.
But when I run the following code :
func print<Type>(unsafePointer pointer: UnsafePointer<Type>) {
print("\(pointer) ==> \(pointer.pointee) : \(Type.self)")
}
var array = [1, 2, 3, 4]
print(unsafePointer: array)
print(unsafePointer: &array[0])
I get
0x0000000104204240 ==> 1 : Int
0x00007ffeefbff440 ==> 1 : Int
Why their addresses are different?
Here
print(unsafePointer: array)
a pointer to the first element of the array storage is passed to the function. And here
print(unsafePointer: &array[0])
the subscript operator is called on the array (returning an Int) and the address of that (temporary) integer is passed to the function, not the address where the original array element is stored.
That becomes more obvious if you call the functions twice:
var array = [1, 2, 3, 4]
print(unsafePointer: array) // 0x00007ffeefbff2e0
print(unsafePointer: array) // 0x00007ffeefbff2e0, same as previous address
print(unsafePointer: &array[0]) // 0x00007ffeefbff320
print(unsafePointer: &array[0]) // 0x00007ffeefbff340, different from previous address
In addition, passing an in-out expression to a function can make a temporary copy, see for example Swift: always copies on inout?.
Arrays in Swift have value semantics, not the reference semantics of arrays in C or Objective-C. The reason you're seeing different addresses (and addresses at all) is that every time you pass the array as a parameter, you're actually telling Swift to bridge your Array struct to an instance of NSArray.
What I discovered
This question is about something I noticed a bit strange in the Swift language. I came across this behaviour, as it was a bug in my code.
If I created an array for a grid as an implicitly unwrapped optional, then map behaves strangely. Have a look at this code:
let grid: [[Int]]! = [ // May be defined like this if set later on
[1, 2, 3],
[4, 5, 6],
[7, 8, 9]
]
print(grid.map { $0[0] }!)
// Prints "[1, 2, 3]" (not what I wanted)
print(grid!.map { $0[0] })
// Prints "[1, 4, 7]" (what I wanted)
I know the row can be obtained simply by doing grid[0]. However, I am trying to get a column.
I tried the first method above, which only gives the row instead of the column. The second method worked and gave the column.
What is the cause?
I defined grid as [[Int]]!, which is an implicitly unwrapped optional.
Why do I need to force unwrap grid to use map properly?
Why does the first method act the same as returning a row using grid[0]?
There are two versions of map: one that operates on the array and one that operates on optionals.
Your grid is an optional, and even though it is an implicitly unwrapped optional (IUO) it is still an optional. Swift will treat an IUO as an optional whenever possible and only force unwraps the value when the unwrapped type is needed.
Because of this, the optional version of map is used instead of the one you expect. By explicitly unwrapping grid with !, you then allow the desired version of map to be used.
How does map work on an optional?
When map is applied to an optional, it applies the closure to the unwrapped value. If the optional is nil, nothing happens.
So, grid is unwrapped and becomes $0, and the closure returns $0[0] which is the first row of the grid.
Note: In Xcode, if you option-click on map in each statement you will see that the first says:
Evaluates the given closure when this Optional instance is not nil,
passing the unwrapped value as a parameter.
and the second one:
Returns an array containing the results of mapping the given closure
over the sequence’s elements.
I need to mutate nested dictionaries of unknown depth.
I realize that structs in swift are value types when in fact i would need a reference type ("NSMutable")
But I've noticed that if I access nested structs using dot(.) syntax I am able to update a value directly, without the need to reassign to the original "parent".
For instance In a case of nested arrays:
var l1 = ["a0","b0"]
var l2 = ["a1","b1"]
var list = [l1,l2]
print(list)
>>[["a0", "b0"], ["a1", "b1"]]
// I can mutate the nested structs by using dot(.) syntax
// mutate the zero indexed nested array:
list[0].insert("x0", atIndex: 0)
print(list)
>> [["x0", "a0", "b0"], ["a1", "b1"]]
// try to mutate after assignment - Not able to
var l1Ref = list[0]
print(l1Ref)
>> ["x0", "a0", "b0"]
l1Ref.removeFirst()
print(l1Ref)
>> ["a0", "b0"]
print(list)
// still the same as was before
>> [["x0", "a0", "b0"], ["a1", "b1"]]
How can I mutate the nested struct iteratively without using dot syntax?
Arrays are structures in Swift and when you assignment a subarray to a variable you got a copy of the subarray.
To get a reference to the subarray define type of your array as array of NSMutableArrays:
var array: [NSMutableArray] = [["a", "b", "c"]]
var subArray = array[0]
subArray.removeObjectAtIndex(1)
print(array, subArray)
>> [(a, c)] [(a, c)]
You can read more about Arrays in Swift here
How to assign c type array to struct member that is also an array of the same type? Here's my struct:
typedef struct {
uint8_t type;
uint8_t data[10];
} MyStruct;
Here's the creation of the struct:
MyStruct myStruct;
Here's generation of some array:
uint8_t generatedArray[10] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
Here's my assignment:
myStruct.data = generatedArray;
As other answers have stated an array is not directly assignable and you must use a function such as memcpy:
memcpy(myStruct.data, generatedArray, sizeof(myStruct.data));
However...
C is a language with a long history. Early languages had roughly the notion of "little" and "large" types, the former being directly assignable and the latter not. Some later languages made everything assignable (or for functional languages, values).
Original C had primitive types; integer, float, etc.; and arrays of these types. The former, being "little", were assignable, the latter, being "large", were not. Subsequently C gained structures, and decided these were "little"...
So, a little strangely, while you cannot directly assign one array to another you can assign on structure to another, and in particular you can assign a structure with just one field which is an array... You can also write literal structure values, including for those with array-valued fields; and being C with its "types are comments" approach you can cast a pointer to an array to a pointer to a structure...
The above means you can write "fun" code like:
typedef struct
{
uint8_t type;
uint8_t data[10];
} MyStruct;
typedef struct
{
uint8_t data[10];
} MyArray;
typedef struct
{
uint8_t type;
MyArray array;
} MyStruct2;
void arrayAssignment(int x)
{
MyStruct myStruct;
MyArray generatedArray = {{1, 2, 3, 4, 5, 6, 7, 8, 9, 10}}; // structure literal
*(MyArray *)&myStruct.data = generatedArray;
uint8_t generatedArray2[] = {11, 12, 13, 14, 15, 16, 17, 18, 19, 20}; // array literal
*(MyArray *)&myStruct.data = *(MyArray *)generatedArray2;
MyStruct2 myStruct2;
myStruct2.array = generatedArray; // no casts at all, but element access is myStruct2.array.data[index]
}
Note that none of the casts, indirections, etc. or in the final example the extra array. in the indexing cost anything in the compiled code - they are all simply ways to persuade the compiler to use its built-in array assignment.
Many would of course argue against regular uses of these techniques!
Arrays cannot be assigned to each other, that is, an array identifier is not allowed to be on the left side of an assignment. When on the right side, the array is said to decay to a pointer to its first element, so it doesn't really represent the whole chunk.
You should use memcpy instead, and pass the size of the array which can be obtained via the sizeof operator. For short arrays, an optimizing compiler may be able to substitute the memcpy call with more efficient instructions to exploit the target architecture better.
You are attempting to assign to an array, but an array cannot be assigned to. An array is, however, an lvalue:
The following object types are lvalues, but not modifiable lvalues:
An array type
An incomplete type
A const-qualified type
An object is a structure or union type and one of its members has a const-qualified type
You'll need to use memcpy instead. You ought to pass sizeof(myStruct.data) as the third argument to memcpy:
memcpy(myStruct.data, generatedArray, sizeof(myStruct.data));
You can't directly assign an array like that. You'll have to copy it over.
I wonder how your compiler let you do that assignment. You cannot use array as modifiable lvalue. Also when used as rvalue an array represents a pointer to the first element in the array.
Other ways of achieving this would be to use pointers or to use memcopy()
With C99 you can use compound literals and string literals as initializer ( if uint8_t has the same bit-representation as char )
MyStruct myStruct={.data="\1\2\3\4\5\6\7\x8\x9\xa"};
...
MyStruct myStruct;
myStruct = (MyStruct){.data="\1\2\3\4\5\6\7\x8\x9\xa"};