Aprenda la programación reactiva funcional en su Arduino

A todo el mundo le encanta aprender un nuevo lenguaje de programación, ¿verdad? Bueno, incluso si no Como Eso, tienes que hacerlo de todos modos, porque pensar en los problemas desde diferentes perspectivas es genial para la imaginación.

Juniper es un lenguaje de programación reactivo funcional para la plataforma Arduino. Esto significa que escribirás tu código usando funciones anónimas, operaciones de mapa / plegado, recursividad y señales. Es como llevar el estilo de evento que necesita para programar un paso más allá; usted escribe a=b+3 y cuando b cambios, el compilador se encarga de cambiar a automáticamente para usted. (Esa es la parte “reactiva”).

Si está acostumbrado al estilo primero-hazlo-luego-hazlo-de Arduino (y la mayoría de la programación C / C ++), esto dependerá de la expansión. Pero nosotros faru tenga en cuenta que una gran cantidad de código de microcontrolador busca cambios en el entorno y luego actúa (más o menos asincrónicamente) sobre esos datos. En ese nivel de abstracción, algo como Juniper parece una buena opción.

Cambiar el paradigma de programación para Arduino es un proyecto ambicioso, especialmente considerando que fue iniciado por dos estudiantes. [Caleb Helbling] y [Louis Ades] como gerente senior de proyectos. También es nuevo, por lo que aún no hay mucha base de código. El tiempo y su participación dirán si es útil. Pero una cosa es segura, una vez que haya programado en lenguaje reactivo, no podrá ver un bucle retrasado de la misma manera.

¿Cuál es el lenguaje más sabio en el que ha programado un microcontrolador?

