Any way to get array by reference?

Today I spent one hour to get myself educated on Array type.

I have the following class in one of my app:

class PathNode: Hashable, Comparable, CustomStringConvertible {
    var name: String!
    var path: String!
    var children: [PathNode]?
    
    static func == (lhs: PathNode, rhs: PathNode) -> Bool {
        lhs.name == rhs.name
    }

    static func < (lhs: PathNode, rhs: PathNode) -> Bool {
        lhs.name < rhs.name
    }

    func hash(into hasher: inout Hasher) {
        hasher.combine(name)
        hasher.combine(children)
    }

    /// Sort child nodes.
    func sort() {
        if let children = self.children {
            children.sort()
            for child in children { child.sort() }
        }
    }
// other members...
}

The problem is in the sort function. I found out in my outline view the result is not sorted even though I did call sort on the root node.

After about one hour's frustration, I came to realize that I forgot one import fact about the array type in Swift - it's a value type!

I have to adjust sort function to the following code:

    /// Sort child nodes.
    func sort() {
        if self.children != nil {
            self.children!.sort()
            for child in self.children! { child.sort() }
        }
    }

That's not an elegant way of writing code! Is there any other way to get a 'reference' to an array in Swift?

Your initial code cannot compile : Cannot use mutating member on immutable value: 'children' is a 'let' constant.

You should write

if var children =

But problem here:

    func sort() {
        if let children = self.children {
            children.sort()
            for child in children { child.sort() }
        }
    }

You create a local var (const) children, which you sort, but this has effectively no effect on self.children.

BTW, the solution 1 is not ugly at all !

    func sort() {
        if self.children != nil {
            self.children!.sort()
            for child in self.children! { child.sort() }
        }
    }

What you could do (solution 2):

    func sort() {
        if let children = self.children {
            children.sort()
            for child in children { child.sort() }
            self.children = children  // <<-- Add this
        }
    }

But that's not really more elegant.

If you absolutely want to pass a reference, use inout, solution 3:

    func sort2( childrenToSort: inout [PathNode]?) {
        if var childrenToSort {
            childrenToSort.sort()
            for child in childrenToSort { child.sort() }
        }
    }

And call:

path1.sort2(childrenToSort: &path1.children)

But that's uselessly complicated compared to solution 1 or 2.

There are many discussions on this, like here: https://stackoverflow.com/questions/24250938/swift-pass-array-by-reference

I agree on one point. I find it misleading and error ptone to have the same = operator work as assign reference or assign content, depending on the type of object (which we don't necessarily know immediately).

I once suggested to have 2 operators, such as = and := to assign content ; which would have worked for class (providing built-in assign content operator) and struct (providing the assign reference you looked for), allowing developer to know precisely what he/she is doing.

But Swift will not change now.

Any way to get array by reference?
 
 
Q