Aprendiendo Elm con un secuenciador de batería (Parte 1)

 

 

 

  • Implemente rápidamente. Implementar inteligentemente
  • Register!

  • Índice
    1. Empezando con el olmo
    2. Modelado de datos con tipos
      1. Modelando nuestra aplicación en JavaScript
    3. Modelado con tipos en Elm
    4. Usando la arquitectura Elm
      1. Inicializando nuestra aplicación
      2. Representando nuestra aplicación
      3. Actualización del estado de la aplicación

    Escribir en un nuevo idioma requiere tiempo y práctica. El desarrollador front-end Brian Holt guía a los lectores en la construcción de un secuenciador de batería en Elm. En la primera parte de esta serie de dos partes, analizará los conceptos fundamentales de Elm, es decir, cómo comenzar, usar tipos, representar vistas y actualizar el estado. Aprenderá a trabajar con la arquitectura Elm para crear aplicaciones sencillas.

     

    Si es un desarrollador front-end que sigue la evolución de las aplicaciones de una sola página (SPA) , es probable que haya oído hablar de Elm, el lenguaje funcional que inspiró Redux . Si no lo ha hecho, es un lenguaje de compilación en JavaScript comparable con proyectos SPA como React , Angular y Vue .

    Al igual que estos, gestiona los cambios de estado a través de su dominio virtual con el objetivo de hacer que el código sea más fácil de mantener y con mejor rendimiento . Se centra en la felicidad de los desarrolladores, herramientas de alta calidad y patrones simples y repetibles. Algunas de sus diferencias clave incluyen mensajes de error maravillosamente útiles , escritos estáticamente y que es un lenguaje funcional (a diferencia del orientado a objetos).

    Mi introducción se produjo a través de una charla dada por Evan Czaplicki, el creador de Elm, sobre su visión de la experiencia del desarrollador front-end y, a su vez, la visión de Elm. Como alguien también se centró en la mantenibilidad y usabilidad del desarrollo front-end, su charla realmente me impactó. Probé Elm en un proyecto paralelo hace un año y sigo disfrutando de sus características y desafíos como no lo había hecho desde que comencé a programar; Soy un principiante de nuevo. Además, puedo aplicar muchas de las prácticas de Elm en otros idiomas.

    Desarrollar la conciencia de la dependencia

    Las dependencias están en todas partes. Al reducirlos, puede mejorar la probabilidad de que su sitio sea utilizable por la mayor cantidad de personas en la más amplia variedad de escenarios.Leer un artículo relacionado →

     

    En este artículo de dos partes, crearemos un secuenciador por pasos para programar ritmos de batería en Elm y, al mismo tiempo, mostraremos algunas de las mejores características del lenguaje. Hoy, analizaremos los conceptos fundamentales de Elm, es decir, cómo comenzar, usar tipos, representar vistas y actualizar el estado. La segunda parte de este artículo profundizará en temas más avanzados, como el manejo sencillo de grandes refactorizaciones, la configuración de eventos recurrentes y la interacción con JavaScript.

    Juega con el proyecto final aquí y consulta su código aquí .

    Así es como se verá el secuenciador de pasos completo en acción.

    Empezando con el olmo

    Para seguir este artículo, recomiendo usar Ellie , una experiencia para desarrolladores de Elm en el navegador. No necesita instalar nada para ejecutar Ellie y puede desarrollar aplicaciones completamente funcionales en él. Si prefiere instalar Elm en su computadora, la mejor manera de configurarlo es siguiendo la guía oficial de introducción .

    A lo largo de este artículo, vincularé las versiones de Ellie en proceso, aunque desarrollé el secuenciador localmente. Y aunque CSS se puede escribir completamente en Elm , escribí este proyecto en PostCSS . Esto requiere un poco de configuración en Elm Reactor para el desarrollo local para poder cargar los estilos. En aras de la brevedad, no abordaré los estilos en este artículo, pero los enlaces de Ellie incluyen todos los estilos CSS minimizados.

    Elm es un ecosistema autónomo que incluye:

    • Elm Make
      Para compilar su código Elm. Si bien Webpack sigue siendo popular para producir proyectos de Elm junto con otros activos, no es necesario. En este proyecto, opté por excluir Webpack y confiar en él elm makepara compilar el código.
    • Paquete Elm
      Un administrador de paquetes comparable a NPM para usar paquetes/módulos creados por la comunidad.
    • Elm Reactor
      Para ejecutar un servidor de desarrollo de compilación automática. Lo más notable es que incluye el depurador de viajes en el tiempo , lo que facilita recorrer los estados de su aplicación y reproducir errores.
    • Elm Repl
      Para escribir o probar expresiones simples de Elm en la terminal.

    Se consideran todos los archivos de Elm modules. Las líneas iniciales de cualquier archivo incluirán el module FileName exposing (functions)nombre FileNameliteral del archivo y functionslas funciones públicas que desea que sean accesibles a otros módulos. Inmediatamente después de la definición del módulo se importan desde módulos externos. El resto de funciones siguen.

     

    module Main exposing (main) import Html exposing (Html, text) main : Html msg main = text "Hello, World!"

    Este módulo, llamado Main.elm, expone una única función maine importa Htmly textdesde el Htmlmódulo/paquete. La mainfunción consta de dos partes: la anotación de tipo y la función real. Las anotaciones de tipo pueden considerarse definiciones de funciones. Indican los tipos de argumentos y el tipo de retorno. En este caso, el nuestro indica que la mainfunción no toma argumentos y devuelve Html msg. La función en sí representa un nodo de texto que contiene "Hola, mundo". Para pasar argumentos a una función, agregamos nombres separados por espacios antes del signo igual en la función. También agregamos los tipos de argumentos a la anotación de tipo, en el orden de los argumentos, seguido de una flecha.

    add2Numbers : Int - Int - Int add2Numbers first second = first + second

    En JavaScript, una función como esta es comparable:

    function add2Numbers(first, second) { return first + second; }

    Y en un lenguaje mecanografiado, como TypeScript, se ve así:

    function add2Numbers(first: number, second: number): number { return first + second; }

    add2Numberstoma dos números enteros y devuelve un número entero. El último valor de la anotación es siempre el valor de retorno porque cada función debe devolver un valor. Llamamos add2Numberscon 2 y 3 para obtener 5 como add2Numbers 2 3.

    Así como vincula los componentes de React, debemos vincular el código Elm compilado al DOM. La forma estándar de vincular es llamar embed()a nuestro módulo y pasarle el elemento DOM.

    script const container = document.getElementById('app'); const app = Elm.Main.embed(container); script

    Aunque nuestra aplicación realmente no hace nada, tenemos suficiente para compilar nuestro código Elm y representar texto. Compruébalo en Ellie e intenta cambiar los argumentos a add2Numbersla línea 26.

    Nuestra aplicación Elm básica que muestra números agregados en la pantalla.

    Modelado de datos con tipos

    Al provenir de un lenguaje de tipado dinámico como JavaScript o Ruby, los tipos pueden parecer superfluos. Esos lenguajes determinan qué tipo toman las funciones del valor que se pasa durante el tiempo de ejecución. La escritura de funciones generalmente se considera más rápida, pero se pierde la seguridad de garantizar que las funciones puedan interactuar adecuadamente entre sí.

    Por el contrario, Elm tiene un tipo estático. Depende de su compilador para garantizar que los valores pasados ​​a las funciones sean compatibles antes del tiempo de ejecución. Esto significa que no habrá excepciones de tiempo de ejecución para sus usuarios y es la forma en que Elm puede garantizar su garantía de “no excepciones de tiempo de ejecución”. Mientras que los errores tipográficos en muchos compiladores pueden ser especialmente crípticos, Elm se centra en hacerlos fáciles de entender y corregir .

     

    Elm hace que comenzar con los tipos sea muy amigable. De hecho, la inferencia de tipos de Elm es tan buena que puedes saltarte la escritura de anotaciones hasta que te sientas más cómodo con ellas. Si eres nuevo en el mundo de los tipos, te recomiendo que confíes en las sugerencias del compilador en lugar de intentar escribirlas tú mismo.

    Comencemos a modelar nuestros datos usando tipos. Nuestro secuenciador por pasos es una línea de tiempo visual de cuándo debe reproducirse una muestra de batería en particular. La línea de tiempo consta de pistas , a cada una de las cuales se le asigna una muestra de batería específica y la secuencia de pasos . Un paso puede considerarse un momento en el tiempo o un latido. Si un paso está activo , la muestra debe activarse durante la reproducción, y si el paso está inactivo , la muestra debe permanecer en silencio. Durante la reproducción, el secuenciador se moverá a través de cada paso reproduciendo las muestras de los pasos activos. La velocidad de reproducción se establece en Beats Per Minute (BPM) .

    Una captura de pantalla de nuestra aplicación final, compuesta por pistas con secuencias de pasos.

    Modelando nuestra aplicación en JavaScript

    Para tener una mejor idea de nuestros tipos, consideremos cómo modelar este secuenciador de batería en JavaScript. Hay una variedad de pistas. Cada objeto de pista contiene información sobre sí mismo: el nombre de la pista, la muestra/clip que se activará y la secuencia de valores de pasos.

    tracks: [ { name: "Kick", clip: "kick.mp3", sequence: [On, Off, Off, Off, On, etc...] }, { name: "Snare", clip: "snare.mp3", sequence: [Off, Off, Off, Off, On, etc...] }, etc... ]

    Necesitamos administrar el estado de reproducción entre reproducción y parada.

     playback: "playing" || "stopped"

    Durante la reproducción, debemos determinar qué paso se debe reproducir. También deberíamos considerar el rendimiento de la reproducción y, en lugar de recorrer cada secuencia en cada pista cada vez que se incrementa un paso; deberíamos reducir todos los pasos activos en una única secuencia de reproducción. Cada colección dentro de la secuencia de reproducción representa todas las muestras que se deben reproducir. Por ejemplo, ["kick", "hat"]significa que deben reproducirse las muestras de bombo y charles, mientras que ["hat"]significa que solo debe reproducirse el charles. También necesitamos que cada colección restrinja la unicidad de la muestra, para no terminar con algo como ["hat", "hat", "hat"].

    playbackPosition: 1 playbackSequence: [ ["kick", "hat"], [], ["hat"], [], ["snare", "hat"], [], ["hat"], [], ... ],

    Y necesitamos marcar el ritmo de reproducción, o los BPM.

    bpm: 120

    Modelado con tipos en Elm

    Transcribir estos datos en tipos de Elm es esencialmente describir de qué esperamos que estén hechos nuestros datos. Por ejemplo, ya nos referimos a nuestro modelo de datos como modelo , por lo que lo llamamos así con un alias de tipo . Los alias de tipo se utilizan para facilitar la lectura del código. No son un tipo primitivo como un booleano o un número entero; son simplemente nombres que le damos a un tipo primitivo o estructura de datos. Usando uno, definimos cualquier dato que siga la estructura de nuestro modelo como un modelo en lugar de una estructura anónima. En muchos proyectos de Elm, la estructura principal se denomina Modelo.

     

    type alias Model = { tracks : Array Track , playback : Playback , playbackPosition : PlaybackPosition , bpm : Int , playbackSequence : Array (Set Clip) }

    Aunque nuestro modelo se parece un poco a un objeto JavaScript, describe un Elm Record . Los registros se utilizan para organizar datos relacionados en varios campos que tienen sus propias anotaciones de tipo. Es fácil acceder a ellos usando field.attributey fáciles de actualizar, lo cual veremos más adelante. Los objetos y registros son muy similares, con algunas diferencias clave:

    • No se pueden llamar campos inexistentes
    • Los campos nunca serán nulloundefined
    • thisy selfno se puede usar

    Nuestra colección de pistas puede estar compuesta por uno de tres tipos posibles: Listas, Arrays y Conjuntos. En resumen, las listas son colecciones de uso general no indexadas, las matrices están indexadas y los conjuntos solo contienen valores únicos. Necesitamos un índice para saber qué paso de pista se ha conmutado y, dado que las matrices están indexadas, es nuestra mejor elección. Alternativamente, podríamos agregar una identificación a la pista y filtrar desde una Lista.

    En nuestro modelo, hemos compuesto pistas en una matriz de track y otro registro: tracks : Array Track. La pista contiene información sobre sí misma. Tanto el nombre como el clip son cadenas, pero hemos escrito clip con alias porque sabemos que otras funciones harán referencia a él en otras partes del código. Al asignarle un alias, comenzamos a crear código autodocumentado. La creación de tipos y alias de tipos permite a los desarrolladores modelar el modelo de datos según el modelo de negocio, creando un lenguaje ubicuo.

    type alias Track = { name : String , clip : Clip , sequence : Array Step } type Step = On | Off type alias Clip = String

    Sabemos que la secuencia será una serie de valores de encendido/apagado. Podríamos configurarlo como una serie de valores booleanos, como sequence : Array Bool, ¡pero perderíamos la oportunidad de expresar nuestro modelo de negocio! Teniendo en cuenta que los secuenciadores de pasos están hechos de pasos , definimos un nuevo tipo llamado Paso . Un paso podría ser un alias de tipo para a boolean, pero podemos ir un paso más allá: los pasos tienen dos valores posibles, activado y desactivado, así es como definimos el tipo de unión . Ahora los pasos solo pueden estar activados o desactivados, lo que hace que todos los demás estados sean imposibles . Juguetes infantiles: Tienda Gormiti, Monster High, Trompos Cometa, BeyBlade, Bakugan y muchos más

    Definimos otro tipo para Playback, un alias para PlaybackPositiony usamos Clip cuando lo definimos playbackSequencecomo una matriz que contiene conjuntos de clips. BPM se asigna como estándar Int.

    type Playback = Playing | Stopped type alias PlaybackPosition = Int

    Si bien hay un poco más de gastos generales al comenzar con los tipos, nuestro código es mucho más fácil de mantener. Es autodocumentado y utiliza un lenguaje omnipresente en nuestro modelo de negocio. La confianza que ganamos al saber que nuestras funciones futuras interactuarán con nuestros datos de la manera que esperamos, sin necesidad de pruebas, bien vale el tiempo que lleva escribir una anotación. Y podríamos confiar en la inferencia de tipos del compilador para sugerir los tipos, de modo que escribirlos sea tan simple como copiar y pegar. Aquí está la declaración de tipo completa .

     

    Usando la arquitectura Elm

    La Arquitectura Elm es un patrón de gestión de estado simple que surgió naturalmente en el lenguaje. Crea un enfoque en torno al modelo de negocio y es altamente escalable. A diferencia de otros marcos SPA, Elm es obstinado acerca de su arquitectura: es la forma en que están estructuradas todas las aplicaciones, lo que hace que la incorporación sea muy sencilla. La arquitectura consta de tres partes:

    • El modelo , que contiene el estado de la aplicación y la estructura que escribimos, modelo alias.
    • La función de actualización , que actualiza el estado.
    • Y la función de vista , que representa el estado visualmente.

    Comencemos a construir nuestro secuenciador de batería aprendiendo la arquitectura de Elm en la práctica a medida que avanzamos. Comenzaremos inicializando nuestra aplicación, renderizando la vista y luego actualizando el estado de la aplicación. Al tener experiencia en Ruby, tiendo a preferir archivos más cortos y dividir mis funciones de Elm en módulos, aunque es muy normal tener archivos de Elm grandes . Creé un punto de partida en Ellie , pero localmente creé los siguientes archivos:

    • Types.elm, que contiene todas las definiciones de tipos
    • Main.elm, que inicializa y ejecuta el programa.
    • Update.elm, que contiene la función de actualización que gestiona el estado.
    • View.elm, que contiene código Elm para representar en HTML

    Inicializando nuestra aplicación

    Es mejor empezar poco a poco, por lo que reducimos el modelo para centrarnos en construir una única pista que contenga pasos que se activan y desactivan. Si bien ya creemos que conocemos toda la estructura de datos, comenzar poco a poco nos permite centrarnos en representar pistas como HTML. Reduce la complejidad y el código No lo necesitarás . Posteriormente, el compilador nos guiará en la refactorización de nuestro modelo. En el archivo Types.elm, mantenemos nuestros tipos de Paso y Clip pero cambiamos el modelo y la pista.

    type alias Model = { track : Track } type alias Track = { name : String , sequence : Array Step } type Step = On | Off type alias Clip = String

    Para representar Elm como HTML, utilizamos el paquete Elm Html . Tiene opciones para crear tres tipos de programas que se basan entre sí:

    • Programa para principiantes
      Un programa reducido que excluye efectos secundarios y es especialmente útil para aprender la arquitectura Elm.
    • Programa
      El programa estándar que maneja efectos secundarios, útil para trabajar con bases de datos o herramientas que existen fuera de Elm.
    • Programa con banderas
      Un programa extendido que puede inicializarse con datos reales en lugar de datos predeterminados.

    Es una buena práctica utilizar el tipo de programa más simple posible porque es fácil cambiarlo más adelante con el compilador. Esta es una práctica común al programar en Elm; Utilice sólo lo que necesite y cámbielo más tarde. Para nuestros propósitos, sabemos que debemos lidiar con JavaScript, que se considera un efecto secundario, por lo que creamos un archivo Html.program. En Main.elm necesitamos inicializar el programa pasando funciones a sus campos.

     

    main : Program Never Model Msg main = Html.program { init = init , view = view , update = update , subscriptions = always Sub.none }

    Cada campo del programa pasa una función a Elm Runtime, que controla nuestra aplicación. En pocas palabras, Elm Runtime:

    • Inicia el programa con nuestros valores iniciales de init.
    • Representa la primera vista pasando nuestro modelo inicializado a view.
    • Vuelve a representar continuamente la vista cuando se pasan mensajes updatedesde vistas, comandos o suscripciones.

    Localmente, nuestras funciones viewy updatese importarán desde View.elmy Update.elmrespectivamente, y las crearemos en un momento. subscriptionsEscuchamos los mensajes que provocan actualizaciones, pero por ahora los ignoramos asignando always Sub.none. Nuestra primera función, initinicializa el modelo. Piense en initlos valores predeterminados para la primera carga. Lo definimos con una única pista llamada “kick” y una secuencia de pasos Off. Como no obtenemos datos asincrónicos, ignoramos explícitamente los comandos para Cmd.noneinicializar sin efectos secundarios.

    init : ( Model, Cmd.Cmd Msg ) init = ( { track = { sequence = Array.initialize 16 (always Off) , name = "Kick" } } , Cmd.none )

    Nuestra anotación de tipo de inicio coincide con nuestro programa. Es una estructura de datos llamada tupla , que contiene un número fijo de valores. En nuestro caso, los Modelcomandos y. Por ahora, siempre ignoramos los comandos usando Cmd.nonehasta que estemos listos para manejar los efectos secundarios más adelante. ¡Nuestra aplicación no muestra nada, pero compila!

    Representando nuestra aplicación

    Construyamos nuestras opiniones. En este punto, nuestro modelo tiene una sola pista, por lo que eso es lo único que necesitamos renderizar. La estructura HTML debería verse así:

    div p class "track-title"Kick/p div button/button button/button button/button button/button etc... /div /div

    Construiremos tres funciones para representar nuestras vistas:

    1. Uno para renderizar una sola pista, que contiene el nombre de la pista y la secuencia.
    2. Otro para renderizar la secuencia misma.
    3. Y uno más para representar cada botón de paso individual dentro de la secuencia.

    Nuestra primera función de vista renderizará una sola pista. Confiamos en nuestra anotación de tipo, renderTrack : Track - Html Msgpara aplicar una única pista pasada. Usar tipos significa que siempre sabemos que renderTracktendrá una pista. No necesitamos verificar si el namecampo existe en el registro o si hemos pasado una cadena en lugar de un registro. Elm no compilará si intentamos pasar algo que no Tracksea renderTrack. Aún mejor, si cometemos un error y accidentalmente intentamos pasar algo más que una pista a la función, el compilador nos dará mensajes amigables para indicarnos la dirección correcta.

     

    renderTrack : Track - Html Msg renderTrack track = div [ class "track" ] [ p [ class "track-title" ] [ text track.name ] , div [ class "track-sequence" ] (renderSequence track.sequence) ]

    Puede parecer obvio, pero todo Elm es Elm, incluida la escritura HTML. No existe un lenguaje de plantillas ni una abstracción para escribir HTML: todo es Elm. Los elementos HTML son funciones de Elm, que toman el nombre, una lista de atributos y una lista de elementos secundarios. Entonces div [ class "track" ] []salidas div/div. Las listas están separadas por comas en Elm, por lo que agregar una identificación al div se vería así div [ class "track", id "my-id" ] [].

    El ajuste div track-sequencepasa la secuencia de la pista a nuestra segunda función, renderSequence. Toma una secuencia y devuelve una lista de botones HTML. Podríamos continuar renderSequencepara renderTrackomitir la función adicional, pero creo que es mucho más fácil razonar sobre dividir las funciones en partes más pequeñas. Además, tenemos otra oportunidad para definir una anotación de tipo más estricta.

    renderSequence : Array Step - List (Html Msg) renderSequence sequence = Array.indexedMap renderStep sequence | Array.toList

    Mapeamos cada paso de la secuencia y lo pasamos a la renderStepfunción. En JavaScript, el mapeo con un índice se escribiría así:

    sequence.map((node, index) = renderStep(index, node))

    En comparación con JavaScript, el mapeo en Elm es casi al revés. Llamamos a Array.indexedMap, que toma dos argumentos: la función que se aplicará en el mapa ( renderStep) y la matriz sobre la que se asignará ( sequence). renderStepes nuestra última función y determina si un botón está activo o inactivo. Lo usamos indexedMapporque necesitamos pasar el índice del paso (que usamos como ID) al paso mismo para poder pasarlo a la función de actualización.

    renderStep : Int - Step - Html Msg renderStep index step = let classes = if step == On then "step _active" else "step" in button [ class classes ] []

    renderStepacepta el índice como primer argumento, el paso como segundo y devuelve HTML renderizado. Usando un let...inbloque para definir funciones locales, asignamos la _activeclase a On Steps y llamamos a la función de nuestras clases en la lista de atributos del botón.

     

    La pista de inicio que contiene una secuencia de pasos.

    Actualización del estado de la aplicación

    En este punto, nuestra aplicación representa los 16 pasos de la secuencia de patada, pero al hacer clic no se activa el paso. Para actualizar el estado del paso, debemos pasar un mensaje ( Msg) a la función de actualización. Hacemos esto definiendo un mensaje y adjuntándolo a un controlador de eventos para nuestro botón.

    En Types.elm, necesitamos definir nuestro primer mensaje, ToggleStep. Se necesitará un Intpara el índice de secuencia y un Step. A continuación, en renderStep, adjuntamos el mensaje ToggleStepal evento al hacer clic del botón, junto con el índice de secuencia y el paso como argumentos. Esto enviará el mensaje a nuestra función de actualización, pero en este punto, la actualización en realidad no hará nada.

    type Msg = ToggleStep Int Step renderStep index step = let ... in button [ onClick (ToggleStep index step) , class classes ] []

    Los mensajes son tipos regulares, pero los definimos como el tipo que genera actualizaciones, que es la convención en Elm. En Update.elm seguimos la arquitectura Elm para manejar los cambios de estado del modelo. Nuestra función de actualización tomará a Msgy current Modely devolverá un nuevo modelo y potencialmente un comando. Los comandos manejan los efectos secundarios, que veremos en la segunda parte. Sabemos que tendremos varios Msgtipos, por lo que configuramos un bloque de casos que coincida con patrones. Esto nos obliga a manejar todos nuestros casos y al mismo tiempo separar el flujo de estados. Y el compilador se asegurará de que no pasemos por alto ningún caso que pueda cambiar nuestro modelo.

    La actualización de un registro en Elm se realiza de forma un poco diferente a la actualización de un objeto en JavaScript. No podemos cambiar directamente un campo en el registro record.field = *porque no podemos usar thiso self, pero Elm tiene ayudas integradas. Dado un registro como brian = { name = "brian" }, podemos actualizar el campo de nombre como { brian | name = "BRIAN" }. El formato sigue { record | field = newValue }.

    Así es como se actualizan los campos de nivel superior, pero los campos anidados son más complicados en Elm. Necesitamos definir nuestras propias funciones auxiliares, por lo que definiremos cuatro funciones auxiliares para sumergirnos en registros anidados:

    1. Uno para alternar el valor del paso.
    2. Uno para devolver una nueva secuencia, que contiene el valor del paso actualizado.
    3. Otro para elegir a qué pista pertenece la secuencia.
    4. Y una última función para devolver una nueva pista, que contiene la secuencia actualizada que contiene el valor del paso actualizado.

    Comenzamos ToggleStepalternando el valor del paso de la secuencia de pistas entre Activado y Desactivado. Usamos un let...inbloque nuevamente para crear funciones más pequeñas dentro de la declaración del caso. Si el paso ya está desactivado, lo activamos y viceversa.

    toggleStep = if step == Off then On else Off

    toggleStepserá llamado desde newSequence. Los datos son inmutables en los lenguajes funcionales, por lo que en lugar de modificar la secuencia, en realidad estamos creando una nueva secuencia con un valor de paso actualizado para reemplazar la anterior.

    newSequence = Array.set index toggleStep selectedTrack.sequence

    newSequenceusa Array.setpara encontrar el índice que queremos alternar, luego crea la nueva secuencia. Si set no encuentra el índice, devuelve la misma secuencia. Depende selectedTrack.sequencede saber qué secuencia modificar. selectedTrackes nuestra función auxiliar clave que se utiliza para que podamos acceder a nuestro registro anidado. En este punto, es sorprendentemente simple porque nuestro modelo solo






    Tal vez te puede interesar:

    1. ¿Deberían abrirse los enlaces en ventanas nuevas?
    2. 24 excelentes tutoriales de AJAX
    3. 70 técnicas nuevas y útiles de AJAX y JavaScript
    4. Más de 45 excelentes recursos y repositorios de fragmentos de código

    Aprendiendo Elm con un secuenciador de batería (Parte 1)

    Aprendiendo Elm con un secuenciador de batería (Parte 1)

    Implemente rápidamente. Implementar inteligentemente Register! Índice Empezando con el olmo

    programar

    es

    https://pseint.es/static/images/programar-aprendiendo-elm-con-un-secuenciador-de-bateria-parte-1-927-0.jpg

    2024-04-04

     

    Aprendiendo Elm con un secuenciador de batería (Parte 1)
    Aprendiendo Elm con un secuenciador de batería (Parte 1)

    Si crees que alguno de los contenidos (texto, imagenes o multimedia) en esta página infringe tus derechos relativos a propiedad intelectual, marcas registradas o cualquier otro de tus derechos, por favor ponte en contacto con nosotros en el mail [email protected] y retiraremos este contenido inmediatamente

     

     

    Top 20