Post

Atributo Lazy en propiedades e iteraciones en Swift

He aquí las características de las propiedades tipo lazy y las iteraciones tipo lazy.

Las propiedades lazy se calculan cuando son invocadas y una sola vez.

struct Plan {
    //Calcula- cada vez que-es -LLanada**
    var content: String {
        sleep (2) //Operación que toma algún tiempo
        return Date.now.formatted(dateTime.hour().minute().second())
    }
    
    //Calcula valor al inicializar
    private(set) var closureContent: String  = {
        
        sleep (2) //Operación que toma algún tiempo
        return Date.now.formatted(dateTime.hour().minute().second())
    }
    
    //Calcula valor cuando es- llamada y-almacena**-
    lazy private(set) var lazyClosureContent: String =  {
        sleep (2) //Operación que toma algún tiempo
        return Date.now.formatted(.dateTime.hour().minute().second())
    }
}

🧮 En el ejemplo de las propiedades tenemos:

La propiedad content calculará el resultado cada vez que es llamada, por lo que el resultado será diferente cada vez.

La propiedad closureContent calcula el resultado, cuando el struct se instancia y almacena lo almacena.

La propiedad lazyClosureContent calcula el resultado cuando hasta el momento en que se le invoca y lo almacena.

var plan = Plan()
print("Inicio", Date.now.formatted(.dateTime.hour().minute().second())) //12:35:25 PM
print(plan.lazyClosureContent)                                          //12:35:27 PM
print(plan.closureContent)                                              //12:35:25 PM
print(plan.content)                                                     //12:35:29 PM
print(plan.lazyClosureContent)                                          //12:35:27 PM
print(plan.closureContent)                                              //12:35:25 PM
print(plan.content)                                                     //12:35:31 PM
print("Fin", Date.now.formatted(.dateTime.hour().minute().second()))    //12:35:31 PM 

⏩️ En el ejemplo de las iteraciones

let granRango = 0..<Int.max //Range(0..<9223372036854775807)
let filterLazy = granRango.lazy.filter { S0.isMultiple(of: 2) }
// Range (9223372036854775802..<9223372036854775807)
    .suffix(3)
// 9223372036854775802, 9223372036854775804, 9223372036854775806

Con map y filter tenemos la opción de retrasar su ejecución hasta el momento que lo necesitamos y sobre los elementos que le son solicitados.

La propiedad filterLazy solo almacena el rango y cuando es invocada itera sobre los números que son solicitados, no sobre todo el rango.

La desventaja es que lo realiza cada vez que es invocada y almacena un closure de tipo @escaping que debemos tener en cuenta.

Ambos casos pueden ayudarnos a incrementar el performance al no hacer operaciones sobre procesos que el usuario no solicita.