Limit calculated variable

I am trying to create a Vector structure that has a lazy computed variable magnitude, but I cannot find a way to make it.

This is what I have:

struct Vector {

    var x: Double = 0.0 {
        didSet {
            magnitudeActual = -1.0
        }
    }
    var y: Double = 0.0 {
        didSet {
            magnitudeActual = -1.0
        }
    }

    var magnitudeActual: Double = 0.0

    var magnitude: Double {
        if magnitudeActual < 0.0 {
            magnitudeActual = sqrt(x * x + y * y) //cannot assign to "magnitudeActual" in self
        }
        return magnitudeActual
    }

    init() {}

    init(_ x: Double, _ y: Double) {
        self.x = x
        self.y = y
    }

}

I tried many ways to make this work, but nothing works. In addition, a willGetwill be enjoyable, but does not exist.

+4
source share
4 answers

From the docs:

Changing value types from methods inside an instance

Structures and enumerations are value types. By default, value type properties cannot be changed from its instance methods.

, , . ( ) , , , , . self, , .


, a struct , , , mutating. , get .

var magnitude: Double {
mutating get {
    if magnitudeActual < 0.0 {
        NSLog("Recalc") // just to make sure it caching the result properly.
        magnitudeActual = sqrt(x * x + y * y)
    }
    return magnitudeActual
}
}

var v = Vector(3, 4)
v.magnitude // Recalc 5
v.magnitude // 5

v.x = 5
v.y = 12
v.magnitude // Recalc 13
+4

, getter, Alex ,

init(_ x: Double, _ y: Double) {
    self.x = x
    self.y = y
}

, setter x y , , didSet willSet. magnitudeActual 0,

var v = Vector(3,4)

0.

var v = Vector()
v.x = 3
v.y = 4

, Actual -1, .

magnitudeActual -1, GoZoner.

, .


, :

struct Vector {

    var x: Double = 0.0 {
    didSet {
        println("set x")

        magnitudeActual = -1.0
    }
    }
    var y: Double = 0.0 {
    didSet {
        println("set y")
        magnitudeActual = -1.0
    }
    }

    var magnitudeActual: Double = -1.0

    var magnitude: Double {
    mutating get {
        if magnitudeActual < 0.0 {
            println("Recalc") // just to make sure it caching the result properly.
            magnitudeActual = sqrt(x * x + y * y)
        }
        return magnitudeActual
    }
    }

    init() {}

    init(_ x: Double, _ y: Double) {
        self.x = x
        self.y = y
    }
}
+1

:

var magnitude: Double {
   return sqrt(x * x + y * y)
}

, :

lazy var magnitude: Double = {
   return sqrt(x * x + y * y)
}()

Since he is lazy, he will not try to complete the task until his first access. Since assignment is the result of a closure, closure will be performed for the assignment, allowing this value to be calculated on first access.

Here is a simple example of what this behavior is:

class MyClass {
    var x :Double = 10
    lazy var magnitude: Double = {
       return self.x
    }()
}

var obj = MyClass()

obj.x = 12
obj.magnitude // 12 (magnitude was calculated right here after x was changed)

obj.x = 14
obj.magnitude // 12 (magnitude did not change)

obj.magnitude = 8
obj.magnitude // 8 (it changed)
0
source

Of course, you save very little, buy very little, optimizing the calculation magnitude. You can make and spray simply:

class Point {
 var x : Double;
 var y : Double;
 var magnitude : Double { return sqrt (x*x + y*y) }
 var angle     : Double { return atan (x, y) }
}

but if you need to optimize,

class Point {
  var x : Double { didSet { updateMagnitude() }}
  var y : Double { didSet { updateMagnitude() }}
  var magnitude : Double

  func updateMagnitude () { self.magnitude = sqrt (x*x + y*y) }

  init () {
    // ...
    updateMagnitude()
  }
}
0
source

All Articles