[swift] 코드로 알아보는 Lazy Stroed Properties, Lazy Sequence

okstring·2021년 2월 14일
0

Lazy Stored Properties

A lazy stored property is a property whose initial value is not calculated until the first time it is used. You indicate a lazy stored property by writing the lazy modifier before its declaration.

delegate를 만들 때 lazy를 사용한 것을 볼 수 있었다. swift 문서에서는 lazy를 위와 같이 설명해뒀는데 lazy는 처음 사용할때까지 초기 값이 계산되지 않는 property다. 간단한 예제를 통해 알아보자

class Product {
    private var identifier = 0
    lazy var ID: Int = {
        return makeID()
    }()
    
    private func makeID() -> Int {
        print("makeID가 실행됩니다.")
        identifier += 1
        return identifier
    }
}

let product = Product()
print(product.ID)

ID를 만들 때 makeID라는 메소드를 사용해서 만들게 됩니다. 처음 product 인스턴스를 만들때는 ID가 선언이 되어있지 않지만 ID를 사용해야 안의 print 메소드가 실행된다.

지금은 makeID 작업이 간단하지만 만약 ID를 만드는 작업이 많은 시간비용이 드는 작업이라면 lazy를 이용해야 하는 이유가 더 늘어날 것이다.

만약 위 코드에서 lazy를 붙이지 않는다면 이런 컴파일 에러가 난다

Cannot use instance member 'makeID' within property initializer; property initializers run before 'self' is available

lazy를 사용할 때 중요한 점은 다음과 같다

  • lazy 속성은 lazy var로 선언해야 한다. 해당 변수가 쓰이기 전에는 사용하지 않기 때문에! 또한 데이터 타입도 미리 명시를 해줘야 한다.
  • lazy 내에서 self를 사용해야 합니다. 클래스를 사용할 때 strong reference cycle을 만들지 않도록 [unowned self]도 선언해야 합니다.
  • 지연 속성을 ()로 끝내야합니다. 즉, 함수를 호출하는 일을 해야 한다.

Lazy Sequence

A sequence containing the same elements as a Base sequence, but on which some operations such as map and filter are implemented lazily.

lazy sequence는 apple 문서에서 나온 설명 그대로 번역하자면 이 시퀀스와 동일한 요소를 포함하지만 맵 및 필터와 같은 일부 작업이 느리게 구현되는 시퀀스입니다.

lazy sequence는 Lazy Stored Properties와 성격은 비슷해보이지만 이름 그대로 SequenceType, CollectionType protocol에 lazy라는 computed property가 존재하고 쓰이게 됩니다.

func printAndReturnSquareValue(_ value: Int) -> Int {
    print("print square value \(value * 2)")
    return value * 2
}

let arr = Array(1...100)
let computed = arr.lazy.map(printAndReturnSquareValue)
print(computed[5])

// print square value 12
// 12
  • lazy를 사용하게 되면 computed에서 printAndReturnSquareValue를 계산하지 않고 print(computed[5]) 에서 사용하게 됩니다.
  • 이로 인해 필요한 곳에만 계산을 해서 퍼포먼스를 향상시킬 수 있다!

다른 예로 filter도 알아보자

let arr = Array(1...100).shuffled()
func filterSmallNumber(_ value: Int) -> Bool {
    print("Execute")
    return value < 10 ? true : false
}

let computed = arr.lazy.filter(filterSmallNumber)
print("Hello!")
print(computed.first!)
print(computed.first!)

//Hello!
//Execute
//Execute
//Execute
//Execute
//Execute
//Execute
//Execute
//Execute
//3
//Execute
//Execute
//Execute
//Execute
//Execute
//Execute
//Execute
//Execute
//3
  • array를 섞은 후 filter 메소드에 filterSmallNumber 를 넣어 실행하게 했다 물론 lazy
  • computed.first!를 만나고 그제야 섞인 수 중에 10 미만의 수를 찾을때까지 실행하는 모습을 볼 수 있다.
  • 하지만 값을 저장해두지 않고 똑같이 computed.first!또 실행하게 되면 처음부터 다시 한 번 더 찾는 모습을 보여준다. 이를 참고로 주의해서 사용해야 할 것 같다.

Reference

https://www.hackingwithswift.com/example-code/language/what-are-lazy-variables

https://kor45cw.tistory.com/252

https://zeddios.tistory.com/387

profile
step by step

0개의 댓글