Rutas
/
Elm
Elm
/
Ejercicios
/
Subido al carro
Subido al carro

Subido al carro

Ejercicio de aprendizaje

Introducción

Registros

Los registros son estructuras de datos que agrupan información relacionada con etiquetas. Son similares a los objetos en JavaScript o Java, o a los structs en C o Rust, pero con algunas diferencias clave.

Creación de registros

Los registros se crean con llaves y sus elementos se separan por comas.

firefly =
    { name = "Firefly"
    , creator = "Joss Whedon"
    , episodes = 14
    }

El tipo de un registro también se define con una sintaxis similar, excepto que los signos igual = se sustituyen por dos puntos :.

firefly : { name : String, creator : String, episodes : Int }
firefly =
    { name = "Firefly"
    , creator = "Joss Whedon"
    , episodes = 14
    }

Repetir estas definiciones de tipo es engorroso, así que usar un alias de tipo para compartir la definición es una práctica común.

type alias TvSeries =
    { name : String
    , creator : String
    , episodes : Int
    }

firefly : TvSeries
firefly =
    { name = "Firefly"
    , creator = "Joss Whedon"
    , episodes = 14
    }

El alias de tipo también proporciona automáticamente una función constructora para el registro. Esto a veces sorprende, ya que las funciones en Elm deben empezar por un carácter en minúscula, pero los constructores de tipo son una excepción.

firefly : TvSeries
firefly = TvSeries "Firefly" "Joss Whedon" 14

Acceso a los campos de un registro

La forma principal de acceder al valor de un campo de una instancia de registro es usar la notación de punto, como firefly.creator. El compilador de Elm también admite funciones de acceso especiales que empiezan por un punto ., como .creator, que funcionan con cualquier registro que tenga un campo con ese nombre. Esa es la segunda excepción a la regla de que las funciones deben empezar por un carácter en minúscula. De hecho, las funciones definidas por el usuario deben empezar por un carácter en minúscula, pero los dos ejemplos que acabamos de descubrir los genera el compilador, no el programador.

firefly : TvSeries
firefly =
    { name = "Firefly"
    , creator = "Joss Whedon"
    , episodes = 14
    }

firefly.name
    --> "Firefly"

.creator firefly
    --> "Joss Whedon"

Los registros también se pueden desestructurar en vinculaciones usando la coincidencia de patrones de registros. La desestructuración funciona con cualquier registro que tenga campos con los nombres correspondientes.

episodesCount : TvSeries -> Int
episodesCount { episodes } =
    episodes

complicatedCopy : TvSeries -> TvSeries
complicatedCopy show =
    let
        { name, creator } = show
    in
    { name = name
    , creator = creator
    , episodes = episodesCount show
    }

Actualización de registros

Los registros son inmutables, como todo en Elm, así que una vez que se define un registro, los valores de sus campos nunca pueden cambiar. Existe una sintaxis especial para crear una copia de un registro existente, pero cambiando uno o varios campos. Esta sintaxis usa el símbolo de barra vertical | para distinguir el registro original y los campos que cambiarán, como { oldRecord | field1 = newValue }.

firefly : TvSeries
firefly =
    { name = "Firefly"
    , creator = "Joss Whedon"
    , episodes = 14
    }

updatedFirefly : TvSeries
updatedFirefly =
    { firefly | creator = "J Whedon", episodes = 15 }

Comparación de registros

Elm usa la igualdad estructural, lo que significa que dos instancias del mismo registro con valores idénticos son iguales.

firefly1 = TvSeries "Firefly" "Joss Whedon" 14
firefly2 = TvSeries "Firefly" "Joss Whedon" 14

firefly1 == firefly2
    --> True

Registros extensibles

Elm también admite el tipado estructural, lo que significa que si una función requiere un registro con un campo x y otro y, funcionará con cualquier registro que tenga esos campos, como puntos 2D, puntos 3D, naves espaciales, etc. Esos tipos de registro tienen una barra vertical | en su definición, como { a | x : Float, y : Float }, y se denominan «registros extensibles» en la terminología de Elm. Ten cuidado con la diferencia entre una barra vertical | en una definición de tipo, que es una definición de registro extensible ({ a | x : Int }), y una barra vertical | en una instancia de registro real, que significa que estamos actualizando algunos campos de ese registro.

