Lanzamiento del lenguaje de programación Julia 1.12

Se ha publicado el lanzamiento del lenguaje de programación Julia 1.12, que combina cualidades como alto rendimiento, soporte para escritura dinámica y herramientas integradas para programación paralela. La sintaxis de Julia es cercana a MATLAB y toma prestados algunos elementos de Ruby y Lisp. El método de manipulación de cadenas recuerda a Perl. El código del proyecto se distribuye bajo la licencia MIT.

Características clave del idioma:

  • Alto rendimiento: uno de los objetivos clave del proyecto es lograr un rendimiento cercano al de los programas C. El compilador Julia se basa en el trabajo del proyecto LLVM y genera código de máquina nativo eficiente para muchas plataformas de destino;
  • Admite varios paradigmas de programación, incluidos elementos de programación funcional y orientada a objetos. La biblioteca estándar proporciona, entre otras cosas, funciones para E/S asíncrona, control de procesos, registro, creación de perfiles y gestión de paquetes;
  • Escritura dinámica: el lenguaje no requiere una definición explícita de tipos de variables, similar a los lenguajes de programación de scripts. Modo interactivo compatible;
  • Capacidad opcional para especificar tipos explícitamente;
  • Una sintaxis ideal para computación numérica, computación científica, aprendizaje automático y visualización de datos. Soporte para muchos tipos de datos numéricos y herramientas para paralelización de cálculos.
  • La capacidad de llamar directamente funciones desde bibliotecas C sin capas adicionales.