(El texto alto del cómic XKCD dice “La programación funcional combina la flexibilidad y el poder de las matemáticas abstractas con la claridad intuitiva de las matemáticas abstractas”).

  • ScubaBearLA dice:

    ¡Rápido, alguien escribe 99 botellas de cerveza en este idioma!

  • dahud dice:

    No estoy seguro de qué tan bien funciona la programación en el entorno de rendimiento limitado de AVR. Con C, puedo mirar un bloque de código y adivinar cuántos bucles y cuánta memoria usará. No sé si eso es cierto en el lenguaje funcional.

    • El gran dice:

      Ese fue mi pensamiento inicial al leer esto … Supongo que el tiempo dirá cómo es la presentación.

      • Palmadita dice:

        Es más que eso, si lo piensas. Bien, entonces el rendimiento podría ser limitado. Lo que. Pero la pregunta más importante es * ¿cómo se lleva a cabo exactamente *?

        C existe porque, en general, se asigna “bastante bien” al funcionamiento básico de la mayoría de las computadoras. No es perfecto (no hay concepto de banderas de acarreo / cero / desbordamiento que tienen casi todas las computadoras) pero bastante bueno. Tiene saltos y bifurcaciones, a menudo también tiene bifurcaciones calculadas (que son el equivalente a las sentencias de conmutación), llamadas y devoluciones. Tiene almacenamiento temporal (registros) y almacenamiento permanente en una matriz direccionable. Bastante básico.

        La programación funcional * no se corresponde con el funcionamiento básico de las computadoras en absoluto. Traza mejor cómo * queremos * que funcionen (si esto sucede, haga esto, si eso sucede, haga eso) pero no * realmente * funcionan de esa manera.

        Entonces, por ejemplo, en su ejemplo de Blink, la función “Something: toggle” se llama cada vez que se emite el evento “timerSig”. Estupendo. Maravilloso. ¿Cómo se implementa esto? ¿En interrupción? ¿Existe la posibilidad de que Something: toggle pierda un evento timerSig (por ejemplo, está alineado o es una bandera)? ¿Cuántas funciones se pueden etiquetar en un evento timerSig? ¿Cuál es la escala en términos de costo de recursos?

        Y realmente, no hay * información * sobre cómo se implementa en absoluto. Lo que es realmente muy frustrante, porque sin conocer los límites del entorno, es difícil imaginar trabajar dentro de ellos.

        • Caleb Helbling dice:

          La documentación de la función Io: toggle está aquí:
          http://www.juniper-lang.org/docs/files/Io-jun.html#Io.toggle

          Si realmente quieres ensuciarte, puedes ver directamente el código fuente de la biblioteca estándar:
          https://github.com/calebh/Juniper/blob/master/Juniper/junstd/Io.jun#L82

          Como puede ver, la plantilla de la función Io: toggle coincide en la entrada (que tiene un tipo pinState). Cuando la entrada es el constructor de valor bajo, el constructor de valor alto se usa para hacer el valor de retorno, y cuando el constructor de valor es alto, el constructor de valor bajo se usa para hacer el valor de retorno.
          http://www.juniper-lang.org/docs/files/Io-jun.html#Io.pinState
          https://github.com/calebh/Juniper/blob/master/Juniper/junstd/Io.jun#L34

          Acerca de cómo funciona Juniper:
          Las señales son posiblemente valores secretos. La definición de una señal es muy simple y se puede encontrar en el Preludio:
          http://www.juniper-lang.org/docs/files/Prelude-jun.html#Prelude.sig
          https://github.com/calebh/Juniper/blob/master/Juniper/junstd/Prelude.jun#L112

          Todas las funciones de procesamiento de señales son funciones normales planteadas en la mónada Maybe! Puedes ver esto en acción en
          https://github.com/calebh/Juniper/blob/master/Juniper/junstd/Signal.jun#L25

          Entonces, las señales son en realidad valores ordinarios, como números enteros o algunos otros tipos.
          Juniper no usa interrupciones en ninguna parte (ejecutar el compilador fue bastante difícil). Todo utiliza un modelo de base electoral.

          En algunos otros lenguajes de FRP, es posible que vea una separación explícita de un lenguaje que describe el gráfico de señales o se podría construir un gráfico de señales como un gráfico dirigido a la memoria. Este no es el caso en Juniper, debido a que las señales son simplemente valores posibles, esto significa que no hay un gráfico de señales construido en ninguna etapa. En cambio, la información sobre el gráfico de señales se codifica en el gráfico de llamadas.

          No tuvimos mucho tiempo para procesar la documentación. Actualmente paso mi tiempo escribiendo un artículo sobre el idioma y no he tenido tiempo de trabajar en otro tutorial.

          -Kaleb

          • evitar dice:

            ¿Sin interrupciones?

            ¿Eso significa que no hay temporizadores UART, I2C, ADC?

          • Palmadita dice:

            Sí, estoy un poco confundido acerca de todo “sin interrupciones”. Puedo comprar esto para la parte de Hora, aunque parece, de acuerdo con el código de Hora, que si el sistema está ocupado y el temporizador no se sondea lo suficientemente rápido, no será regular (porque se actualiza lastPulse en t, no en incremento de la hora actual).

            Seré honesto, siempre me confunden las personas que prestan más atención a la semántica * lingüística * que a * cómo se implementa el lenguaje *. No importa qué tan poderosa sea la semántica si la implementación no funciona bien.

            Antes dijiste que se compila en código C ++ real, ¿verdad? Sería de gran ayuda comprender cómo funciona el lenguaje si solo publicara el código C ++ compilado junto con los ejemplos.

        • Kratz dice:

          La forma en que se hacen las cosas en el idioma es muy importante, incluso más allá del micrófono hasta el escritorio. Tome este ejemplo de .NET, https://blogs.msdn.microsoft.com/ericlippert/2009/11/12/closing-over-the-loop-variable-considered-harmful/

        • GEOFFRY dice:

          Quien se limite a sí mismo será lo que tú te limites a uno mismo (no te limites nunca porque eso será todo lo que serás)

          • Max dice:

            … y el que no se limita en absoluto se llamará “hinchazón”.

    • TheRegnirps dice:

      Entonces … ¿es una hoja de cálculo?

      • Caleb Helbling dice:

        Sí, puedes pensar en el idioma como una hoja de cálculo muy muy avanzada.

  • Pedro dice:

    Uno de los principales puntos de venta del entorno Arduino es la abundancia de bibliotecas. Mirando el documento de Juniper, no pude entender si podía acceder a las bibliotecas habituales, p. Ej. I2C, SPI, etc. Encuentro que este es un proyecto hecho por dos estudiantes (muy bien hecho por cierto), pero esto es de poca utilidad si la única interacción con el mundo exterior es solo por un ligero recorte.

    • Caleb dice:

      Hay una sección en los documentos del lenguaje sobre la interacción con las bibliotecas C / C ++ existentes. Debido a que Juniper se compila en C ++, incluso puede escribir código en línea en el idioma.

      http://www.juniper-lang.org/language_docs.html
      (Sección Interacción con C ++ – Bibliotecas, en la parte inferior de la página)

    • Pierce Nichols dice:

      Lo bueno del AVR es que todo esto se logra leyendo / escribiendo un número limitado de registros. Sin embargo, me parece una tarea desagradable reescribir todos los hermosos paquetes que los Arduino han reunido.

      • cb88 dice:

        No sé sobre eso … la mayoría de las veces la implementación de arduino es extremadamente inoportuna debido a las opciones criticables y fáciles de usar. Lo bueno de AVR es que todos los chips tienen mucho en común … por lo que incluso si tuviera que escribir un ensamblaje para un adolescente, no sería demasiado difícil llevarlo a uno más grande si necesitara incluir más características. Entonces, si bien es cierto que sería un trabajo decente … sería un trabajo bastante gratificante para mucha gente.

        No es que esté escribiendo ningún conjunto … solo C y particularmente me gusta mi codificador cuadrado de 350 botones para ATtiny13A. Me preguntaría si alguien podría hacerlo menos, pero no me sorprendería demasiado.

    • Clóvis Fritzen dice:

      ¡Es exactamente por eso que el autor de la publicación está pidiendo ayuda comunitaria!

    • Caleb Helbling dice:

      Hay una sección en los documentos del lenguaje sobre la interacción con las bibliotecas C / C ++ existentes. Debido a que Juniper se compila en C ++, incluso puede escribir código en línea en el idioma.

      http://www.juniper-lang.org/language_docs.html
      Interactuar con C ++: sección Bibliotecas, en la parte inferior de la página

  • Moryc dice:

    ¿No es esto solo un software equivalente a un Stop-Change de rutina mezclado con una máquina finita? Se puede hacer con una declaración de yuxtaposición en el bucle principal y funciones que realmente hacen las cosas llamadas por él, con una función agregada sin ninguna superior …

  • licenciado en Derecho dice:

    > ¿Cuál es el lenguaje más sabio en el que ha programado un microcontrolador?

    No me gusta el enebro. ¿qué tal avici?

    (viejo chiste de telecomunicaciones; ahora, GOML)

  • DaveW dice:

    No creo que necesitemos YAPL (otro lenguaje de programación más). Bastante bueno es bastante bueno. Como alguien que ha programado en Forth y ha tratado de entender cómo las bibliotecas de C interactúan con Lua, casi siempre regreso a los lenguajes conocidos para las aplicaciones basadas en texto. programado. Creo que hay espacio para nuevos paradigmas de programación, pero es difícil equilibrar la codificación inicial fácil, la inteligibilidad (poder leer el código y comprender lo que hace), la facilidad de depuración y la eficiencia. El probado y los lenguajes fiables tienen un equilibrio bastante bueno.

    • Ingenuo de patas azules dice:

      Entonces, ¿básicamente “lo que tenemos es perfecto, por lo que el progreso es innecesario”?

      • guenther dice:

        No dijo eso del todo. Y aunque dudo en recomendar Forth en el siglo XXI, mirando el ejemplo de “parpadeo”, prefiero programarlo en Forth.

        Ensamblador, Forth (y en menor medida) C, dividido en proyectos grandes o grandes (para Forth y Assembler más grandes que uno o dos en realidad) equipos. Dado que no habrá grandes proyectos en Arduino, eso no es un problema en este espacio.

        Los lenguajes de programación funcional tienen su espacio y uso, pero no estoy convencido de que existan microcontroladores de 8 bits.

  • rasz_pl dice:

    ¿Enebro? es verdad ¿iOS coincide?
    para nada confuso

    • licenciado en Derecho dice:

      … bueno, la flota y el protón no están disponibles para comentarios;)

  • W dice:

    Todos saben acerca de los PLC, ¿verdad? ¿Lógica de escalera? En su mayor parte, es solo una forma incómoda (dirigida a electricistas, no a programadores) de expresar salidas como funciones de entrada.

    Si desea asegurarse de que un sistema automatizado sea igual de seguro, casi tiene que utilizar esos tipos funcionales de tecnologías. Nadie se fía del código imperativo.

    • gh0stwriter88 dice:

      El problema con la lógica de escalera es que tiene una escalabilidad limitada … deberías ser un completo lunático para dibujar el código que escribimos en mi tarea en una escalera. Dicho esto … las cosas críticas para la seguridad (como paradas de emergencia) a menudo se hacen en una escalera solo porque los electricistas lo entienden.

      Entonces, básicamente, terminas con un PLC con lógica de control escrita en texto estructurado o lo que sea que tengas y toda la lógica de falla en una escalera. De modo que obtiene su lógica compleja descargando cualquier “confianza” necesaria a la lógica de escalera.

  • RandyKC dice:

    ¿No puede hacer lo mismo una máquina de estado?

  • Rud Merriam dice:

    Simplemente lea la introducción y no vea nada inviable en C ++ moderno y el código se vería casi igual. El C ++ moderno tiene lambdas, que parece ser el único truco que juegan en este código. Estoy listo para ser educado.

    • Caleb Helbling dice:

      C ++ moderno no tiene tipos de datos algebraicos ni coincidencias de patrones.

      • Rud Merriam dice:

        Visité algunos sitios web sobre tipos de datos algebraicos. Ellos no ayudaron. No siguió el patrón de coincidencia. Pero me sorprendería que esto sea algo realmente nuevo que no haya visto antes en todas mis décadas. jajaja

        • Requerido dice:

          Entonces puede que se sorprenda, y aprender algo nuevo sobre idiomas puede ayudarlo incluso en su idioma favorito. Especialmente la coincidencia de patrones es un concepto / experiencia muy agradable. ¿Quizás podrías aprender Rust o SML para mojarte los pies?

          • Rud Merriam dice:

            La compatibilidad de plantillas no es nueva. Puedo volver a SNOBOL por ello. Eso es compatible con texto, pero el concepto es el mismo. A este respecto, la compatibilidad de firmas de C ++ es el mismo concepto.

            Sospeché que las plantillas proporcionan los tipos de datos algebraicos, pero no estaba 100% seguro. Tu otro comentario indica que sí.

      • Requerido dice:

        De hecho, el lenguaje de plantillas C ++ tiene eso y más. En C ++ incluso tiene compatibilidad de tipos enteros, en el lenguaje de la plantilla y especialización de escritura. Apuesto a que Juniper no te dejará hacer eso. (El tratamiento de C ++ de los tipos de unión es sombrío, lo admito)

        • Caleb Helbling dice:

          La palabra que busca aquí es un polimorfismo ad hoc que Juniper no admite actualmente. Hay otros lenguajes funcionales como F # y Elm que no admiten el polimorfismo ad hoc, pero que, sin embargo, son extremadamente utilizables.

          Juniper tiene cierto soporte para números enteros en patrones; consulte la sección de habilidades en http://www.juniper-lang.org/language_docs.html

        • Caleb Helbling dice:

          En los lenguajes funcionales hay varias formas diferentes de tratar el polimorfismo ad hoc. El primero es por módulos (SML y OCaml) y el segundo es por clases de tipo (Haskell). Después de que se implemente el sistema de tipos Hindley-Milner más avanzado en Juniper, buscaré implementar clases de tipos.

  • ¿Jugado? dice:

    Mimi the GOML guy @bl de antes …

    Ya sea investigado o interrumpido, si lógicamente todavía no estamos discutiendo solo otra forma de hacer las cosas:

    Si entonces

    El hecho de que tenga tipos elegantes, coincidencias de patrones, etc., ¿no es solo otra forma de abstracción, sino un poco más eliminado del código máquina? Simplemente no hace referencia / verifica el estado en el código, aunque investigar algo no muy lejano es en mi humilde opinión.

    Sin embargo, como @W, también estoy dispuesto a recibir educación, pero todavía no he visto razones para dejar el procedimiento para la mayoría de las cosas.

  • Dan # 9445376854 dice:

    ¿Cómo se supone que debe depurar un problema con la sincronización del flujo de datos a través de un gráfico cuando las rutas secundarias tienen diferentes longitudes y las señales vinculadas a una interrupción eterna no están sincronizadas de modo que a = b + c, pero los estados de byc tienen cada uno una línea de tiempo (obviamente) pero debido a la complejidad necesaria para calcular c en comparación con b, están desincronizados de modo que a = b.time (x) + c.time (x + d) donde d es la diferencia entre los tiempos de ejecución para calcule byc cuando realmente quisiera a = b.time (x + d) + c.time (x + d) e incluso entonces, ¿qué pasa si b cambia rápidamente, más rápido que c se puede calcular?

    • Max dice:

      Hmmm … interrupciones eternas … esos son los que se olvidan de vaciar la bandera de interrupción, ¿verdad? 😉

      • Dan # 9445376854 dice:

        Esto no está relacionado con mi pregunta, que describe una forma de problema de estatus racial.

  • Mate dice:

    ¿Cómo haces lo decente y asignas o enlazas de nuevo al cómic XKCD del que arrancaste la imagen?

    • Copyleft dice:

      Uso legítimo, ¿verdad?

  • Iw2 dice:

    Me parece que están tratando de hacer que una MCU se comporte como una FPGA. Parece que sería más eficiente mapear esto a Verilog o VHDL y usar FPGA pequeños como la serie ICE40.

  • Tony Pedley dice:

    Me las arreglé para poner a Erlang por delante de Sharp Zaurus hace mucho tiempo. Funcionó, pero tuve que eliminar muchas bibliotecas para insertarlo en la memoria. No hay ninguna razón por la que los lenguajes funcionales no deban funcionar con sistemas de bajos recursos y que Erlang sea suave en tiempo real podría ser bastante útil. El mayor problema sería la administración de la memoria, porque los programas mal escritos pueden ocupar mucha memoria en recursividad, por lo que un sistema operativo simple puede fallar y quemarse.

  • Maldición dice:

    C y C ++ siguen en pie, los demás parecen vientos que pasan …

  • Minero criogénico dice:

    Realmente, realmente me gusta la idea de este idioma. La idea parece perfectamente apropiada para la plataforma Arduino en el trabajo relacionado de AVR. Pude ver este lenguaje excepcionalmente útil para trabajos pequeños de IO. No para reemplazar lenguajes probados y verdaderos, sino como alternativa a situaciones apropiadas. También impresiono a los creadores, gran trabajo, de los nuevos desarrolladores que asumen proyectos ambiciosos. Creo que probablemente puedas hacer todo lo que hace el lenguaje en otros lenguajes maduros (como han demostrado casi todos los comentarios), pero Juniper no reemplaza el trabajo realizado en las grandes empresas de software. Me irrita el tono negativo general y la falta de apoyo en los comentarios, aunque puede que esté leyendo demasiado escepticismo. ¡Genial Caleb Helbling y Louis Ades!
    -¡Saludos!

    • Dan # 9445376854 dice:

      “He podido ver este lenguaje excepcionalmente útil para trabajos de IO pequeños. “¿Por qué, exactamente?”

    • BillSmith (@ melanchton1) dice:

      ¿Podría dar un ejemplo de una “situación adecuada”?
      No sé si la mayoría de los tonos son negativos, solo la gente realmente pregunta “¿por qué”?

  • BillSmith (@ melanchton1) dice:

    Soy un tipo de chico lógico, así que me gusta la programación lógica.
    Como tal, me pregunto qué puedo hacer con la programación funcional reactiva que no puedo hacer en C.

Victoria Prieto
Victoria Prieto

Deja una respuesta

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *