Destructuración🔗

No creo que sea reconocida como valida la palabra destructuración sin embargo es la traducción que se puede encontrar de destructuring. Igual y uno podría usar desempaquetado.

Destructuring se entiende como una manera concisa de dar nombres a valores encontrados en una colección, que en términos de programación sería variables y estructuras de datos.

Ahora bien, el tema gira alrededor de parallel assignment, por lo que también se podría hablar de simultaneous assignment, multiple assignment y unpacking.

Variables🔗

Todo un tema… ¿estoy hablando de asociación (binding) o de asignación?… ¿estoy dando nombre a un valor o a una ubicación de memoria?… ¿es destructiva o de ocultación?.

Estructuras de datos🔗

Al menos solemos trabajar con dos tipos de estructuras de datos:

  • Secuenciales: listas y arreglos, por ejemplo.
  • Asociativas: mapas y conjuntos, por ejemplo.

Una vez más… ¿estoy hablando de una estructura de datos como valor o como un espacio de memoria?… ¿es una estructura de datos estática o dinámica?… ¿los datos en ella son de tipo mixto u homogéneo?.

Por cierto, ¿las cadenas de caracteres (string) son estructuras de datos?… ¿el lenguaje de programación me permite trabajar con ellas como si lo fueran?.

Métodos y/o funciones🔗

Y finalmente… ¿estoy hablando de paso por valor o paso por referencia?… ¿estoy trabajando con una variable local o una variable global… en fin.

Ejemplos🔗

Algunos ejemplos de destructuración que podemos encontrar en lenguajes de programación:

Clojure🔗

Cuenta con una sintaxis que refleja la estructura de datos a destructurar:

  • En secuencias: se asocia a, b y c a los valores encontrados en el vector [10 20 30], evaluando [c b a].

    => (let [[a b c] [10 20 30]]
         (vector c b a)) ;; [30 20 10]
    
  • En asociaciones: se asocia a al valor de la llave :x, b al valor de la llave :y y c al valor de la llave :z encontrados en el mapa {:x 10 :y 20 :z 30}, evaluando[c b a].

    => (let [{a :x b :y c :z} {:x 10 :y 20 :z 30}]
         (vector c b a)) ;; [30 20 10]
    
  • En funciones:

    => (defn f [[a b c]]
         [c b a])
    => (f [10 20 30]) ;; [30 20 10]
    
    => (defn g [{a :x b :y c :z}]
         [c b a])
    => (g {:x 10 :y 20 :z 30}) ;; [30 20 10]
    
    => (defn h [x]
         [(dec x) x (inc x)])
    => (let [[a b c] (h 10)]
         [c b a]) ;; [11 10 9]
    
    => (map
         (fn [[a b c]] [c b a])
         [[10 20 30] [40 50 60] [70 80 90]]) ;; ([30 20 10] [60 50 40] [90 80 70])
    
  • En cadenas de caracteres:

    => (let [[a b c] "HOLA"]
         [c b a]) ;; [\L \O \H]
    

Ruby🔗

Cuenta con dos sintaxis: una mediante la asignación en paralelo y otra mediante el splat operator (*):

  • En secuencias: se asocia a, b y c a los valores encontrados en el arreglo [10 20 30], evaluando [c b a]

    > a, b, c = [10, 20, 30]
    > [c, b, a] # [30, 20, 10]
    
  • En asociaciones: se asocia a al valor de la llave :x, b al valor de la llave :y y c al valor de la llave :z encontrados en el hash {:x 10 :y 20 :z 30}, evaluando [c b a].

    > a, b, c = {x: 10, y: 20, z: 30}.values_at(:x, :y, :z)
    > [c, b, a] # [30, 20, 10]
    
  • En funciones:

    > def f(a, b, c)
        [c, b, a]
      end
    > f(*[10, 20, 30]) # [30, 20, 10]
    
    > def g(a, b, c)
        [c, b, a]
      end
    > g(*{x: 10, y: 20, z: 30}.values_at(:x, :y, :z)) # [30, 20, 10]
    
    > def h(x)
        [x.pred, x, x.next]
      end
      a, b, c = h(10)
    > [c, b, a] ;; [11, 10, 9]
    
    > [[10, 20, 30], [40, 50, 60], [70, 80, 90]].map {|a, b, c| [c, b, a]} # [[30, 20, 10], [60, 50, 40], [90, 80, 70]]
    
  • En cadenas de caracteres:

    > a, b, c = "HOLA".chars
    > [c, b, a] # ["L", "O", "H"]
    

En conclusión🔗

El tema de destructuring varia entre los lenguaje de programación debido a la semántica, de ahí que uno se cuestione sobre el concepto que se tenga de variable y estructura de datos. Algo común, considero, es ver a la destructuración como una forma idiomática, apoyada por la sintaxis en un lenguaje de programación, para acceder al contenido de una estructura de datos sin lidiar directamente con la organización o el recorrido de la misma. Lo anterior libera al programador de escribir las instrucciones singulares para cada operación de acceso a la información, pero sobre todo, permite que el código refleje la organización de la estructura de datos con la cual se trabajará.