Опубликован язык программирования Julia 1.11

Опубликован релиз языка программирования Julia 1.11, сочетающего такие качества как высокая производительность, поддержка динамической типизации и встроенные средства для параллельного программирования. Синтаксис Julia близок к MATLAB с заимствованием некоторых элементов из Ruby и Lisp. Метод манипуляции строками напоминает Perl. Код проекта распространяется под лицензией MIT.

Ключевые особенности языка:

  • Высокая производительность: одной из ключевых целей проекта является достижение производительности близкой к программам на языке Си. Компилятор Julia основан на наработках проекта LLVM и генерирует эффективный нативный машинный код для многих целевых платформ;
  • Поддержка различных парадигм программирования, включая элементы объектно-ориентированного и функционального программирования. Стандартная библиотека предоставляет в том числе функции для асинхронного ввода/вывода, управления процессами, ведения логов, профилирования и управления пакетами;
  • Динамическая типизация: язык не требует явного определения типов для переменных по аналогии со скриптовыми языками программирования. Поддерживается интерактивный режим работы;
  • Опциональная возможность явного указания типов;
  • Синтаксис, превосходно подходящий для численных вычислений, научных расчётов, систем машинного обучения и визуализации данных. Поддержка многих числовых типов данных и средств для распараллеливания вычислений.
  • Возможность прямого вызова функций из библиотек на языке Си без дополнительных прослоек.

