Rutas
/
Elm
Elm
/
Ejercicios
/
¡Billete, por favor!
¡Billete, por favor!

¡Billete, por favor!

Ejercicio de aprendizaje

Introducción

Coincidencia de patrones

La coincidencia de patrones permite escribir código con ramificaciones expresivas y la desestructuración aporta una forma elegante de vincular valores a variables.

Coincidencia de patrones simple

La coincidencia de patrones puede vincular valores a variables o descartarlos con el comodín _, usando la instrucción case.

type Entity = Alien | Stranger (Maybe String) | Friend { name: String }

hello : Entity -> String
hello entity =
    case entity of
        -- Custom type variant
        Alien -> "Hello, you are not from around here are you?"
        -- Binding to a litteral value nested in Stranger
        Stranger (Just nametag) -> "Hello, erm... " ++ nametag ++ "."
        -- Discarding Friend's data
        Friend _ -> "Hi!"
        -- All other cases
        _ -> "Hello stranger!"

Desestructuración

La desestructuración puede vincular valores en enlaces let, en argumentos de funciones y, por supuesto, en expresiones case, siempre que solo haya una forma posible para los datos.

pairSum : ( Int, Int ) -> Int
pairSum pair =
    -- Destructuring of a pair in a 'let' binding
    let ( x, y ) = pair
    in x + y

-- Destructuring in the function argument
pairSum : ( Int, Int ) -> Int
pairSum ( x, y ) = x + y

-- Custom type containing a single variant
type Container = Box String

-- Destructuring in the function argument
unbox : Container -> String
unbox (Box str) = str

-- Destructuring combined with pattern matching
unboxMaybe : Maybe Container -> Maybe String
unboxMaybe maybeContainer =
    case maybeContainer of
        Nothing -> Nothing
        Just (Box "42") -> Just "The answer to the universe!"
        Just (Box str) -> Just str

La desestructuración también se puede usar con registros o con la palabra clave as.

type alias Circle =
    { radius : Float
    , center : ( Float, Float )
    }

perimeter : Circle -> Float
perimeter { radius } =
    2 * pi * radius

left : Circle -> Float
left { radius, center } =
    -- the pair center cannot be pattern matched directly in the function argument
    -- so we do it in a 'let' statement
    let ( x, _ ) = center
    in x - radius

-- using the 'as' keyword to bind both the fields and the whole record
smaller : Float -> Circle -> Circle
smaller reduction ({ radius } as circle) =
    if reduction < radius then
        { circle | radius = radius - reduction }
    else
        circle

Instrucciones

Formas parte del servicio de asistencia técnica y quieres mejorar el sistema de tickets para que sea más eficiente y poder proporcionar estadísticas a tu jefa.

Un ticket tiene un estado (nuevo, en curso...), un creador (identificado por un nombre de usuario y un identificador de empleado), se puede asignar a un empleado de TI y contiene un historial de comentarios.

Aquí tienes cuatro tareas que mejorarán tu sistema de tickets actual.

1. Detectar comentarios vacíos

Los comentarios vacíos saturan la interfaz y no aportan ninguna información, así que quieres filtrarlos.

Define una función auxiliar emptyComment que reciba un par usuario/comentario y devuelva True para los comentarios vacíos.

Usa la desestructuración para extraer el usuario y el comentario directamente en el argumento de la función. Ignora el usuario, ya que no necesitas esa información.

emptyComment ( User "Alice", "" )
-- => True

2. Contar el número de comentarios del creador

Tu jefa quiere tener estadísticas sobre la participación de los usuarios en el proceso de tickets. Te pide que compruebes cuántos comentarios añade el creador del ticket.

Define numberOfCreatorComments que recibe un ticket y devuelve el número de comentarios añadidos por el creador del ticket.

Usa la desestructuración en el argumento de la función para extraer el registro del tipo Ticket, a la vez que los campos que necesitas del registro. Después, desestructura createdBy en un enlace let para poder contar los comentarios correspondientes. Usa funciones de List para hacer el recuento y usa la desestructuración en el argumento de la función de una función anónima para separar el par usuario/comentario.

numberOfCreatorComments
numberOfCreatorComments
    (Ticket
        { status = Closed
        , createdBy = ( User "Chiaki", 1 )
        , assignedTo = Nothing
        , comments = [ ( User "Chiaki", "Never mind, fixed it." ) ]
        }
    )
-- => 1

3. Detectar tickets asignados al equipo de desarrollo

Algunos tickets tienen que escalarse a Alice, Bob o Charlie del equipo de desarrollo. Es importante vigilar esos para asegurarte de que avanzan.

Define una función auxiliar assignedToDevTeam que compruebe si un ticket está asignado a uno de los miembros del equipo de desarrollo.

Usa la desestructuración en el argumento de la función para extraer el registro del tipo Ticket, así como el campo que necesitas. Después, usa una única expresión case para comprobar si el ticket está asignado a Alice, Bob o Charlie usando coincidencia de patrones recursiva para extraer sus nombres de usuario y coincidencia de patrones literal para hacerlos coincidir.

assignedToDevTeam
    (Ticket
        { status = InProgress
        , createdBy = ( User "Bill", 2 )
        , assignedTo = Just (User "Alice")
        , comments = [ ( User "Bill", "What's an 'undefined'?" ) ]
        }
    )
-- => True

4. Asignar tickets a empleados de TI

A veces hay un montón de tickets que hay que reasignar a otros empleados de TI.

Define una función assignTicketTo que te ayude a hacerlo. La función recibe dos argumentos: un usuario al que asignar el ticket y un ticket. Si el estado del ticket es New, asígnalo al nuevo usuario y cambia el estado a InProgress. Para otros estados, simplemente reasigna el ticket al nuevo usuario, excepto los tickets con el estado Archived, que no se deben modificar en absoluto.

Usa la desestructuración en el argumento de la función para extraer el registro del tipo Ticket y también el campo que necesitas, y usa asimismo la palabra clave as para capturar el registro completo tal y como está. Usa una única expresión case para hacer coincidir el patrón del estado y devolver el ticket correspondiente, creado a partir de la modificación del registro original que capturaste con la palabra clave as.

assignTicketTo (User "Danny")
    (Ticket
        { status = New
        , createdBy = ( User "Jesse", 3 )
        , assignedTo = Just (User "Alice")
        , comments = [ ( User "Jesse", "I've been waiting for 6 months!!" ) ]
        }
    )
-- => Ticket
--        { status = InProgress
--        , createdBy = ( User "Jesse", 3 )
--        , assignedTo = Just (User "Danny")
--        , comments = [ ( User "Jesse", "I've been waiting for 6 months!!" ) ]
--        }
Editar en GitHub El enlace se abre en una ventana o pestaña nueva
Elm Exercism

¿Listo para empezar ¡Billete, por favor!?

Regístrate en Exercism para aprender y dominar Elm con 28 conceptos110 ejercicios y mentoría humana real, todo gratis.