Опубликован релиз языка программирования Julia 1.9. Его синтаксис близок к MATLAB с заимствованием некоторых элементов из Ruby и Lisp. Код проекта распространяется под открытой лицензией MIT.
Ключевыми особенностями языка выступают высокая производительность, поддержка различных парадигм программирования, включая элементы объектно-ориентированного и функционального, динамическая типизация с опциональной возможностью явного указания типов, поддержка многих числовых типов данных и средств для распараллеливания вычислений, а также возможность прямого вызова функций из библиотек на языке Си без дополнительных прослоек.
Основные изменения в Julia 1.9 включают:
выполнение присвоений в другом модуле с помощью "setproperty!(::Module, ::Symbol, x)";
множественное присваивание не в финальной позиции. Например, строка "a, b..., c = 1, 2, 3, 4" будет обработана как "a = 1; b..., = 2, 3; c = 4" через Base.split_rest;
поддержку литералами отдельных символов того же синтаксиса, что и строковыми;
поддержку спецификации Unicode 15;
использование в качестве параметров типа вложенных комбинаций кортежей и именованных кортежи символов;
новые встроенные функции "getglobal(::Module, ::Symbol[, order])" и "setglobal!(::Module, ::Symbol, x[, order])" для чтения и записи исключительно в глобальные переменные. Метод getglobal теперь должен быть предпочтительнее для доступа к глобальным переменным, чем метод getfield;
экспорт макроса "@invoke", представленного в версии 1.7. Он использует метод "Core.Typeof(x)", а не "Any" в случае, когда аннотация типа опущена для аргумента "x". Это необходимо для того, чтобы типы, передаваемые в качестве аргументов, обрабатывались правильно;
экспортирование функции "invokelatest" и макроса "@invokelatest", появившихся в версии 1.7;
сокращение время до первого выполнения (TTFX — Time to first execution). Предварительная компиляция пакета теперь сохраняет машинный код в "pkgimage". Таким образом, код, сгенерированный в процессе предварительной компиляции, не потребует повторной компиляции после загрузки пакета. Использование режима pkgimages можно отключить с помощью опции "--pkgimages=no";
исправление проблемы квадратичной сложности выведения типов. Некоторые граничные случаи с автоматически сгенерированными длинными функциями (например, ModelingToolkit.jl с уравнениями в частных производных и большими причинно-следственными моделями) компилируются намного быстрее;
оптимизацию вызовов с аргументами без конкретных типов методом Union-splitting для внедрения или статического разрешения, даже если существует несколько разнотиповых кандидатов для диспетчеризации. Это может улучшить производительность в определённых ситуациях, когда типы объектов не полностью статически разрешены, за счёт статического разрешения сайтов вызова "@nospecialize-d" и избежания повторной компиляции;
замену вариантов использования макроса @pure в модуле Base на Base.@assume_effects;
отсутствие перекомпиляции пакета при вызовах invoke(f, invokesig, args...) с менее конкретными типами;
определение доступного количества процессоров на основе CPU affinity параметром "--threads=auto" в Linux и Windows;
отключение параметра "--math-mode=fast", вместо которого рекомендуется использовать макрос "@fastmath";
формат "auto | N[,auto|M]" у параметра "--threads", где M указывает количество создаваемых интерактивных потоков;
опцию "--heap-size-hint=<size>", устанавливающую порог, после которого начинается активная сборка мусора. Размер может быть указан в байтах, килобайтах (1000 КБ), мегабайтах (300 МБ) или гигабайтах (1,5 ГБ);
опциональный первый аргумент со значением ":default" или ":interactive" в "Threads.@spawn". Интерактивные задачи будут выполняться в интерактивных потоках, если они указаны при запуске Julia;
вызов кода Julia потоками, запущенными вне среды выполнения, с использованием "jl_adopt_thread". Это происходит автоматически при вводе кода Julia через "cfunction" или точку входа "@ccallable";
функцию "Iterators.flatmap";
функцию "pkgversion(m::Module)" для получения версии пакета, который загрузил данный модуль, аналогично "pkgdir(m::Module)";
функцию "stack(x)", которая обобщает "reduce(hcat, x::Vector{<:Vector})" до любой размерности и допускает любой итератор итераторов. Метод "stack(f, x)" обобщает "mapreduce(f, hcat, x)" и является более эффективным;
макрос для анализа выделенной памяти "@allocations", аналогичный "@allocated", за исключением того, что возвращает количество операций выделения памяти, а не общий размер выделенной памяти;
работу "RoundFromZero" для типов, отличных от "BigFloat";
ручное уменьшение "Dict" с помощью "sizehint!";
указание процента времени в "@time", потраченного на перекомпиляцию недействительных методов;
устранение проблемы параллельного доступа в методах итерации для Dict и других производных объектов, таких как keys(::Dict), values(::Dict) и Set. Эти методы итерации теперь можно вызывать для Dict или Set параллельно для неограниченного количества потоков при условии, что нет действий, изменяющих словарь или набор;
возвращение составной функции "(!) ∘ f" вместо анонимной при отрицании функции-предиката "!f";
работу функции среза размерности в нескольких измерениях: "eachslice", "eachrow" и "eachcol" возвращают объект "Slices", который позволяет выполнять диспетчеризацию для предоставления более эффективных методов;
макрос "@kwdef" в общедоступном API;
исправление проблемы с порядком операций в "fld1";
стабильную сортировку по времени (переработан QuickSort);
экспорт "Base.splat". Возвращаемое значение представляет собой тип "Base.Splat", а не анонимную функцию;
поддержку загрузки фрагмента кода из других пакетов в менеджере пакетов "Package Extensions", загружаемых в сеансе Julia. Применение, сходное с пакетом "Requires.jl", но поддерживается предварительная компиляция и совместимость настроек;
в библиотеке LinearAlgebra из-за риска путаницы с поэлементным делением удалены методы "a / b" и "b \ a" со скаляром "a" и вектором "b", которые были эквивалентны "a * pinv(b)";
применение для вызова BLAS и LAPACK "libblastrampoline (LBT)". OpenBLAS поставляется по умолчанию, но сборка образа системы с другими библиотеками BLAS/LAPACK не поддерживается. Вместо этого рекомендуется использовать механизм LBT для замены BLAS/LAPACK на иной имеющийся комплект библиотек;
поддержку "lu" новой стратегии поворота матрицы "RowNonZero()", которая выбирает первый ненулевой элемент поворота для использования с новыми арифметическими типами и для учебных целей;
поддержку любого нормированного векторного пространства "x", включая скаляры, в "normalize(x, p=2)";
уравнивание количества потоков BLAS по умолчанию с потоками CPU на архитектуре ARM и половиной числа потоков CPU на других архитектурах;
переработку в Printf сообщений об ошибках для строк неправильного формата для лучшей читаемости;
новую функцию "Profile.take_heap_snapshot(file)", которая записывает файл в формате ".heapsnapshot" на основе JSON, поддерживаемом в Chrome;
работу randn и randexp для любого типа AbstractFloat, определяющего rand;
открытие текущего ввода в редакторе при нажатии комбинации клавиш "Alt-e" в REPL. Содержимое (если оно изменено) будет выполнено при выходе из редактора;
замену текущего контекста модуля, активного в REPL, с помощью функции "REPL.activate(::Module)" или путём ввода модуля в REPL и нажатия комбинации клавиш "Alt-m";
вывод числа для каждого входа и выхода и сохранение результата в Out в режиме "нумерованной подсказки", который может быть активирован с помощью "REPL.numbered_prompt!()";
автодополнение с отображением доступных аргументов ключевого слова;
перемещение кода для решателя "SuiteSparse" в "SparseArrays.jl". Решатели теперь повторно экспортируются "SuiteSparse.jl";
доступность решателей "SuiteSparse" в качестве подмодулей "SparseArrays";
улучшение режимов защиты потоков UMFPACK и CHOLMOD за счёт исключения глобальных переменных и использования блокировок. Многопоточный "ldiv!" объектов UMFPACK теперь можно выполнять безопасно;
функцию "SparseArrays.allowscalar(::Bool)", которая позволяет отключать или включать скалярное индексирование разрежённых массивов. Эта функция предназначена для обнаружения случайного скалярного индексирования объектов "SparseMatrixCSC", что является распространённым источником проблем с производительностью;
новый режим для наборов тестов, который досрочно завершает тестовый запуск в случае сбоя или ошибки. Устанавливается либо через "@testset kwarg failfast=true", либо "export JULIA_TEST_FAILFAST=true". Подобное бывает необходимо в запусках CI для досрочного получения сообщений об ошибке;
распространение конфигурации пакета Distributed (активный проект, "LOAD_PATH", "DEPOT_PATH") при добавлении локальных рабочих процессов (например, с помощью "addprocs(N::Int)" или с помощью флага командной строки "--procs=N");
возвращение "addprocs" для локальных рабочих процессов аргумента с именем "env" для передачи переменных окружения рабочим процессам;
возвращение подстроки от m-й до n-й графемы в "s""graphemes(s, m:n)" в Unicode;
вывод пакета DelimitedFiles из системных библиотек. Теперь он распространяется как отдельный пакет, который должен быть явно установлен для использования;
автоматическое определение версии системной библиотеки libstdc++ в Linux. Если она новее, то происходит загрузка. Старое поведение загрузки встроенной libstdc++ независимо от версии системы можно восстановить, установив переменную окружения "JULIA_PROBE_LIBSTDCXX=0";
удаление "RPATH" из бинарного файла julia, что может привести в Linux к поломке библиотек, которым не удалось определить переменную "RUNPATH";
сокращение вывода "MethodError" и методов (например из "methods(my_func)") в соответствии с принципом вывода методов при трассировке стека.
Язык Julia был разработан в Массачусетском технологическом институте и представлен в 2012 году. В 2015 его создатели — доктор Вирал Шах, профессор Алан Эдельман, доктор Джефф Безансон, Стефан Карпински — совместно с Дипаком Винчи и Кено Фишером основали компанию Julia Computing. Язык используют более чем 10 тыс. компаний по всему миру, включая AstraZeneca, BlackRock, Google, Intel, Microsoft, Moderna, Pfizer.