Основные изменения в Julia 1.11:

  • Новые возможности языка
    • Добавлен тип Memory, который является низкоуровневой альтернативой типу Array. Тип Memory требует меньших затрат и имеет быстрый конструктор, являясь при этом альтернативой Array там, где не требуется полный набор его возможностей. Например, многомерные массивы. Во внутренней реализации, большая часть методов типа Array реализована поверх типа Memory, что существенно ускорило некоторые функции, например push.
    • Добавлено ключевое слово “public”. Идентификаторы, которые промаркированы как “public”, рассматриваются как внешний программный интерфейс. Идентификаторы с ключевым словом “export” рассматриваются похожим образом. Но основное различием между “public” и “export” в том, что имена, помеченные “public”, не включаются в контекст модуля при использования “using” в зависимых модулях.
    • Пакет ScopedValue реализует динамическую область видимости при использовании в параллельном программировании Threads/tasks.
    • Файл Manifest.toml теперь может быть переименован в формате Manifest-v{major}.{minor}.toml для использования конкретной версией Julia. Например файл Manifest-v1.11.toml будет использован версией 1.11, а файл Manifest.toml в той же директории будет использоваться прочими версиями Julia.
    • Добавлена поддержка Unicode 15.1.
  • Изменения в языке
    • В процессе прекомпиляции обработчик “atexit” запускается до формирования результирующего файла. Это позволяет пользователям безопасно завершать фоновое выполнение (например триггеры по таймеру или периодические оповещения), а также явно высвобождать ресурсы перед завершением программы.
    • Файлы покрытия кода и выделения памяти больше не формируются в процессе прекомпиляции. Кроме того, в этих режимах кэши pkgimage используются для пакетов, которые также не отслеживаются. Это означает, что тесты покрытия (по умолчанию для julia-actions/julia-runtest) используют кэши pkgimage для всех остальных пакетов, от которых зависит тестируемый. Это позволяет ускорить тестирование.
    • Указание пути в JULIA_DEPOT_PATH теперь обрабатывается иначе. При наличии одного пути, только этот путь будет вставлен в значение внутренней переменной DEPOT_PATH. Если последним символом является “:”, то переменная DEPOT_PATH получит значение, содержащее всё то, что было указано до “:”, а также перечень системных путей, где находится Julia.
    • Файлы кэша предварительной компиляции теперь можно перемещать, а их актуальность теперь проверяется с помощью хеша содержимого исходных файлов, а не с помощью “mtime”.
  • Улучшения компилятора/среды выполнения
    • Обновлена эвристика сборщика мусора, позволяющая работать со страницами памяти в целом вместо индивидуальных объектов.
    • Добавлена поддержка аннотирования Base.@assume_effects в коде.
  • Изменения параметров командной строки
    • Точка входа теперь строго определена как Main.main(args). Точка входа должна быть определена макросом @main (см. документацию). Если точка входа задана в скрипте, запускаемом в командной строке (например “julia script.jl или julia -e expr”), julia запустит функцию Main.main автоматически. Это сделано для унификации исполнения скриптов и их компиляции, когда загрузка кода может происходить для компиляции, а выполнение метода Main.main только на этапе запуска исполняемого файла. При использовании Julia в интерактивном режиме изменений нет. Весь код исполняется последовательно.
      Аргументы “–compiled-modules” и “–pkgimages” могут быть выставлены в режим existing, который заставляет Julia использовать существующие кэши, но не создавать новые.
    • Аргумент “–project” теперь может получать значение @script для указания размещения файла Project.toml относительно запускаемого скрипта. Например “–project=@script/foo” для поддиректории foo. Если ничего не указано, то есть “–project=@script”, это будет аналогично “–project=@.”, когда файл Project.toml ищется в текущей директории.
  • Многопоточные изменения
    • В макросе Threads.@threads можно указать режим планировщика :greedy, который удобен для неравномерной вычислительной нагрузки.
      Новая структура (со спецификатором public, но не export) “struct Base.Lockable{T, L<:AbstractLock}” представляет собой обёртку для упорядочивания параллельного доступа к элементам составных типов, в целом упрощая код.
  • Изменения системы сборки
    • Файл Makefile для сборки Julia и LLVM использует стратегии оптимизации PGO и LTO. См. contrib/pgo-lto/Makefile.
  • Новые библиотечные функции
    • Добавлены три новых типа в рамках идеи текста с аннотацией – Pair{Symbol, Any}, например ‘:lang => “en”‘ или ‘:face => :magenta’. Если это возможно, то аннотации сохраняются в процессе операций над строками, например конкатенции.
    • Конкретный тип AnnotatedString реализует AbstractString. Этот тип является обёрткой над строкой, позволяя добавить аннотацию по диапазону символов. Тип AnnotatedString широко используется в новой стандартной библиотеке StyledStrings для отображения информации на экране со стилем.
    • Конкретный тип AnnotatedChar реализует AbstractChar. Является обёрткой над символом и позволяет присоединить список аннотаций к нему.
    • Конкретный тип AnnotatedIOBuffer реализует IO, повторяет интерфейс типа IOBuffer, но имеет специализированные методы read/write для аннотирования потока. Может использоваться как построитель строк или как средство склейки аннотированных и не аннотированных строк.
    • Метод “in!(x, s::AbstractSet)” всегда возвращает true. Но если элемент x не входит в s, то он будет вставлен.
    • Новая функция Libc.mkfifo является обёрткой C-функции mkfifo для Unix платформ.
    • Метод “logrange(start, stop; length)” создаёт логарифмическую последовательность с указанным количеством, вместо фиксированного шага.
    • Методы “copyuntil(out, io, delim)” и “copyline(out, io)” копируют данные из потока io в поток out::IO.
    • Метод “eachrsplit(string, pattern)” возвращает итератор по разбитым элементам строки справа налево.
    • Метод Sys.username() возвращает имя текущего пользователя.
    • Методы Sys.isreadable(), Sys.iswritable() могут быть использованы для определения разрешений пользователя на чтение и запись данных.
    • Метод GC.logging_enabled() возвращает true если журналирование операций сборщика мусора включено через GC.enable_logging.
    • Тип IdSet теперь экспортируется из Base и является общедоступным.
    • Макрос “@time” теперь сообщает значение счётчика конфликтов блокировки, если используется ReentrantLock, который необходимо ожидать. А также добавлен макрос “@lock_conflicts”, которые возвращает этот счётчик.
    • Макрос Base.Cartesian.@ncallkw разработан по аналогии с Base.Cartesian.@ncall, но позволяет добавить аргументы в форме ключевых слов для вызова функции.
    • Новая функция Docs.hasdoc(module, symbol) сообщает имеет ли запрошенное имя symbol описания docstring.
    • Новая функция Docs.undocumented_names(module) возвращает имена недокументированных функций запрошенного модуля module.
  • Новые возможности известных методов
    • Метод invmod(n, T) для предопределённого целого типа T теперь вычисляет обратное по модулю целое n по новому алгоритму.
    • Метод invmod(n) предоставляет сокращённую форму вызова invmod(n, typeof(n)) для целых типов.
    • Метод replace(string, pattern…) теперь поддерживает опциональный аргумент IO для возврата значения в поток вместо возврата строки типа String.
    • Новые методы allequal(f, itr) и allunique(f, itr) с аргументом функции-предиката.
    • Метод sizehint!(s, n) теперь поддерживает опцию “shrink”, позволяющую отключить отсечку элементов.
    • Передача IOBuffer как аргумента stdout при порождении процессов, теперь работает с полной синхронизацией “wait” или “success”, поэтому в Base.BufferStream нет больше необходимости проверки доступности.
    • Метод “closewrite” больше не вызывается автоматически для переданного потока после закрытия процесса. Используйте метод “wait” для процесса, а затем принудительно вызывайте “closewrite”. Или используйте форму метода open с функций для автоматической обработки закрытия.
    • Метод “@timed” теперь дополнительно возвращает оценку времени компиляции и перекомпиляции, обусловленной нестабильностью типов.
    • Метод “filter” теперь может работать с NamedTuple.
    • Метод Iterators.cycle(iter, n) запускается на итераторе “iter” фиксированное n число раз.
    • Метод zero(::AbstractArray) применяется рекурсивно, например zero([[1,2],[3,4,5]]) порождает [[0,0],[0,0,0]] вместо генерации ошибки.
    • Метод include_dependency(path; track_content=true) подключает зависимости на основе хэш-значения прекомпилированного кода, а не mtime.
  • Изменения базовой библиотеки
    • Метод write(::IO, ::AbstractArray) используется для рекурсивного вызова методов “write” для каждого элемента массива, но теперь записывается представление в памяти каждого значения. Например, вызов write(io, ‘a’:’b’) запишет 4 байта каждого символа, вместо сокращенного представления UTF-8 для каждого из них. Новый формат совместим с Array, делая возможным использовать метод “read!” для обратного чтения значений.
    • Невозможно определить метод “length” для итераторов с состоянием в общем виде. В связи с потенциально некорректной работой итераторов Stateful, метод length(::Stateful) удалён.
    • StyledStrings
      • Новая стандартная библиотека для стилевого представления строк.
      • Структура Faces является контейнером стилевой информации (цвет, декораторы и пр.), а также предоставляет каркас удобного, расширяемого (via addface!), и адаптируемого (с применением пользовательских Faces.toml и loadfaces!) подхода к отображению содержимого со стилями.
      • Макрос @styled_str предоставляет удобный способ создания аннотированных строк AnnotatedString с различными атрибутами-стилями. Например, StyledStrings.addface!(:orange => StyledStrings.Face(foreground = 0xFF7700)) styled”{orange:this is orange text}”
    • Libdl
      • Новый тип LazyLibrary экспортируется из библиотеки Libdl для создания ленивых цепочек загрузки библиотек, изначально используемых в формате JLL.
    • LinearAlgebra
      • Метод cbrt(::AbstractMatrix{<:Real}) теперь возвращает матрицу действительных значений квадратных корней для входной матрицы действительных значений.
      • Метод вычисления собственных значений “eigvals/eigen(A, bunchkaufman(B)) and eigvals/eigen(A, lu(B))” использует алгоритмы Bunchkaufman (LDL) и LU декомпозиции B, соответственно, для эффективного вычисления обобщённых собственных значений (eigen: и eigenvectors) от A и B. Вторым аргументом метода передаётся результат методов bunchkaufman или lu.
      • Специализированный метод “eigvals/eigen(::Hermitian{<:Tridiagonal})”, который предназначен для симметричных тридиагональных матриц и использует средства LAPACK.
      • Структурированные матрицы теперь сохраняют оси родительских(для Symmetric/Hermitian/AbstractTriangular/UpperHessenberg), либо оси главных диагоналей (для ленточных матриц).
      • Методы bunchkaufman и bunchkaufman! теперь определены для типов AbstractFloat, Rational и их комплексных вариаций. Метод bunchkaufman теперь поддерживает типы Integer, внутренне преобразуя их к Rational{BigInt}. Добавлена функция inertia, которая вычисляет инерцию диагонального фактора процедуры BunchKaufman для объекта действительной симметричной или Эрмитовой матрицы. Для комплексных симметричных матриц, метод inertia только вычисляет количество собственных значений диагонального фактора.
      • Пакеты, который определяют метод матричного умножения mul! с сигнатурой mul!(::AbstractMatrix, ::MyMatrix, ::AbstractMatrix, ::Number, ::Number) больше не будут иметь неоднозначность, взаимодействуя с пакетом LinearAlgebra. Ранее при умножении возникали неоднозначности между пользовательским типом матрицы MyMatrix и структурированными матрицами, предоставляемыми пакетом LinearAlgebra, например AbstractTriangular. Подобные проблемы устранены для операций mul! с типами матрица-вектор.
      • Методы lu и issuccess(::LU) теперь поддерживают аргумент allowsingular. Если он имеет значение true, допустимая факторизация с фактором U с недостаточным рангом будет считаться успешной, а не выдавать ошибку. Такие факторизации теперь отображаются путем печати множителей вместе с пометкой “rank-deficient”, а не сообщения “Failed Factorization”.
    • Random
      • Метод rand теперь применим для типов, переданных в форме Tuple.
      • Метод rand теперь применим для типов, переданных в Pair.
      • Для начального запуска генератора случайных чисел RNG модуля Random теперь можно использовать отрицательные числа.
      • Инициализация генератора случайных чисел теперь может быть выполнена строкой, например seed!(rng, “a random seed”).
    • REPL
      • Нажатие на клавишу Tab для завершения подсказки теперь подсвечивается светлым шрифтом. Для выключения этого режима примените Base.active_repl.options.hint_tab_completes = false интерактивно или в скрипте startup.jl: if VERSION >= v”1.11.0-0″ atreplinit() do repl repl.options.hint_tab_completes = false end
        end
      • Meta-M с пустым приглашением теперь переключает контекстный модуль между предыдущим неосновным контекстным модулем и основным, упрощая переключение туда и обратно.
    • Dates
      • Недокументированная функция adjust больше не экспортируется, но задокументирована.
    • Statistics
      • Пакет Statistics теперь является обновляемым без всего комплекта Julia.
    • Distributed
      • Метод pmap теперь использует по-умолчанию CachingPool.
  • Устаревшие и удалённые методы
    • Методы Base.map, Iterators.map, и foreach с единственным аргументом больше не поддерживаются.
  • Внешние зависимости
    • Библиотека libuv обновлена с версии 1.44.2 до 1.48.0.
    • Метод tput больше не используется для проверки возможностей терминала. Он заменён средствами разбора terminfo, реализованными полностью на Julia.
    • Terminfo используется по умолчанию. Если в системе он отсутствует, то Julia может быть собрана с опцией Makefile WITH_TERMINFO=0.
  • Улучшения инструментов
    • CI теперь выполняет ограниченную автоматическую проверку типов во всех запросах слияния.
Release. Ссылка here.