4 years ago by s3cur3
Swift's Array type is just so well designed. It's a delight to use.
Two things stood out to me here as being really nice for someone coming from C++:
- Implicit upcasting to convert `[Derived]` to `[Base]` in O(1).
- Checked conversions convert `[T]` to `[U]?` in O(N) via `a as [U]` in O(n).
These are both operations I've manually written the C++ code to do, because there's no ergonomic way to do it with `std::vector`.
4 years ago by higerordermap
As someone who hasn't used swift, are there same array covariance problems as C#/Java due to implicit casting?
4 years ago by KMag
I was wondering the same thing. The linked article explains that they use an extra layer of indirection to perform copy-on-write for implicit upcasts. So, you can upcast in O(1), but your first write to the upcast array has an O(N) cost.
The upcast is type sound, unlike Java, but at the cost of an extra indirection, and a big hit for the first mutation after upcast. I would have been tempted to instead just have immutable array references that could be freely upcast, but this is also an elegant and safe solution.
4 years ago by undefined
4 years ago by jimbob45
Isnāt your second one just a simple ternary macro to check if null and return if so?
4 years ago by s3cur3
Not in C++ or Swift, noāto do it in the general case requires trying to cast each member of the array to the Derived type, and returning the null optional if any of those conversions fails.
E.g., given an array of Animal, youād like to see if you can convert it to an array of Dog. Neither the compiler nor the runtime stores information on the array itself to say āit just so happens that the concrete Animal type of all the things I hold is [Dog/Cat/a mix of both],ā so you have to go through the elements one by one.
4 years ago by andijcr
for the first one, there is no direct equivalent, but you can directly loop over any [Derived] collection as a reference to [Base]
4 years ago by s3cur3
True! Itās only an annoyance when you need to pass a std::vector<Derived> to a function that only accepts std::vector<Base>.
4 years ago by coldtea
>To achieve goals 1 and 2 together, we use static knowledge of the element type: when it is statically known that the element type is not a class, code and checks accounting for the possibility of wrapping an NSArray are eliminated. An Array of Swift value types always uses the most efficient possible representation, identical to that of ContiguousArray.
Why would elements being classes change this?
Wouldn't an array of class elements only hold pointers to those instances, so it wouldn't be different than "an array of Swift value types" at that regard (the extra dereference would only be needed after getting the element pointer out of the array).
4 years ago by gilgoomesh
The point is that an NSArray can only hold classes (an Objective-C limitation), so if the element type is not a class, it can't be an NSArray.
4 years ago by mpweiher
> Why would elements being classes change this?
It's more the other way around: having non-objects allows things to change.
Being able to transparently bridge between Objective-C and Swift is very valuable, particularly because the vast majority of library/framework code is written in Objective-C.
So Swift Arrays are designed to be bridgeable to NSArray whenever possible, for example by simply pointing to an NSArray as their backing store. NSArrays can be non-contiguous, largely due to them not really being arrays in the strict sense, but more like Smalltalk OrderedCollections, meaning you can, for example, add and remove elements from the front.
However, non-object Swift types cannot be stored in an NSArray and would thus never be expected in Objective-C code. Therefore, there is no need to bridge those, meaning that you can use different kinds of backing store.
4 years ago by blacktriangle
It's very valuable...to working with the existing Apple ecosystem. These are the issues that keep sinking Swift as a general purpose language: it is hamstrung by its requirement to bridge to Objective-C.
4 years ago by schrodinger
Thought that was strange too, but if you read further it talks about having to use NSArray which isnāt always contiguous for class types to have free bridging with obj-c.
4 years ago by bobbylarrybobby
I think that because a Swift array of objects must be bridgeable from Objective-C, and Objective-C arrays might be non-contiguous, Swift arrays of objects must be permitted to be non-contiguous. This isnāt a concern with arrays of structs because they donāt exist in Objective-C. In practice, Iād imagine that Swift arrays of objects that are never bridges to/from Objective-C are almost always contiguous.
Daily digest email
Get a daily email with the the top stories from Hacker News. No spam, unsubscribe at any time.