Опубликован релиз языка программирования Julia 1.12, сочетающего такие качества как высокая производительность, поддержка динамической типизации и встроенные средства для параллельного программирования. Синтаксис Julia близок к MATLAB с заимствованием некоторых элементов из Ruby и Lisp. Метод манипуляции строками напоминает Perl. Код проекта распространяется под лицензией MIT.
Ключевые особенности языка:
- Высокая производительность: одной из ключевых целей проекта является достижение производительности близкой к программам на языке Си. Компилятор Julia основан на наработках проекта LLVM и генерирует эффективный нативный машинный код для многих целевых платформ;
- Поддержка различных парадигм программирования, включая элементы объектно-ориентированного и функционального программирования. Стандартная библиотека предоставляет в том числе функции для асинхронного ввода/вывода, управления процессами, ведения логов, профилирования и управления пакетами;
- Динамическая типизация: язык не требует явного определения типов для переменных по аналогии со скриптовыми языками программирования. Поддерживается интерактивный режим работы;
- Опциональная возможность явного указания типов;
- Синтаксис, превосходно подходящий для численных вычислений, научных расчётов, систем машинного обучения и визуализации данных. Поддержка многих числовых типов данных и средств для распараллеливания вычислений.
- Возможность прямого вызова функций из библиотек на языке Си без дополнительных прослоек.
Основные изменения в Julia 1.12:
- Новые возможности языка
- Экспериментальный параметр «—trim», позволяющий создавать более компактные бинарные файлы за счёт удаления кода, который не достижим из указанных точек входа. Точки входа можно помечать с помощью «Base.Experimental.entrypoint». С этой опцией может работать не весь код.
- Переопределение констант теперь чётко определено и следует семантике «world age«. Допустимы дополнительные переопределения (например, типов).
- В функцию «names» добавлен новый параметр «usings::Bool», заставляющий функцию вернуть все имена, видимые через «using».
- Семейство макросов «@atomic» теперь поддерживает синтаксис присваивания ссылок, например: «@atomic :monotonic v[3] += 4», который атомарно изменяет «v[3]» с семантикой монотонного упорядочения. Поддерживаемый синтаксис включает:
- атомарное чтение («x = @atomic v[3]»),
- атомарное присваивание («@atomic v[3] = 4»),
- атомарное изменение («@atomic v[3] += 2»),
- атомарное однократное присваивание («@atomiconce v[3] = 2»),
- атомарный обмен («x = @atomicswap v[3] = 2»),
- атомарную замену («x = @atomicreplace v[3] 2=>5»).
- Новый параметр «—task-metrics=yes», включающий сбор информации о времени выполнения каждой задачи, который можно включать/выключать и во время работы через «Base.Experimental.task_metrics(::Bool)». Доступные метрики:
- фактическое время выполнения задачи, включая компиляцию и сбор мусора («Base.Experimental.task_running_time_ns»),
- время от момента, когда задача начала выполняться до завершения(«Base.Experimental.task_wall_time_ns»).
- Поддержка Unicode 16.
- «Threads.@spawn» теперь принимает аргумент «:samepool» для указания того же пула потоков, что и вызывающий код. «Threads.@spawn :samepool foo()» — сокращение для «Threads.@spawn Threads.threadpool() foo()».
- Макрос «@ccall» теперь может принимать аргумент «gc_safe». Если он равен true, то во время вызова «ccall» рантайм может осуществлять сборку мусора параллельно.
- Изменения языка
- При замене метода эквивалентным по сигнатуре, существующий метод не удаляется. Вместо этого новый метод становится приоритетным. Если новый метод будет удалён, старый метод снова начнёт работать. Это полезно, например, в фреймворках тестирования с подменой (SparseArrays, Pluto, Mocking и др.), так как не нужно явно восстанавливать старый метод. В настоящее время для этой ситуации требуется повторная компиляция, но возможно в будущем удастся переиспользовать старые результаты.
- Развертывание макросов больше не будет сразу рекурсивно входить в выражения «Expr(:toplevel)» из макросов. Вместо этого развёртывание «:toplevel» будет отложено до времени выполнения. Это позволяет более поздним выражениям в том же «:toplevel» использовать макросы, определённые ранее.
- Тривиальные бесконечные циклы (такие как «while true; end») больше не считаются неопределённым поведением. Бесконечные циклы, в которых что-то происходит (например, с побочными эффектами или sleep), никогда не были и не являются неопределённым поведением.
- Одновременная пометка идентификатора как «public» и «export» теперь является ошибкой.
- Ошибки во время выполнения «getfield» теперь порождают новый тип исключений «FieldError» вместо общего «ErrorException».
- Макросы в позиции объявления функций теперь не требуют круглых скобок. Например, допустимо «function @main(args) … end», тогда как ранее требовалось «function (@main)(args) … end».
- Вызов «using» по имени пакета внутри самого пакета (особенно актуально для вложенных модулей) теперь явно использует этот пакет без просмотра Manifest и окружения, так же, как «..Name». Это лучше соответствует ожидаемому поведению.
- Улучшения компилятора/рантайма
- Сгенерированный LLVM промежуточный код (IR) теперь использует типы указателей вместо передачи указателей в форме целых чисел. Это касается «llvmcall»: встроенный LLVM IR следует обновить, заменив «i32″/»i64» на «i8*» или «ptr» и убрав ненужные конверсии «ptrtoint»/»inttoptr». Для совместимости IR с целочисленными указателями всё ещё поддерживается, но выдаёт предупреждение.
- Изменения параметров командной строки
- Флаг «-m/—module» можно передать для запуска функции «main» внутри пакета с набором аргументов. Эта функция должна быть объявлена через «@main», указывая, что это точка входа.
- Включение/отключение цветового вывода в Julia теперь можно контролировать с помощью переменных окружения «NO_COLOR» и «FORCE_COLOR«. Эти переменные также учитываются системой сборки Julia.
- «—project=@temp» запускает Julia с временным окружением.
- Новый параметр «—trace-compile-timing» выводит время компиляции каждого метода, который выводится «—trace-compile», в миллисекундах.
- «—trace-compile» теперь выводит перекомпилированные методы жёлтым цветом или добавляет комментарий, если цвет недоступен.
- Новый параметр «—trace-dispatch» выводит методы, которые динамически распределяются.
- Изменения многопоточности
- Julia теперь по умолчанию использует 1 «интерактивный» поток, в дополнение к 1 основному «рабочему» потоку, т.е. «-t1,1». Это означает, что основная задача и REPL (в интерактивном режиме), которые оба работают в потоке 1, теперь выполняются в интерактивном пуле. Цикл ввода-вывода libuv тоже работает в потоке 1, что обеспечивает эффективное использование рабочего пула, используемого «Threads.@spawn». Запрос ровно 1 потока («-t1″/»JULIA_NUM_THREADS=1») или 0 интерактивных потоков отключает интерактивный поток: «-t1,0», «JULIA_NUM_THREADS=1,0» или «-tauto,0». Запрос более 1 потока включает интерактивный поток; например, «-t2» эквивалентно «-t2,1». Напоминаем: буферы не следует привязывать к «threadid()».
- Определены новые типы для шаблона кода, который должен выполняться один раз на процесс — тип «OncePerProcess{T}» позволяет определить функцию, которая выполнится ровно один раз, когда её впервые вызовут, а затем будет всегда возвращать одно и то же значение типа «T» при последующих вызовах. Также существуют типы «OncePerThread{T}» и «OncePerTask{T}» для аналогичного использования с потоками или задачами.
- Изменения системы сборки
- Добавлены новые файлы Makefile для сборки Julia и LLVM с использованием BOLT (Binary Optimization and Layout Tool). См.
«contrib/bolt» и «contrib/pgo-lto-bolt».
- Добавлены новые файлы Makefile для сборки Julia и LLVM с использованием BOLT (Binary Optimization and Layout Tool). См.
- Новые библиотечные функции
- «logrange(start, stop; length)» создаёт диапазон с постоянным коэффициентом (ratio), а не постоянным шагом.
- Новая функция «isfull(c::Channel)» проверяет, будет ли блокироваться «put!(c, some_value)».
- «waitany(tasks; throw=false)» и «waitall(tasks; failfast=false, throw=false)» ждёт завершения нескольких задач одновременно.
- «uuid7()» создаёт UUID версии 7, соответствующий RFC 9562.
- «insertdims(array; dims)» вставляет одноэлементные размерности в массив — операция, обратная «dropdims».
- Новый тип «Fix» обобщает «Fix1/Fix2» для фиксации одного аргумента.
- «Sys.detectwsl()» проверяет, выполняется ли Julia внутри WSL в runtime.
- Новые возможности библиотек
- «escape_string» принимает дополнительные параметры «ascii=true» (для экранирования всех не-ASCII символов) и «fullhex=true» (для использования полного 4/8-значного hex-формата в u/U-экранировке, например для совместимости с C).
- «tempname» теперь может принимать строку суффикса, чтобы имя файла включало этот суффикс и он учитывался при уникальности.
- Объекты «RegexMatch» теперь можно использовать для создания «NamedTuple» и «Dict».
- «Lockable» теперь экспортируется.
- «Base.require_one_based_indexing» и «Base.has_offset_axes» теперь публичные.
- Добавлены новые функции «ltruncate», «rtruncate» и «ctruncate» для усечения строк до ширины текста, учитывая ширину символов.
- Функция «isless» (а значит, и «cmp», сортировка и т.д.) теперь поддерживается для нулемерных «AbstractArray».
- «invoke» теперь позволяет передавать «Method» вместо сигнатуры типа.
- «invoke» теперь принимает «CodeInstance» вместо типа, что может ускорить некоторые рабочие процессы плагинов компилятора.
- «Timer(f, …)» теперь наследует «липкость» (stickiness) родительской задачи при создании задач таймера, что можно переопределить новым аргументом «spawn». Это решает проблему, когда липкие порождённые задачи («@async») делали родителя липким.
- «Timer» теперь имеет читаемые свойства «timeout» и «interval», а также более описательный метод «show».
- «sort» теперь поддерживает кортежи «NTuple».
- «map!(f, A)» теперь сохраняет результаты в «A», как «map!(f, A, A)» или «A .= f.(A)».
- «setprecision» с аргументом-функцией (обычно через блок «do») теперь потокобезопасен. Другие формы следует избегать, и типы должны перейти к реализации, использующей «ScopedValue».
- Изменения стандартной библиотеки
- «gcdx(0, 0)» теперь возвращает «(0, 0, 0)» вместо «(0, 1, 0)».
- «fd» возвращает «RawFD» вместо «Int».
- Пакет JuliaSyntaxHighlighting
- Новый стандартный пакет для применения подсветки синтаксиса к коду Julia, использующий «JuliaSyntax» и «StyledStrings» для реализации функции «highlight», которая создаёт «AnnotatedString» с применённой подсветкой.
- Пакет LinearAlgebra.
- «rank» теперь может принимать матрицу «QRPivoted» для оценки ранга через QR-факторизацию.
- Добавлен ключевой параметр «alg» для «eigen», «eigen!», «eigvals» и «eigvals!» для типов самосопряжённых матриц (типовое объединение «RealHermSymComplexHerm»), позволяющий переключаться между различными алгоритмами извлечения собственных значений.
- Добавлена общая версия неблокированного разложения Холецкого с выборкой поворотов (вызывается через «cholesky[!](A, RowMaximum())»).
- Количество потоков BLAS по умолчанию теперь учитывает привязку процессов (process affinity), а не просто количество логических потоков системы.
- Добавлена функция «zeroslike», которая возвращает нулевые элементы для матриц с ленточным хранением. Пользовательские типы массивов могут специализировать эту функцию для правильного результата.
- Перемножение матриц «A * B» теперь вызывает «matprod_dest(A, B, T::Type)» для генерации приемника. Эта функция теперь публичная.
- Функция «haszero(T::Type)» используется для проверки, имеет ли тип «T» уникальный нулевой элемент, определённый как «zero(T)». Теперь она публичная.
- Добавлена функция «diagview», возвращающая представление (view) на конкретную диагональ матрицы «AbstractMatrix».
- Пакет Profile
- «Profile.take_heap_snapshot» теперь принимает новый параметр «redact_data::Bool», по умолчанию «true». Если разрешено, то содержимое объектов Julia (например, строк) не включается в снимок памяти.
- «Profile.print()» теперь окрашивает модули Base/Core/Package так же, как это делается в трассировках стека, а также пути (даже обрезанные) теперь кликабельны в терминалах, которые поддерживают ссылки URI и позволяют открыть указанный файл и строку в редакторе, заданном «JULIA_EDITOR».
- REPL
- Используя новую возможность «usings=true» в функции «names()», автодополнение в REPL может дополнять имена, видимые через «using».
- Автодополнение REPL теперь может завершать строки вида «[import|using] Mod: xxx|», например, завершать «using Base.Experimental: @op» до «using Base.Experimental: @opaque».
- REPL теперь выдаёт предупреждение, если имя обращается через модуль, который его не определяет (и не имеет подмодуля, который его определяет), и имя не является публичным в этом модуле. Например, «map» определён в Base, и выполнение «LinearAlgebra.map» в REPL теперь выдаст предупреждение при первом таком обращении.
- При выводе результата ввода в REPL вывод теперь обрезается до 20 KiB. Это не влияет на ручные вызовы «show», «print» и т.д.
- Автодополнение по символу «» теперь выводит соответствующий символ или эмоджи рядом с каждым соответствующим кодовым словом.
- Пакет Test
- Если набор тестов «DefaultTestSet» завершается с ошибкой, на экран выводится генератор случайных чисел (RNG) этого набора, чтобы помочь воспроизвести стохастическую ошибку, зависящую только от состояния RNG. Также можно задать RNG для набора тестов, передав параметр «rng» в макрос «@testset»:
julia using Test, Random @testset rng=Xoshiro(0x2e026445595ed28e, 0x07bb81ac4c54926d, 0x83d7d70843e8bad6, 0xdbef927d150af80b, 0xdbf91ddf2534f850) begin @test rand() == 0.559472630416976 end
- Если набор тестов «DefaultTestSet» завершается с ошибкой, на экран выводится генератор случайных чисел (RNG) этого набора, чтобы помочь воспроизвести стохастическую ошибку, зависящую только от состояния RNG. Также можно задать RNG для набора тестов, передав параметр «rng» в макрос «@testset»:
- Пакет InteractiveUtils
- Новые макросы «@trace_compile» и «@trace_dispatch» для выполнения выражений с параметрами «—trace-compile=stderr —trace-compile-timing» и «—trace-dispatch=stderr» соответственно.
- Внешние зависимости
- База данных terminal info («terminfo») теперь входит в поставку Julia по умолчанию, что улучшает работу REPL, когда «terminfo» недоступен в системе. Julia можно собрать без встраивания базы, используя параметр Makefile «WITH_TERMINFO=0».
- Улучшения инструментов
- Доступен профилировщик «wall-time» для пользователей, которым нужен профилировщик с выборкой, захватывающий задачи независимо от их состояния (запланированы/выполняются). Такой профилировщик позволяет профилировать задачи с интенсивным вводом-выводом и помогает обнаружить области сильной конкуренции в системе.
Источник: http://www.opennet.ru/opennews/art.shtml?num=64032