• ¿Qué es un lenguaje de programación?
  • Entorno de Desarrollo en macOS
WeiseRatel
  • ¿Qué es Swift?
  • ¿Hablamos?
  • Sobre WeiseRatel.com
No Result
View All Result
  • ¿Qué es Swift?
  • ¿Hablamos?
  • Sobre WeiseRatel.com
No Result
View All Result
WeiseRatel
No Result
View All Result
Home Lenguajes de Programación Swift

Swift – ¿Cómo iterar sobre tipos de datos propios?

WeiseRatel by WeiseRatel
in Swift
Reading Time: 6 mins read
A A
¿Cómo iterar sobre tipos de datos propios?, Swift
11
SHARES
36
VIEWS
Compartir en FacebookCompartir en Twitter

Hoy aprenderemos a iterar sobre tipos de datos propios. Veremos como los protocolos SequenceType y GeneratorType nos ayudan a conformar una interfaz para que nuestros tipos de datos sea iterables a través de un bucle for-in.

Creo que resulta evidente la utilidad que esto tiene y si alguien piensa que por defecto lo podemos hacer pues está completamente equivocado y lo vamos a demostrar. Hoy aprenderemos a implementar esta funcionalidad.

[better-ads type=’banner’ banner=’159′ ]

Iterar sobre tipos de datos propios

Tomemos como ejemplo una Pila y veamos si podemos iterar sobre cada elemento almacenado:

import Cocoa

struct Stack<Element> {
    
    var items = [Element]()
    
    mutating func push(newItem: Element) {
        
        items.append(newItem)
        
    } // push
    
    mutating func pop() -> Element? {
        
        guard !items.isEmpty else {
            
            return nil
            
        } // guard
        
        return items.removeLast()
        
    } // pop
    
    mutating func append(item: Element) {
        
        self.push(item)
        
    } // append
    
    func map<U>(f: Element -> U) -> Stack<U> {
        
        var mappedItems = [U]()
        
        for item in items {
            
            mappedItems.append(f(item))
            
        } // for
        
        return Stack<U>(items: mappedItems)
        
    } // map
    
    var count: Int {
        
        return items.count
        
    } // count
    
    subscript(i: Int) -> Element {
        
        return items[i]
        
    } // subscript
    
} // Stack

var myStack = Stack<Int>()

myStack.push(10)
myStack.push(20)
myStack.push(30)

for value in myStack.items {
    
    print("Obteniendo el valor: (value)")
    
} // for

y la salida en pantalla sería:

Obteniendo el valor: 10
Obteniendo el valor: 20
Obteniendo el valor: 30

Sí, funciona perfectamente.

¿No debería de haber fallado?

pues no, hemos hecho trampa, realmente no estamos iterando sobre nuestro tipo Stack, lo hacemos sobre el arreglo llamado items que es miembro de la estructura Stack, y que al ser un arreglo común, Swift conoce como iterar sobre él.

Para poder usar nuestro propio tipo de dato y que el bucle for-in por ejemplo, sepa de donde extraer los valores, tenemos que adoptar dos protocolos que son los que establecen la interfaz necesaria para que esto ocurra.

El protocolo GeneratorType

Comprendamos antes la intención detrás de este protocolo que forma parte de la librería estándar de Swift y que a su vez cuenta con un tipo asociado, algo que ya analizamos en el artículo sobre tipos genéricos.

Su definición es bastante sencilla:

protocol GeneratorType {
    
    associatedtype Element
    
    mutating func next() -> Element?
    
} // GeneratorType

aquí tenemos un tipo asociado nombrado Element y una función marcada como mutable de nombre next y que devuelve un valor opcional de tipo Element.

[better-ads type=’banner’ banner=’160′ ]

Creemos ahora una estructura de nombre StackGenerator que implemente el protocolo GeneratorType y que obtendrá los valores a generar de los elementos almacenados dentro de la Pila:

protocol GeneratorType {
    
    associatedtype Element
    
    mutating func next() -> Element?
    
} // GeneratorType

struct StackGenerator<T>: GeneratorType {
    
    typealias Element = T
    
    var stack: Stack<T>
    
