Passing arrays to funcs in Swift

In Objective-C, one can pass an array to a function easily be reference and allow the array values to be changed by the function. This seems to be very difficult to do in Swift. I have a fixed length array which I am passing to a function whose header is:


func rho33(.... inout inten: [Float]...)


In the calling program, I use:


rho33(...inten: &inten...) to pass the array, "inten". Swift requires the local value of the passed array to be also in the calling statement, followed by a colon. I allocated enough memory for inten using: "inten.reserveCapacity(400)" (in the calling program). When I single stepped through the program, whenever it accessed "inten" in the function, I got an "index out of bounds" error (I also reserved the memory in the func and this didn't help). Is there a good reference to this business of passing arrays (a fairly elementary and useful procedure in all the C dialects)? Thanks!


Warren Nagourney

Accepted Reply

1. The capcity of the array is not the count of the array. Reserving capactiy just makes sure that the array is allocated enough memory so that it's unlikely any more memory will need to be allocated for the reserved number of elements. But the array is still empty (count == 0) until you add elements.


If you want to create an array that has 400 elements, so that the rho33 function can simply index into it, allocate it like this:


myArray = [Float] (count: 400, repeatedValue: 0)


2. Yes, it's inconvenient to pass around array references (via 'inout') in Swift. In Obj-C, you are encouraged to design your app to take advantage of reference semantics, but in Swift you are encouraged to rethink your design in terms of value semantics. This takes a bit of getting used to.


It's OK to pass the array by reference (with 'inout') if you want to. Or, you can make the array a property of a class, and pass around the object reference instead.

Replies

1. The capcity of the array is not the count of the array. Reserving capactiy just makes sure that the array is allocated enough memory so that it's unlikely any more memory will need to be allocated for the reserved number of elements. But the array is still empty (count == 0) until you add elements.


If you want to create an array that has 400 elements, so that the rho33 function can simply index into it, allocate it like this:


myArray = [Float] (count: 400, repeatedValue: 0)


2. Yes, it's inconvenient to pass around array references (via 'inout') in Swift. In Obj-C, you are encouraged to design your app to take advantage of reference semantics, but in Swift you are encouraged to rethink your design in terms of value semantics. This takes a bit of getting used to.


It's OK to pass the array by reference (with 'inout') if you want to. Or, you can make the array a property of a class, and pass around the object reference instead.

Thanks very much -- that fixed things.


It seems inefficient and wasteful to pass along a large array by value -- is it really necessary to copy the array to a different place in memory when the initial address is readily available?


As a rank beginner in Swift, I am finding a number of things somewhat awkward -- rigorous typing (particularly with the graphics CGFloat, which is not implicitely converted from Float), white space around equals and dyadic operators, the confusion when there are no trailing zeros in floats, etc. I'll get used to these things.


Thanks again -- the app works well.


**

The Swift runtime is lazy I think; it will only actually make a copy of the array if one of the places that holds a reference is mutated. So logically it is a copy but behind the scenes it may be a reference until such time as it actually needs to be a copy.

I understand the mental adjustment that's required from native Swift arrays being value types. If you're used to reference types, it seems unnatural. I suggest you watch the WWDC videos that touch on the philosophy of value types:


https://developer.apple.com/videos/play/wwdc2015/414/

https://developer.apple.com/videos/play/wwdc2015/408 (the beginning few minutes, in particular)


It's worth taking the time to understand that it's a deliberate choice, to make the language like that.


Besides, as I said before, it's easy enough to wrap an array in a class, if you want to pass the array around with familiar reference semantics.