Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Variable p passed by reference before being initialized

I have a Human class with a function that takes any amount of people and determines if someone is older than any of those people, then returns an array with the people he/she is older than.

func isOlderThan(people: Human...) -> [Human] {
    var p: [Human]

    for person in people {
        if age > person.age {
            p.append(person)
        }
    }
    return p
}

However at

p.append(person)

I'm getting the error

Variable p passed by reference before being initialized

Anyone sure why this is? Thanks!

like image 945
Brejuro Avatar asked Jul 19 '14 07:07

Brejuro


3 Answers

Your declaration of p is just that, a declaration. You haven't initialised it. You need to change it to

var p = [Human]()

Or, as @MartinR points out,

var p: [Human] = []

There are other equivalent constructs, too, but the important thing is you have to assign something to the declared variable (in both cases here, an empty array that will accept Human members).

Update For completeness, you could also use:

var p: Array<Human> = []

or

var p = Array<Human>()
like image 75
Grimxn Avatar answered Sep 23 '22 23:09

Grimxn


append is a mutating method of the struct Array.

You can think of a struct method as a function with a hidden self parameter. By default, parameters to functions are constants, and therefore you cannot do anything to it that you cannot do to a constant. A mutating struct method needs to do things that cannot be done to a constant, therefore, it must take the self parameter as inout, i.e. as if it's passed by reference. Thus, you can only call a mutating method on something you can pass by reference. And you cannot pass an uninitialized variable by reference.

like image 31
newacct Avatar answered Sep 21 '22 23:09

newacct


You are better off simply using the filter method:

func isOlderThan(people: Human...) -> [Human] {
  return people.filter { self.age > $0.age }
}

It works like this:

 20> class Human {
 21.     let age : Int
 22.     init (age: Int) { self.age = age }
 23.     func isOlderThan (people: Human...) -> [Human] {
 24.         return people.filter { self.age > $0.age }
 25.     }
 26. }

 28> let me = Human(age:27)
me: Human = {
  age = 27
}

 29> me.isOlderThan (Human(age:25), Human(age:30))
$R10: [Human] = 1 value {
  [0] = {
    age = 25
  }
}

By the way, before long you'll find it useful to define an additional method specified as:

func isOlderThan(people: [Human]) -> [Human] { ... }

because as soon as you have an array and since there is no apply method yet in Swift, your original method won't work.

like image 22
GoZoner Avatar answered Sep 25 '22 23:09

GoZoner