    mutating func next() -> Element? {
        
        return stack.pop()
    
    } // next
    
} // StackGenerator

var myStack = Stack<Int>()

myStack.push(10)
myStack.push(20)
myStack.push(30)

var myStackGenerator = StackGenerator(stack: myStack)

while let value = myStackGenerator.next() {

    print("Obteniendo el valor: (value)")
    
} // while

la salida en pantalla sería:

Obteniendo el valor: 30
Obteniendo el valor: 20
Obteniendo el valor: 10

La función de GeneratorType es que podamos llamar al método next repetidas veces y que en cada una de ellas nos genere un nuevo valor. En caso de que no sea posible seguir generando más valores el método devuelve nil.

El protocolo SequenceType

El próximo protocolo que analizaremos será SequenceType que forma parte también de la librería estándar del lenguaje y cuenta con la siguiente definición:

protocol SequenceType {
    
    associatedtype Generator: GeneratorType
    
    func generate() -> Generator

} // SequenceType

como podemos observar es igual de sencilla que el anterior protocolo. Se declara un tipo asociado de nombre Generator y de tipo GeneratorType y un método de nombre generate que devuelve un objeto Generator.

Ahora en pos de entender mejor su funcionamiento unamos el código que ya tenemos con este nuevo protocolo y hagamos que nuestra Pila lo adopte:

//: Playground - noun: a place where people can play

import Cocoa

struct StackGenerator<T>: GeneratorType {
    
    typealias Element = T
    
    var stack: Stack<T>
    
    mutating func next() -> Element? {
        
        return stack.pop()
        
    } // next
    
} // StackGenerator

struct Stack<Element>: SequenceType {
    
    var items = [Element]()
    
    mutating func push(newItem: Element) {
        
        items.append(newItem)
        
    } // push
    
    mutating func pop() -> Element? {
        
        guard !items.isEmpty else {
            
            return nil
            
        } // guard
        
        return items.removeLast()
        
    } // pop
    
    mutating func append(item: Element) {
        
        self.push(item)
        
    } // append
    
    func map<U>(f: Element -> U) -> Stack<U> {
        
        var mappedItems = [U]()
        
        for item in items {
            
            mappedItems.append(f(item))
            
        } // for
        
        return Stack<U>(items: mappedItems)
        
    } // map
    
    func generate() -> StackGenerator<Element> {
        
        return StackGenerator(stack: self)

    } // generate
    
    var count: Int {
        
        return items.count
        
    } // count
    
    subscript(i: Int) -> Element {
        
        return items[i]
        
    } // subscript
    
} // Stack

var myStack = Stack<Int>()

myStack.push(10)
myStack.push(20)
myStack.push(30)

for value in myStack {
    
    print("Getting the value: (value)")
    
} // for

la salida en pantalla sería:

Getting the value: 30
Getting the value: 20
Getting the value: 10

De la línea 61 a la 65 implementamos el método generate el cual se apoya en la estructura StackGenerator y esta a su vez es la que retornamos como objeto de tipo GeneratorType.

En este punto ya queda bastante claro el comportamiento: el método generate le brinda al bucle for-in un flujo de valores sobre los cuales iterar y esto lo obtiene gracias al objeto de tipo GeneratorType que este método retorna y que haciendo uso de su método next se va obteniendo valor tras valor.

[better-ads type=’banner’ banner=’161′ ]

Dicho esto ya podemos confiar nuestra Pila al bucle for-in tal y como podemos constatar en la línea 87, sin necesidad de hacer referencias a nada más que a la instancia del objeto.

El protocolo SequenceType junto a GeneratorType conforman una interfaz para el bucle for-in, logrando así que los valores que conforman cierta colección de datos puedan ser recorridos / iterados.

Falta aún mucho por aprender en nuestro camino a convertirnos en iOS Developer. Suscríbete a nuestra lista de correo y síguenos en nuestras redes sociales. Mantente al tanto de todas nuestras publicaciones.

Espero que todo cuanto se ha dicho aquí, de una forma u otra le haya servido de aprendizaje, de referencia, que haya valido su preciado tiempo.

