Tracks
/
Swift
Swift
/
Ejercicios
/
Líneas de registro
Líneas de registro

Líneas de registro

Ejercicio de aprendizaje

Introducción

Cuando modelas datos que solo pueden tomar un conjunto específico de estados posibles, como los días de la semana, las direcciones de una brújula o los botones de un control, los tipos básicos como Int o String tienen grandes desventajas. Con enteros o strings, tu código debe verificar constantemente si hay valores inválidos (como un código de estado 999 o un error de escritura como "leftt"), y las personas que leen el código no pueden saber fácilmente qué representan los números.

Swift resuelve este problema con las enumeraciones (a menudo abreviadas como enums). Un enum define un tipo común para un grupo de valores relacionados y con nombre. Como el compilador conoce de antemano todos los casos posibles, puede verificar la exactitud y la exhaustividad de tu código en tiempo de compilación. Los enums también pueden tener métodos, inicializadores y propiedades calculadas.

Cómo definir enums

Define un enum con la palabra clave enum seguida del nombre del tipo, y lista sus casos entre llaves. Por convención de Swift, el nombre del tipo usa UpperCamelCase, mientras que cada caso usa lowerCamelCase:

enum NESButton {
    case up
    case down
    case left
    case right
    case a
    case b
    case select
    case start
}

También puedes definir varios casos en una sola línea, separados por comas:

enum NESButton {
    case up, down, left, right, a, b, select, start
}

Para referirte a un caso de un enum, escribe el nombre del tipo del enum, un punto (.) y el nombre del caso. Cuando el tipo ya se conoce o el compilador puede inferirlo, puedes omitir el nombre del tipo y usar la sintaxis de punto más corta:

var lastPressed = NESButton.up

// Swift infers the type, so you can omit the type name:
lastPressed = .down

let konamiCode: [NESButton] = [.up, .up, .down, .down, .left, .right, .left, .right, .b, .a]

Métodos e inicializadores

Los enums pueden definir métodos e inicializadores personalizados igual que las clases y las estructuras. Dentro de un método de un enum, self se refiere al valor del caso actual:

enum Coin {
    case heads
    case tails

    init(_ value: Int) {
        if value.isMultiple(of: 2) {
            self = .heads
        } else {
            self = .tails
        }
    }

    func flip() -> Coin {
        switch self {
        case .heads: return .tails
        case .tails: return .heads
        }
    }
}

let tails = Coin(13)     // .tails
let heads = Coin(0)      // .heads
let flipped = heads.flip() // .tails

Valores brutos

Los casos de un enum pueden venir con valores predeterminados llamados valores brutos. Todos los valores brutos de un enum deben compartir el mismo tipo (como Int, String o Character):

enum NESButton: Character {
    case up = "⬆️"
    case down = "⬇️"
    case left = "⬅️"
    case right = "➡️"
    case a = "🅰️"
    case b = "🅱️"
    case select = "✅"
    case start = "🚦"
}

print(NESButton.left.rawValue) // Prints "⬅️"

Puedes inicializar un enum a partir de un valor bruto usando init(rawValue:). Como es posible que se proporcione un valor bruto inválido, este inicializador devuelve un opcional:

let upButton = NESButton(rawValue: "⬆️") // Optional(NESButton.up)
let invalid = NESButton(rawValue: "🙄")  // nil

Swift puede asignar valores brutos automáticamente para los enums de String y de Int:

  • En los enums de String, el valor bruto de cada caso es su nombre de caso de forma predeterminada.
  • En los enums de Int, los valores brutos empiezan en 0 y aumentan de 1 en 1, salvo que se especifique lo contrario.
enum Planet: Int {
    case mercury = 1, venus, earth, mars
}

print(Planet.earth.rawValue) // Prints 3

Instrucciones

En este ejercicio vas a procesar líneas de log.

Cada línea de log es una cadena con el siguiente formato: "[<LVL>]: <MESSAGE>".

Estos son los diferentes niveles de log:

  • TRC (trace)
  • DBG (debug)
  • INF (info)
  • WRN (warning)
  • ERR (error)
  • FTL (fatal)

Tienes tres tareas, y cada una debe completarse para proporcionar la funcionalidad necesaria.

1. Crea la enumeración LogLevel

Define una enumeración LogLevel que tenga seis casos correspondientes a los niveles de log anteriores, más un caso desconocido para los niveles faltantes o no estándar.

  • trace
  • debug
  • info
  • warning
  • error
  • fatal
  • unknown

2. Analiza el nivel de log

Ahora implementa el inicializador de LogLevel para analizar el nivel de log de una línea de log:

LogLevel("[INF]: File deleted")
// Returns LogLevel.info
LogLevel("Something went wrong!")
// Returns LogLevel.unknown

3. Convierte la línea de log al formato corto

El nivel de log de una línea de log es bastante verboso. Para reducir el espacio en disco que se necesita para almacenar las líneas de log, se desarrolló un formato corto: "<ENCODED_LEVEL>:<MESSAGE>".

El nivel de log codificado es un simple mapeo de un nivel de log a un número:

  • trace - 0
  • debug - 1
  • info - 4
  • warning - 5
  • error - 6
  • fatal - 7
  • unknown - 42

Implementa el método shortFormat(message: String) -> String, que devuelve la línea de log en formato corto como un String:

let overflow = LogLevel.error
overflow.shortFormat(message: "Stack overflow")
// Returns "6:Stack overflow"
Editar en GitHub El enlace se abre en una ventana o una pestaña nuevas
Swift Exercism

¿Todo listo para empezar Líneas de registro?

Regístrate en Exercism para aprender y dominar Swift con 35 conceptos116 ejercicios y mentoría humana real, todo gratis.