point2d = { x = 1, y = 2 }
point3d = { x = 3, y = 4, z = 7 }

.x point2d --> 1
.x point3d --> 3

length : { a | x : Float, y : Float } -> Float
length vector =
    sqrt (vector.x * vector.x + vector.y * vector.y)

length point2d --> 2.236068
length point3d --> 5

translateX : { a | x : Float } -> { a | x : Float }
translateX vector =
    { vector | x = vector.x + 1 }

translateX point2d --> { x = 2, y = 2 }
translateX point3d --> { x = 4, y = 4, z = 7 }

Instrucciones

En este ejercicio eres un gran aficionado al deporte y acabas de descubrir tu pasión por el baloncesto de la NBA. Como eres nuevo en el baloncesto de la NBA, te estás sumergiendo a fondo en la historia de la NBA, haciendo un seguimiento de los equipos, los entrenadores y sus estadísticas de victorias y derrotas, y comparándolos entre sí.

Como todavía no tienes un equipo favorito, también vas a desarrollar un algoritmo para averiguar si merece la pena animar a un equipo en concreto. Tienes siete tareas que te ayudarán a desarrollar tu propio algoritmo anima a un equipo.

1. Define el modelo

Define el alias de tipo Coach para un registro con los dos campos siguientes, en este orden:

  • name: el nombre del entrenador, de tipo String.
  • formerPlayer: indica si el entrenador fue jugador anteriormente, de tipo Bool.

Define el alias de tipo Stats para un registro con los dos campos siguientes, en este orden:

  • wins: el número de victorias, de tipo Int.
  • losses: el número de derrotas, de tipo Int.

Define el alias de tipo Team para un registro con los tres campos siguientes, en este orden:

  • name: el nombre del equipo, de tipo String.
  • coach: el entrenador del equipo, de tipo Coach.
  • stats: las estadísticas del equipo, de tipo Stats.

2. Crea un equipo

Quieres comunicarte con código de terceros que tiene el concepto de equipo, pero que llama a tu código con los parámetros en un orden diferente. Añade una función createTeam con la siguiente firma String -> Stats -> Coach -> Team.

3. Sustituye al entrenador

Como los propietarios de la NBA son impacientes, has descubierto que los malos resultados del equipo a menudo llevaban a que se sustituyera al entrenador. Implementa la función replaceCoach, que toma el nuevo entrenador y el equipo como parámetros y devuelve el equipo, pero con el nuevo entrenador:

let
    coach = { name = "Larry Bird", formerPlayer = True }
    stats = { wins = 58, losses =  24 }
    team = { name = "Indiana Pacers", coach = coach, stats =  stats }
    newCoach = { name = "Isiah Thomas", formerPlayer = True }
in
replaceCoach newCoach team
--> { name = "Indiana Pacers"
--  , coach = { name = "Isiah Thomas", formerPlayer = True }
--  , stats = { wins = 58, losses = 24 } }

4. Comprueba si deberías animar a un equipo

En el futuro tienes pensado idear un algoritmo complicado para decidir si merece la pena animar a un equipo o no, pero para este primer intento has decidido que deberías animar a cualquier equipo que tenga más victorias que derrotas.

Quieres que esta función sea reutilizable en otros contextos, así que usa un registro extensible en la firma del tipo para aceptar cualquier registro que tenga los campos relevantes. Para que la función sea lo más concisa posible, quieres usar la coincidencia de patrones para obtener stats del parámetro de la función. Implementa la función rootForTeam, que toma un equipo y devuelve True si deberías animar a ese equipo; en caso contrario, devuelve False.

let
    spursCoach = { name = "Gregg Popovich", formerPlayer =  False }
    spursStats = { wins = 56, losses = 26 }
    spursTeam = { name = "San Antonio Spurs", coach = spursCoach, stats = spursStats }
in
rootForTeam spursTeam
--> True
Editar en GitHub El enlace se abre en una ventana o pestaña nueva
Elm Exercism

¿Listo para empezar Subido al carro?

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