Cambios importantes en Julia 1.12:

  • Nuevas funciones de idioma
    • La opción experimental "--trim" crea binarios más compactos eliminando el código inaccesible desde los puntos de entrada especificados. Los puntos de entrada se pueden marcar con "Base.Experimental.entrypoint". Es posible que no todo el código funcione con esta opción.
    • Las anulaciones de constantes ahora están claramente definidas y siguen la semántica de la era mundial. Se permiten anulaciones adicionales (por ejemplo, de tipos).
    • Se ha agregado un nuevo parámetro "usings::Bool" a la función "names", lo que hace que la función devuelva todos los nombres visibles a través de "using".
    • La familia de macros @atomic ahora admite la sintaxis de asignación de referencias, como @atomic :monotonic v[3] += 4, que modifica atómicamente v[3] con semántica de ordenamiento monótono. La sintaxis compatible incluye:
      • lectura atómica ("x = @atomic v[3]"),
      • asignación atómica ("@atomic v[3] = 4"),
      • cambio atómico ("@atomic v[3] += 2"),
      • asignación única atómica ("@atomiconce v[3] = 2"),
      • intercambio atómico ("x = @atomicswap v[3] = 2"),
      • reemplazo atómico ("x = @atomicreplace v[3] 2=>5").
    • El nuevo parámetro "--task-metrics=yes" permite recopilar información sobre el tiempo de ejecución de cada tarea. Este parámetro se puede activar o desactivar en tiempo de ejecución mediante "Base.Experimental.task_metrics(::Bool)". Métricas disponibles:
      • el tiempo de ejecución real de la tarea, incluida la compilación y la recolección de elementos no utilizados ("Base.Experimental.task_running_time_ns"),
      • tiempo desde el momento en que se inició la tarea hasta su finalización (“Base.Experimental.task_wall_time_ns”).
    • Compatibilidad con Unicode 16.
    • "Threads.@spawn" ahora acepta el argumento ":samepool" para especificar el mismo grupo de subprocesos que el código de llamada. "Threads.@spawn :samepool foo()" es la abreviatura de "Threads.@spawn Threads.threadpool() foo()".
    • La macro "@ccall" ahora acepta el argumento "gc_safe". Si este argumento es verdadero, el entorno de ejecución puede realizar la recolección de elementos no utilizados en paralelo mientras se llama a "ccall".
  • Cambios de idioma
    • Al reemplazar un método con una firma equivalente, el método existente no se elimina. En su lugar, el nuevo método tiene prioridad. Si se elimina el nuevo método, el antiguo volverá a funcionar. Esto es útil, por ejemplo, en entornos de pruebas simuladas (SparseArrays, Pluto, Mocking, etc.), ya que no es necesario restaurar explícitamente el método antiguo. Actualmente, esta situación requiere una recompilación, pero es posible que se puedan reutilizar los resultados antiguos en el futuro.
    • La expansión de macros ya no introducirá de forma recursiva expresiones "Expr(:toplevel)" desde macros. En su lugar, la expansión ":toplevel" se pospondrá hasta el tiempo de ejecución. Esto permite que expresiones posteriores en el mismo ":toplevel" utilicen macros previamente definidas.
    • Los bucles infinitos triviales (como "while true; end") ya no se consideran comportamientos indefinidos. Los bucles infinitos que realmente realizan una acción (como con efectos secundarios o el sueño) nunca se consideraron ni se consideran comportamientos indefinidos.
    • Marcar un identificador como "público" y "exportador" al mismo tiempo ahora es un error.
    • Los errores de tiempo de ejecución en "getfield" ahora arrojan un nuevo tipo de excepción "FieldError" en lugar del "ErrorException" genérico.
    • Las macros en las declaraciones de funciones ya no requieren paréntesis. Por ejemplo, ahora se acepta "function @main(args) … end", mientras que antes se requería "function (@main)(args) … end".
    • Al llamar a "using" en un nombre de paquete dentro del propio paquete (especialmente relevante para módulos anidados), ahora se usa explícitamente ese paquete sin consultar el manifiesto ni el entorno, al igual que "..Name". Esto se ajusta mejor al comportamiento esperado.
  • Mejoras del compilador y del tiempo de ejecución
    • El código intermedio (IR) generado por LLVM ahora usa tipos de puntero en lugar de pasar punteros como enteros. Esto afecta a "llvmcall": el IR integrado de LLVM debe actualizarse para reemplazar "i32"/"i64" por "i8*" o "ptr" y eliminar las conversiones innecesarias de "ptrtoint"/"inttoptr". Por compatibilidad, el IR con punteros enteros aún es compatible, pero genera una advertencia.
  • Cambios en las opciones de la línea de comando
    • Se puede pasar la bandera "-m/--module" para ejecutar la función "main" dentro del paquete con un conjunto de argumentos. Esta función debe declararse con "@main", lo que indica que es el punto de entrada.
    • La salida de color de Julia ahora se puede activar o desactivar mediante las variables de entorno "NO_COLOR" y "FORCE_COLOR". Estas variables también son respetadas por el sistema de compilación de Julia.
    • "--project=@temp" inicia a Julia con un entorno temporal.
    • La nueva opción "--trace-compile-timing" imprime el tiempo de compilación de cada método generado por "--trace-compile" en milisegundos.
    • "--trace-compile" ahora imprime los métodos recompilados en amarillo o agrega un comentario si el color no está disponible.
    • La nueva opción "--trace-dispatch" imprime métodos que se asignan dinámicamente.
  • Cambios de subprocesos múltiples
    • Julia ahora usa un hilo "interactivo" por defecto, además de un hilo principal "de trabajo", es decir, "-t1,1". Esto significa que la tarea principal y REPL (en modo interactivo), que se ejecutan en el hilo 1, ahora se ejecutan en el grupo interactivo. El bucle de E/S de libuv también se ejecuta en el hilo 1, lo que garantiza un uso eficiente del grupo de trabajo utilizado por "Threads.@spawn". Solicitar exactamente un hilo ("-t1"/"JULIA_NUM_THREADS=1") o ningún hilo interactivo deshabilita el hilo interactivo: "-t1,0", "JULIA_NUM_THREADS=1,0" o "-tauto,0". Solicitar más de un hilo habilita el hilo interactivo; por ejemplo, "-t2" equivale a "-t2,1". Como recordatorio, los búferes no deben estar vinculados a "threadid()".
    • Se definen nuevos tipos para las plantillas de código que deben ejecutarse una vez por proceso. El tipo "OncePerProcess{T}" permite definir una función que se ejecutará exactamente una vez la primera vez que se llame y que siempre devolverá el mismo valor de tipo "T" en las llamadas posteriores. También existen los tipos "OncePerThread{T}" y "OncePerTask{T}" para usos similares con subprocesos o tareas.
  • Construir cambios en el sistema
    • Se añadieron nuevos Makefiles para compilar Julia y LLVM con BOLT (Herramienta de Optimización y Diseño Binario). Consulte "contrib/bolt" y "contrib/pgo-lto-bolt".
  • Nuevas funciones de biblioteca
    • "logrange(start, stop; length)" crea un rango con una relación constante en lugar de un paso constante.
    • La nueva función "isfull(c::Channel)" verifica si "put!(c, some_value)" se bloqueará.
    • "waitany(tasks; throw=false)" y "waitall(tasks; failfast=false, throw=false)" esperan a que varias tareas se completen simultáneamente.
    • "uuid7()" crea un UUID de versión 7 que cumple con RFC 9562.
    • "insertdims(array; dims)" inserta dimensiones de un solo elemento en una matriz: la operación inversa de "dropdims".
    • El nuevo tipo "Fix" generaliza "Fix1/Fix2" para corregir un solo argumento.
    • "Sys.detectwsl()" comprueba si Julia se está ejecutando dentro de WSL en tiempo de ejecución.
  • Nuevas oportunidades para las bibliotecas
    • "escape_string" toma los parámetros adicionales "ascii=true" (para escapar todos los caracteres que no sean ASCII) y "fullhex=true" (para utilizar el formato hexadecimal completo de 4/8 dígitos en el escape u/U, por ejemplo para compatibilidad con C).
    • "tempname" ahora puede aceptar una cadena de sufijo para que el nombre del archivo incluya ese sufijo y se tenga en cuenta para garantizar su unicidad.
    • Ahora se pueden usar objetos RegexMatch para crear NamedTuple y Dict.
    • "Bloqueable" ahora es exportable.
    • "Base.require_one_based_indexing" y "Base.has_offset_axes" ahora son públicos.
    • Se agregaron nuevas funciones "ltruncate", "rtruncate" y "ctruncate" para truncar cadenas al ancho del texto, teniendo en cuenta el ancho del carácter.
    • La función "isless" (y por lo tanto "cmp", clasificación, etc.) ahora es compatible con "AbstractArray" de dimensión cero.
    • "invocar" ahora permite pasar un "Método" en lugar de una firma de tipo.
    • "invoke" ahora acepta un "CodeInstance" en lugar de un tipo, lo que puede acelerar algunos flujos de trabajo del complemento del compilador.
    • "Timer(f, …)" ahora hereda la persistencia de la tarea principal al crear tareas de temporizador, lo cual se puede anular con el nuevo argumento "spawn". Esto soluciona un problema por el cual las tareas generadas con persistencia ("@async") hacían que la tarea principal fuera persistente.
    • "Timer" ahora tiene propiedades "timeout" e "interval" legibles, y un método "show" más descriptivo.
    • 'sort' ahora admite tuplas 'NTuple'.
    • "map!(f, A)" ahora almacena los resultados en "A", como "map!(f, A, A)" o "A .= f.(A)".
    • "setprecision" con un argumento de función (normalmente mediante un bloque "do") ahora es seguro para subprocesos. Se deben evitar otras formas y los tipos deben migrar a una implementación que utilice "ScopedValue".
  • Cambios de biblioteca estándar
    • "gcdx(0, 0)" ahora devuelve "(0, 0, 0)" en lugar de "(0, 1, 0)".
    • "fd" devuelve "RawFD" en lugar de "Int".
    • Paquete JuliaSyntaxHighlighting
      • Un nuevo paquete estándar para aplicar resaltado de sintaxis al código Julia, utilizando JuliaSyntax y StyledStrings para implementar una función de resaltado que produce una AnnotatedString con el resaltado aplicado.
    • Paquete de álgebra lineal.
      • "rank" ahora puede aceptar una matriz "QRPivoted" para estimar el rango a través de la factorización QR.
      • Se agregó el parámetro clave "alg" a "eigen", "eigen!", "eigvals" y "eigvals!" para tipos de matrices autoadjuntas (unión típica "RealHermSymComplexHerm"), lo que permite cambiar entre diferentes algoritmos de extracción de valores propios.
      • Se agregó una versión general de la descomposición de Cholesky desbloqueada con muestreo de rotación (llamada a través de "cholesky[!](A, RowMaximum())").
      • La cantidad predeterminada de subprocesos BLAS ahora tiene en cuenta la afinidad del proceso en lugar de simplemente la cantidad de subprocesos lógicos en el sistema.
      • Se añadió la función "zeroslike", que devuelve cero elementos para matrices basadas en cintas. Los tipos de matriz personalizados pueden especializar esta función para devolver el resultado correcto.
      • La multiplicación de matrices "A * B" ahora llama a "matprod_dest(A, B, T::Type)" para generar el destino. Esta función ahora es pública.
      • La función "haszero(T::Type)" se utiliza para comprobar si el tipo "T" tiene un elemento cero único, definido como "zero(T)". Ahora es pública.
      • Se agregó la función "diagview", que devuelve una vista de una diagonal específica de la matriz "AbstractMatrix".
    • Paquete de perfil
      • "Profile.take_heap_snapshot" ahora acepta un nuevo parámetro, "redact_data::Bool", con un valor predeterminado de "true". Si está habilitado, el contenido de los objetos de Julia (como las cadenas) no se incluye en la instantánea del montón.
      • "Profile.print()" ahora colorea los módulos Base/Core/Package de la misma manera que lo hace en los seguimientos de pila, y las rutas (incluso las truncadas) ahora se pueden hacer clic en terminales que admiten enlaces URI y permiten abrir el archivo y la línea especificados en el editor especificado por "JULIA_EDITOR".
    • REEMPLAZAR
      • Al utilizar la nueva función "usings=true" en la función "names()", la finalización de REPL puede completar los nombres visibles a través de "using".
      • La finalización de REPL ahora puede completar cadenas como "[import|using] Mod: xxx|", por ejemplo, completando "using Base.Experimental: @op" a "using Base.Experimental: @opaque".
      • El REPL ahora emite una advertencia si se hace referencia a un nombre a través de un módulo que no lo define (ni tiene un submódulo que lo defina), y el nombre no es público en ese módulo. Por ejemplo, "map" está definido en Base, y ejecutar "LinearAlgebra.map" en el REPL ahora emitirá una advertencia la primera vez que se haga dicha referencia.
      • Al enviar la entrada al REPL, la salida ahora se trunca a 20 KiB. Esto no afecta las llamadas manuales a "mostrar", "imprimir", etc.
      • El autocompletado del carácter "\" ahora muestra el carácter o emoji correspondiente junto a cada palabra de código coincidente.
    • Paquete de prueba
      • Si la suite de pruebas DefaultTestSet falla, se imprime su generador de números aleatorios (RNG) para reproducir un error aleatorio que depende únicamente del estado del RNG. También puede especificar el RNG de una suite de pruebas pasando el parámetro rng a la macro @testset: julia using Test, Random @testset rng=Xoshiro(0x2e026445595ed28e, 0x07bb81ac4c54926d, 0x83d7d70843e8bad6, 0xdbef927d150af80b, 0xdbf91ddf2534f850) begin @test rand() == 0.559472630416976 end
    • Paquete InteractiveUtils
      • Nuevas macros "@trace_compile" y "@trace_dispatch" para ejecutar expresiones con los parámetros "--trace-compile=stderr --trace-compile-timing" y "--trace-dispatch=stderr" respectivamente.
  • Dependencias externas
    • La base de datos de información del terminal ("terminfo") ahora se incluye por defecto en Julia, lo que mejora el rendimiento de REPL cuando terminfo no está disponible en el sistema. Julia se puede compilar sin incluir la base de datos mediante el parámetro "WITH_TERMINFO=0" del Makefile.
  • Mejoras de herramientas
    • Hay un perfilador de tiempo de pared disponible para usuarios que necesitan un perfilador de muestreo que capture tareas independientemente de su estado (programadas/en ejecución). Este perfilador permite perfilar tareas con uso intensivo de E/S y ayuda a identificar áreas de alta contención en el sistema.

Fuente: opennet.ru

Añadir un comentario