Rutas
/
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 concreto de estados posibles, como los días de la semana, los puntos cardinales o los botones de un mando, los tipos básicos como Int o String tienen grandes inconvenientes. Con enteros o strings, tu código tiene que estar comprobando constantemente si hay valores no válidos (como un código de estado 999 o una errata como "leftt"), y a quien lee el código le cuesta saber qué representan los números.

Swift resuelve este problema con las enumeraciones (a menudo abreviadas como enum). Una enumeración 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 comprobar que tu código es correcto y está completo en tiempo de compilación. Las enumeraciones también pueden tener métodos, inicializadores y propiedades calculadas.

Definir enumeraciones

Define una enumeración con la palabra clave enum seguida del nombre del tipo, con sus casos indicados dentro de llaves. Por convención en 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 una enumeración, escribe el nombre del tipo de la enumeración, un punto (.) y el nombre del caso. Cuando el compilador ya conoce el tipo o puede inferirlo, puedes omitir el nombre del tipo y usar la sintaxis abreviada con el punto:

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

Las enumeraciones pueden definir métodos e inicializadores personalizados igual que las clases y las estructuras. Dentro de un método de una enumeración, self hace referencia 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 una enumeración se pueden rellenar de antemano con valores predeterminados llamados valores brutos. Todos los valores brutos de una enumeración 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 una enumeración a partir de un valor bruto con init(rawValue:). Como es posible que se proporcione un valor bruto no válido, este inicializador devuelve un opcional:

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

Swift puede asignar automáticamente los valores brutos de las enumeraciones de tipo String e Int:

  • En las enumeraciones de tipo String, el valor bruto de cada caso es su propio nombre de caso de forma predeterminada.
  • En las enumeraciones de tipo Int, los valores brutos empiezan en 0 y se incrementan de 1 en 1, a menos que se indique 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 registro.

Cada línea de registro es un string con el siguiente formato: "[<LVL>]: <MESSAGE>".

Estos son los distintos niveles de registro:

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

Tienes tres tareas, y debes completar cada una de ellas 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 registro anteriores, más un caso desconocido para niveles ausentes o no estándar.

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

2. Analiza el nivel de registro

A continuación, implementa el inicializador de LogLevel para analizar el nivel de registro de una línea de registro:

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

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

El nivel de registro de una línea de registro es bastante verboso. Para reducir el espacio en disco necesario para almacenar las líneas de registro, se ha desarrollado un formato corto: "<ENCODED_LEVEL>:<MESSAGE>".

El nivel de registro codificado es una simple asignación de un nivel de registro 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 registro 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 pestaña nueva
Swift Exercism

¿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.