Este artículo, al igual que el resto, será revisado con cierta frecuencia en pos de mantener un contenido de calidad y actualizado.

¡Cualquier duda o sugerencia, ya sea errores a corregir o ejemplos a añadir, será más que bienvenida, necesaria!

WeiseRatel

WeiseRatel

Desarrollador Swift / iOS. Llevo en el mundo de la informática más de 15 años, trabajado con varios lenguajes de programación y frameworks como Swift, C++ / Qt, C#, Java, entre otros. También he fungido como administrador de redes, bases de datos y sistemas Linux (algún que otro BSD) desde 2005 hasta la actualidad. Soy “Experto en Administración y Seguridad de Redes” por la Universidad Tecnológica Nacional FRVM de Córdoba, Argentina.

Artículos relacionados

La Sentencia Guard, Swift
Swift

Swift – La Sentencia Guard

Funciones de Órden Superior, Swift
Swift

Swift – Funciones de Órden Superior

Trabajo con Fechas, Swift
Swift

Swift – Trabajo con Fechas

Gestión de Archivos, Swift
Swift

Swift – Gestión de Archivos

Load More
0 0 votos
Article Rating
Suscríbete
Login
Notificar de
guest
guest

Este sitio usa Akismet para reducir el spam. Aprende cómo se procesan los datos de tus comentarios.

0 Comments
Inline Feedbacks
Ver todos los comentarios

Suscríbete

Únete!

Únete!

Suscríbete a nuestra lista de correo y mantente actualizado con las nuevas publicaciones.

Se ha suscrito correctamente!

Entradas recientes

  • Estructuras de Datos – Lista Enlazada
  • MariaDB – Comandos Básicos
  • MariaDB – Instalación y Configuración
  • ¿Cómo hacer una instalación limpia de macOS Catalina?
  • Git – Instalación y Configuración

Categorías

  • Bases de Datos (2)
    • MariaDB (2)
  • Estructuras de Datos (3)
  • Gestión de Dependencias (2)
    • Swift Package Manager (2)
  • Git (2)
  • Guías (2)
  • Lenguajes de Programación (27)
    • Swift (27)
  • Sobre WiseRatel.com
  • Política de Privacidad
  • Política de Cookies
  • ¿Hablamos?
Powered by humans!

© 2021 WeiseRatel. All Rights Reserved.

No Result
View All Result
  • ¿Qué es Swift?
  • ¿Hablamos?
  • Sobre WeiseRatel.com

© 2021 WeiseRatel. All Rights Reserved.

wpDiscuz
RECIBE CONTENIDO SIMILAR EN TU CORREO

RECIBE CONTENIDO SIMILAR EN TU CORREO

Suscríbete a nuestra lista de correo y mantente actualizado con las nuevas publicaciones.

Se ha suscrito correctamente!

Cookies Para que este sitio funcione adecuadamente, a veces instalamos en los dispositivos de los usuarios pequeños ficheros de datos, conocidos como cookies. La mayoría de los grandes sitios web también lo hacen.
Aceptar cookies
Leer más
Ajustes de cookies
Configuración de Cookie Box
Configuración de Cookie Box

Ajustes de privacidad

Decida qué cookies desea permitir. Puede cambiar estos ajustes en cualquier momento. Sin embargo, esto puede hacer que algunas funciones dejen de estar disponibles. Para obtener información sobre eliminar las cookies, por favor consulte la función de ayuda de su navegador. MÁS INFORMACIÓN SOBRE LAS COOKIES QUE USAMOS.

Con el deslizador, puede habilitar o deshabilitar los diferentes tipos de cookies:

  • Block all
  • Essential
  • Functionality
  • Analytics
  • Advertising

Este sitio web

  • Esencial: Recordar sus ajustes de permisos de cookies
  • Esencial: Permitir cookies de sesión
  • Esencial: Recopilar la información que introduzca en el formulario de contacto de un boletín informativo y otros formularios en todas las páginas
  • Esencial: Hacer un seguimiento de lo que introduzca en la cesta de la compra
  • Esencial: Verificar que ha iniciado sesión en su cuenta de usuario
  • Esencial: Recordar la versión del idioma seleccionado

Este sitio web no

  • Recordar los datos de inicio de sesión
  • Funcionalidad: Recordar los ajustes de redes sociales
  • Funcionalidad: Recordar el país y la región seleccionados
  • Análisis: Hacer un seguimiento de las páginas visitadas y de la interacción en las mismas
  • Análisis: Hacer un seguimiento de la ubicación y la región según la dirección IP
  • Análisis: Hacer un seguimiento del tiempo pasado en cada página
  • Análisis: Aumentar la calidad de los datos de las funciones estadísticas
  • Publicidad: Adaptar la información y la publicidad a sus intereses según, p.ej., el contenido que ha visitado antes. (Actualmente no usamos segmentación ni cookies de segmentación)
  • Publicidad: Recopilar información personalmente identificable como el nombre y la ubicación

Este sitio web

  • Esencial: Recordar sus ajustes de permisos de cookies
  • Esencial: Permitir cookies de sesión
  • Esencial: Recopilar la información que introduzca en el formulario de contacto de un boletín informativo y otros formularios en todas las páginas
  • Esencial: Hacer un seguimiento de lo que introduzca en la cesta de la compra
  • Esencial: Verificar que ha iniciado sesión en su cuenta de usuario
  • Esencial: Recordar la versión del idioma seleccionado
  • Funcionalidad: Recordar todos los ajustes de redes sociales
  • Funcionalidad: Recordar el país y la región seleccionados

Este sitio web no

  • Análisis: Hacer un seguimiento de las páginas visitadas y de la interacción en las mismas
  • Análisis: Hacer un seguimiento de la ubicación y la región según la dirección IP
  • Análisis: Hacer un seguimiento del tiempo pasado en cada página
  • Análisis: Aumentar la calidad de los datos de las funciones estadísticas
  • Publicidad: Adaptar la información y la publicidad a sus intereses según, p.ej., el contenido que ha visitado antes. (Actualmente no usamos segmentación ni cookies de segmentación)
  • Publicidad: Recopilar información personalmente identificable como el nombre y la ubicación

Este sitio web

  • Esencial: Recordar sus ajustes de permisos de cookies
  • Esencial: Permitir cookies de sesión
  • Esencial: Recopilar la información que introduzca en el formulario de contacto de un boletín informativo y otros formularios en todas las páginas
  • Esencial: Hacer un seguimiento de lo que introduzca en la cesta de la compra
  • Esencial: Verificar que ha iniciado sesión en su cuenta de usuario
  • Esencial: Recordar la versión del idioma seleccionado
  • Funcionalidad: Recordar todos los ajustes de redes sociales
  • Funcionalidad: Recordar el país y la región seleccionados
  • Análisis: Hacer un seguimiento de las páginas visitadas y de la interacción en las mismas
  • Análisis: Hacer un seguimiento de la ubicación y la región según la dirección IP
  • Análisis: Hacer un seguimiento del tiempo pasado en cada página
  • Análisis: Aumentar la calidad de los datos de las funciones estadísticas

Este sitio web no

  • Publicidad: Adaptar la información y la publicidad a sus intereses según, p.ej., el contenido que ha visitado antes. (Actualmente no usamos segmentación ni cookies de segmentación)
  • Publicidad: Recopilar información personalmente identificable como el nombre y la ubicación

Este sitio web

  • Funcionalidad: Recordar los ajustes de redes sociales
  • Funcionalidad: Recordar el país y la región seleccionados
  • Análisis: Hacer un seguimiento de las páginas visitadas y de la interacción en las mismas
  • Análisis: Hacer un seguimiento de la ubicación y la región según la dirección IP
  • Análisis: Hacer un seguimiento del tiempo pasado en cada página
  • Análisis: Aumentar la calidad de los datos de las funciones estadísticas
  • Publicidad: Adaptar la información y la publicidad a sus intereses según, p.ej., el contenido que ha visitado antes. (Actualmente no usamos segmentación ni cookies de segmentación)
  • Publicidad: Recopilar información personalmente identificable como el nombre y la ubicación

Este sitio web no

  • Recordar los datos de inicio de sesión
Guardar cerrar