1 puntos por GN⁺ 3 시간 전 | 1 comentarios | Compartir por WhatsApp
  • La inferencia de tipos y la verificación gradual (gradually) de tipos se aplican a todos los programas de Elixir, lo que permite encontrar bugs verificados que llevarían a código muerto y fallos garantizados en tiempo de ejecución, incluso sin anotaciones de tipo
  • El tipo dynamic(), a diferencia de any() que “permite cualquier cosa”, rastrea el rango de tipos posibles en tiempo de ejecución y solo reporta una infracción cuando no hay superposición total con los tipos permitidos
  • Un valor dynamic(integer() or binary()) no genera una infracción en llamadas donde algunas posibilidades se superponen, como operaciones numéricas o funciones de cadenas, pero sí la genera en llamadas que solo aceptan map, como Map.fetch!
  • dynamic() se va acotando según cómo se use, refinando data en código como data.a + data.b hacia un map con la forma %{..., a: number(), b: number()}
  • En los guards, infiere unión, intersección y negación para usar como información de tipos condiciones como is_list, is_integer, is_map_key, not is_map_key y tuple_size
  • case y las condicionales reflejan la información de cláusulas anteriores en las siguientes, realizando verificaciones de tipos como manejar primero nil y luego acotar el valor restante a binary()
  • Se añadieron tipos a varias funciones relacionadas con tuple y map en la biblioteca estándar, lo que ayuda a encontrar cláusulas redundantes y código muerto en bases de código existentes
  • En “If T: Benchmark for Type Narrowing”, superó 12 de 13 categorías, mostrando que puede recuperar información de tipos precisa en código Elixir común
  • v1.20 también volvió a mejorar los tiempos de compilación en aplicaciones para entornos multinúcleo, y en benchmarks sintéticos la herramienta de build de Elixir mostró los resultados más rápidos entre los lenguajes de BEAM
  • La nueva opción del compilador :module_definition permite elegir el modo de ejecución de la definición de módulos entre el valor predeterminado :compiled o :interpreted, y se activa con elixirc_options: [module_definition: :interpreted] en mix.exs
  • La opción :module_definition no afecta a los archivos .beam escritos en disco y solo cambia la forma de ejecución dentro de defmodule, por lo que puede ayudar a mejorar los tiempos de compilación en proyectos grandes
  • Las nuevas firmas de tipos que aprovechan tipos conjuntistas se discutirán junto con la definición de typed struct después de que se cumplan las investigaciones sobre rendimiento del sistema de tipos de v1.20, tipos recursivos, tipos parametrizados y recorrido de pares clave-valor en map

