Tracks
/
Elm
Elm
/
Ejercicios
/
Subirse al carro
Subirse al carro

Subirse 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 de JavaScript o Java, o a las structs de C o Rust, pero con algunas diferencias clave.

Crear registros

Los registros se crean con llaves y sus elementos se separan con 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 de igual = se reemplazan 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 type alias para compartir la definición es algo habitual.

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

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

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

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

Acceder 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 con un punto ., como .creator, que funcionan en cualquier registro que tenga un campo con ese nombre. Esa es la segunda excepción a la regla de que las funciones deben empezar con un carácter minúsculo. De hecho, las funciones definidas por el usuario deben empezar con un carácter minúsculo, pero los dos ejemplos que acabamos de ver los genera el compilador, no quien programa.

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

firefly.name
    --> "Firefly"

.creator firefly
    --> "Joss Whedon"

Los registros también se pueden desestructurar al vincular valores usando la coincidencia de patrones de registros. La desestructuración funciona con cualquier registro que tenga campos con los nombres relevantes.

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

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

Actualizar 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 más 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 }

Comparar registros

Elm usa la [igualdad estructural][equality], 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 un campo y, funcionará con cualquier registro que tenga esos campos, como puntos en 2D, puntos en 3D, naves espaciales, etc. Esos tipos de registro tienen una barra vertical | en su definición, como { a | x : Float, y : Float }, y se llaman «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 te apasionan los deportes y acabas de descubrir tu pasión por el básquetbol de la NBA. Como eres nuevo en el básquetbol de la NBA, te estás sumergiendo en la historia de la NBA, llevando un registro de equipos, 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 determinar si deberías apoyar a un equipo en particular. Tienes siete tareas que te ayudarán a desarrollar tu propio algoritmo root-for-a-team.

1. Define el modelo

Define el alias de tipo Coach para un registro con los siguientes dos campos, en el siguiente 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 siguientes dos campos, en el siguiente orden:

  • wins: la cantidad de victorias, de tipo Int.
  • losses: la cantidad de derrotas, de tipo Int.

Define el alias de tipo Team para un registro con los siguientes tres campos, en el siguiente 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 interactuar 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. Agrega una función createTeam con la siguiente firma String -> Stats -> Coach -> Team.

3. Reemplaza al entrenador

Como los dueños de la NBA son impacientes, descubriste que los malos resultados del equipo a menudo hacían que se reemplazara 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 apoyar a un equipo

En el futuro planeas crear un algoritmo complicado para decidir si apoyar a un equipo o no, pero para el primer intento has decidido que deberías apoyar 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 de tipo para aceptar cualquier registro que tenga los campos relevantes. Para que la función sea lo más concisa posible, quieres usar coincidencia de patrones para obtener los stats del parámetro de la función. Implementa la función rootForTeam que toma un equipo y devuelve True si deberías apoyar a ese equipo; de lo 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 una pestaña nuevas
Elm Exercism

¿Todo listo para empezar Subirse al carro?

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