1 comentarios

 
GN⁺ 3 시간 전
Comentarios de Hacker News
  • Puede que sea solo mi experiencia personal, pero siento que, si no es un lenguaje que tuvo tipos desde el principio, no funciona tan bien como un verdadero lenguaje de tipos estáticos

    • Estoy de acuerdo, pero hay otra perspectiva: “Why are gradual static types so great?” https://www.benkuhn.net/gradual/
    • Por otro lado, TypeScript tiene que soportar todo tipo de patrones extrañísimos que la gente ha venido usando en un lenguaje sin tipos, así que terminó siendo mi sistema de tipos favorito
  • Llevo unos 10 años trabajando como desarrollador profesional de Elixir y desde hace mucho esperaba la llegada de los tipos. Me alegra muchísimo que por fin haya entrado ese primer paso en esta ocasión
    Aun así, me gustaría saber cómo se compara el estado incluido en v1.20 con Dialyzer sin especificaciones. Entendía que el enfoque de success typing de Dialyzer se parece más a “si existe хотя бы una combinación de argumentos que funcione, no avisa”, en vez de “avisa si hay una combinación de argumentos que puede fallar”, y pensé que lo que Elixir estaba haciendo aquí era parecido, pero nunca sentí que Dialyzer fuera especialmente útil

    • Tengo curiosidad por ver qué encontrará en un codebase de Elixir de 10 años que todavía sigue en producción
  • He visto varias veces en HN artículos sobre el sistema de tipos graduales de Elixir, pero no los he seguido a detalle. Me pregunto si alguien sabe si este sistema de tipos graduales puede cambiar la complejidad asintótica de un programa en comparación con código sin tipos
    Hasta donde sé, la mayoría de los sistemas de tipos graduales, por ejemplo Racket, pueden hacer que un programa sea asintóticamente más lento, aunque hay algunas excepciones [1]
    [1] https://doi.org/10.1145/3314221.3314627

    • El sistema de tipos graduales de Elixir no puede cambiar la complejidad asintótica del programa. Por diseño, excluye explícitamente los casts en tiempo de ejecución en la frontera entre lo estático y lo dinámico, que son la causa de la lentitud en otros sistemas de tipos graduales
      La mayoría de los sistemas de tipos graduales insertan coerciones cuando un valor cruza la frontera entre código tipado y no tipado. Por ejemplo, revisan todos los elementos de una lista o envuelven un valor en un proxy de tipos. Pero el equipo de Elixir publicó resultados de strong arrows para obtener solidez sin esas verificaciones en tiempo de ejecución, y el bytecode que genera el compilador es semánticamente idéntico al del código sin tipos
  • Irónicamente, los críticos decían que hacían falta tipos, y los fans de Elixir decían que no hacían falta y que Elixir era de algún modo mágico, así que no tenía bugs relacionados con tipos. Ahora que le están metiendo tipos, está encontrando bugs. ¿No se suponía que no hacían falta para prevenir bugs? Aun así, es un buen cambio. En su momento usé bastante Elixir y me gustó, pero me costaba aceptar la ausencia de tipos

    • Eso es la falacia Goomba
      https://en.wiktionary.org/wiki/Goomba_fallacy
    • No he seguido Elixir tan de cerca en particular, pero lo que vi en discusiones del lado de Erlang era algo un poco distinto. Como de todos modos hay que manejar los fallos con elegancia, la idea era que los errores de tipos también se podían tratar con los mecanismos de recuperación de fallos que ya debían existir
      No estoy de acuerdo con esa postura, pero es una afirmación mucho más defendible que decir “$LANGUAGE es magia”
    • No puedo asegurar que nunca haya visto a alguien hacer ese argumento, pero no lo recuerdo, y aunque haya existido, habría sido una minoría muy pequeña. El argumento real en contra normalmente se parecía más a “los tipos son buenos, pero tienen un costo, y ese costo no siempre se traduce en un beneficio suficiente”
      Antes del avance de la teoría de tipos conjuntista, esa postura quizá sí era correcta
    • Lo mismo pasó en JavaScript/TypeScript y Python. A veces no queda más que dejar que la gente piense lo que quiere pensar
    • Es el ciclo de la vida. Los lenguajes de tipos dinámicos ganan fans, otras personas dicen —con razón— que serían mucho más útiles con tipos estáticos. Los fans se lo toman como algo personal y dicen que los tipos estáticos no hacen falta. Las razones varían: “de todos modos no sirven”, “van contra el espíritu del lenguaje”, “solo es un lenguaje de scripting”, “usa un depurador”, “los tipos estáticos dañan la productividad”, etc.
      Y al final terminan agregando tipos estáticos. Pasó con Python, JavaScript y Ruby, y seguramente con más
  • Me encanta poder actualizar Elixir sin que haya cambios incompatibles en varios proyectos, y que el compilador me encuentre bugs gratis. Ya me malacostumbré

  • Esto de verdad me da mucho gusto. Ya se está acercando al nivel de “gran lenguaje”, y para mí Elixir es el primer candidato
    Si conocen otro lenguaje que ya sea cómodo de usar y al mismo tiempo siga agregando grandes funcionalidades de forma estable y segura, me encantaría saberlo. Después de dominar Go me pasé a aprender C# avanzado, porque sentía que Go se había quedado estancado en cuanto a sumar buenas funcionalidades

  • En el último mes hice el track de Elixir en exercism.io https://exercism.org/tracks/elixir
    Es realmente excelente

  • Ah, ahí vamos otra vez. Parece que voy a pasar otro año aprendiendo Elixir de nuevo
    Me encanta todo de Elixir, pero más que cualquier otro lenguaje, Elixir hace que siga dudando de mí mismo. Siento que mi cerebro no está hecho para lo funcional, pero este cambio me dan ganas de intentarlo otra vez
    Lo malo es que no diría que el ecosistema sea muy amigable para principiantes, y muchas veces, cuando responden preguntas, asumen que ya conoces bastante el lenguaje

    • https://pragprog.com/titles/lhelph/functional-web-developmen...
      No se dejen engañar por el título. La primera mitad del libro es simplemente Elixir
      He usado este libro cada vez que volví a adaptarme a Elixir durante los últimos 8 años, y siempre me ha funcionado. Nunca lo he terminado
      Uno de mis criterios para saber si este tipo de libros de programación basados en proyectos y tutoriales es bueno, es si aunque lo empiece varias veces y no llegue al final, ya a la mitad me da las herramientas para irme a hacer mi trabajo
    • Cuando probé Haskell por primera vez en la universidad, en una clase tipo “panorama de paradigmas de programación”, pasé exactamente por ese dolor. Ya llevaba años programando en ese momento, y no podía creer sentirme tan inútil para terminar cosas que durante tanto tiempo me habían parecido básicas
      Pero creo que no es tanto que tu cerebro no encaje, sino el contraste entre el nivel de experiencia que traes de lenguajes imperativos y el hecho de volver a empezar como principiante en un estilo puramente funcional
      Va a ir mejorando. El momento en que la programación funcional empezó a resultarme cómoda fue cuando me di cuenta de cuánto me gusta encadenar código tipo “one-liners” de Bash con bastante espacio. Si los datos empiezan con cierta forma, los vuelco con un comando, pienso en la etapa que los acerca más a la forma que quiero, los paso por pipe al siguiente comando y vuelvo a mirar. Si sigues así, al final normalmente te queda una secuencia de transformaciones de datos que no mutan nada
      Una razón por la que esto se siente cómodo en el shell es que todos los días andas recorriendo el sistema de archivos y acumulando vocabulario de comandos. Tu biblioteca familiar de “funciones” en un entorno tipo Unix se vuelve bastante grande con los años. En un entorno de programación puramente funcional hay que hacer lo mismo, pero aprender el vocabulario cuesta un poco más de esfuerzo. Tus “comandos” más frecuentes pasan a ser funciones como map, fold, zip en vez de grep, cat o sort
      Pero en el fondo es realmente lo mismo, y el atractivo de construir pipelines aplica igual en ambos lados. Puedes armarlo por partes, y en cada pequeño rompecabezas puedes olvidarte del paso anterior y pensar solo en cómo transformar los datos que tienes enfrente al siguiente estado. Esa baja carga de contexto se siente fresca y cómoda
      Ojalá lo intentes y lo disfrutes. Cuando logras disfrutar el hecho de no poder hacer algo todavía, es cuando por fin empiezas a volverte bueno
    • Me pregunto si conoces un poco de Rust. Yo tampoco tengo mucha experiencia con lenguajes funcionales, pero Gleam se me hizo familiar por sus partes tipo Rust, así que pude concentrarme más en los conceptos que en la sintaxis
      Claro, solo le dediqué unas cuantas tardes, pero si fuera a reentrenar mi cerebro para lo funcional otra vez, probablemente elegiría Gleam por esa familiaridad
    • Te recomendaría preguntar en ElixirForum. Nunca he visto respuestas realmente hostiles
      A veces hay publicaciones ambiguas que no reciben atención, o las ignoran porque huelen a “háganme la tarea”
      Pero, por lo que yo he visto, todas las publicaciones con curiosidad genuina reciben respuesta
    • Este tipo de comentario siempre me confunde. Los programas orientados a objetos llenos de estado me resultan muchísimo más difíciles de razonar
  • Excelente. En 1.20 parece que la compilación de nuestra gran app umbrella se volvió bastante más rápida

  • Me pregunto cómo se compara con Gleam. O más bien, ¿por qué usar Elixir ahora en vez de Gleam? Phoenix, y en particular LiveView, sí parecen ser una gran ventaja de Elixir

    • Es la diferencia entre si te gusta Rust o te gusta Erlang. Usar Gleam se siente como usar Rust, y usar Elixir se siente como usar Erlang
      No sé cuál sea el estado actual de Gleam OTP, pero la última vez que lo vi no estaba muy bien
      Si te da igual todo eso y solo te importan los tipos, entonces usa Gleam. Aunque en ese caso, ¿por qué no usar simplemente Rust?
    • En el sitio web de Gleam hay una comparativa directamente
    • Gleam no tiene macros, y muchas librerías de Elixir como Phoenix o Ecto usan macros de forma muy efectiva
      Por ejemplo, en Gleam el JSON decoding/encoding puede volverse verboso. En Rust basta con derivar serde, y en Elixir basta con una llamada a función
      Elixir tiene un ecosistema más maduro. Por ejemplo, en Gleam puedes usar Phoenix u otros frameworks de Gleam, pero la experiencia no es la misma
      La gran razón por la que Gleam resulta más atractivo que Elixir son los tipos, y ahora Elixir está empezando a cerrar esa brecha. También está el hecho de que puede compilar a JavaScript, y en Elixir Hologram está haciendo algo parecido
      Personalmente, me gusta más el sistema de tipos de Gleam y su sintaxis tipo Rust, pero hoy por hoy siento que Elixir es una mejor opción para todos mis proyectos de desarrollo web
    • Básicamente por Phoenix y Ecto