Mojo обновления

Mojo обновления надо регулярно отслеживать.

Пламенный привет посетителям этой страницы, пришедшим из социальных сетей, да и всем остальным тоже!

В апреле 2021-го года наблюдал удивительное явление: обильный поток посетителей из 4-х социальных сетей. В связи с этим настоятельно рекомендую всем неоднократно и регулярно посещать сайт rtbsm.ru — там в общих чертах изложена Российская Теннисная Балльная Система Марии (Шараповой).

Приглашаю всех полюбоваться на Фото и Видео красавицы Марии — надеюсь, что Вы поделитесь адресом сайта rtbsm.ru с друзьями и знакомыми.

Главная проблема — известить Марию, чтобы она лично как можно скорее заявила на весь мир о РТБСМ.

Mojo обновления в 2024-м году появляются регулярно: в среднем примерно раз в месяц, поэтому надо их отслеживать и обновлять свою версию MOJO.

Но разработка языка MOJO далека от завершения, поэтому я откладываю его освоение: Python и ранняя версия компилятора MOJO у меня установлены, однако на новом ноутбуке использую Windows 11, поэтому жду версию компилятора для Windows.

Версия от 13-го сентября 2024-го года: со страницы https://docs.modular.com/mojo/changelog#v245-2024-09-13 :

Mojo список изменений

Это список изменений в языке Mojo, стандартной библиотеке и инструментах.

Чтобы проверить текущую версию, запустите mojo --version. Чтобы обновить версию Mojo для вашего проекта с помощью magic менеджера пакетов, следуйте инструкциям в разделе Обновить пакет, чтобы обновить max пакет.

Переключиться на Magic

modular Средство командной строки устарело (см. Как его удалить - https://docs.modular.com/max/faq#if-you-installed-with-modular-deprecated-1 ). Мы рекомендуем Вам теперь управлять своими пакетами с помощью magic (https://docs.modular.com/magic), но Вы также можете использовать conda (https://docs.modular.com/magic/conda).

версия 24.5 (2024-09-13)

✨ Основные моменты

Вот краткое изложение некоторых основных изменений в этом выпуске, с более подробной информацией в следующих разделах:

  • Mojo теперь поддерживает совместимость с Python 3.12.
  • Набор автоматически импортируемых объектов (типов, псевдонимов, функций) в пользовательские программы Mojo был значительно сокращен. Это может нарушить работу существующего пользовательского кода, поскольку пользователям необходимо будет явно импортировать то, что они используют, для случаев, которые ранее автоматически включались ранее.
  • print() теперь требуется, чтобы его аргументы соответствовали Formattable признаку. Это позволяет по умолчанию выполнять эффективную запись на основе потока, избегая ненужных распределений кучи промежуточных строк.
  • Новая встроенная input() функция выводит необязательное приглашение и считывает строку из стандартного ввода тем же способом, что и Python.
  • Mojo теперь позволяет неявно определять переменные внутри fn так же, как это разрешено в def. Ключевое слово var по-прежнему разрешено, но теперь необязательно.
  • Mojo теперь выявляет нарушения «исключительности аргументов» из-за псевдонимов. Mojo требует, чтобы ссылки (включая неявные ссылки из-за аргументов borrowed/inout), если они изменяемы, ссылались на уникальные (не псевдонимы) объекты. В версии 24.5 это предупреждение, но в последующих версиях оно будет преобразовано в ошибку.
  • Mojo теперь поддерживает «условное соответствие», когда некоторые методы в структуре имеют дополнительные требования к свойствам, которых нет в самой структуре.
  • DTypePointerLegacyPointer, и Pointer были удалены. Используйте UnsafePointer вместо этого. Функции, которые ранее требовали DTypePointer теперь требуют эквивалента UnsafePointer. Для получения дополнительной информации об использовании указателей см. Небезопасные указатели в Руководстве Mojo.
  • Существует множество новых API стандартной библиотеки с новыми функциями для строк, коллекций и взаимодействия с файловой системой и средой. Изменения перечислены в разделе стандартная библиотека.
  • Расширение VS Code теперь поддерживает пакет MAX SDK для VS Code, который автоматически загружается расширением и используется для всех функций Mojo, включая сервер Mojo Language Server, Mojo debugger, Mojo formatter и многое другое.
  • mojo test теперь для запуска модульных тестов используется компилятор Mojo. Это решит проблемы с компиляцией, которые иногда возникали, а также улучшит общее время выполнения тестов.

Языковые изменения

  • Mojo теперь допускает неявные определения переменных внутри a fn тем же способом, который был разрешен в a def. Ключевое слово var по-прежнему разрешено и по-прежнему обозначает объявление новой переменной с областью видимости (как в def, так и в fn). Это делает fn и def более похожими, но они по-прежнему отличаются другими важными аспектами.
  • Mojo теперь диагностирует нарушения «эксклюзивности аргументов» из-за псевдонимов ссылок. Mojo требует, чтобы ссылки (включая неявные ссылки из-за borrowed/inout аргументов) имели уникальные ссылки (без псевдонимов), если они изменяемы. Это важно для безопасности кода, поскольку позволяет компилятору (и читателям кода) понимать, где и когда изменяется значение. Это также полезно для оптимизации производительности, поскольку позволяет компилятору знать, что доступ через неизменяемые ссылки не может изменяться за кулисами. Вот недопустимый пример.:
    fntake_two_strings(a: String,inout b: String):
    # Mojo knows 'a' and 'b' cannot be the same string.
       b += a
    fninvalid_access():
    var my_string = String()
    # error: passing `my_string` inout is invalid since it is also passed
    # borrowed.
      take_two_strings(my_string, my_string)
    

    Это похоже на проверку эксклюзивности Swift и на язык Rust иногда известный как «сглаживание xor или изменяемость». Тем не менее, Mojo детали реализации несколько отличаются, потому что время жизни встроено в типы.

    Это предупреждение в выпуске 24.5, но в последующих выпусках оно будет обновлено до ошибки.

    Примечание

    Эксклюзивность аргументов не применяется для типов, передаваемых через регистр. Они передаются методом копирования, поэтому не образуют псевдонимов.

  • Mojo теперь поддерживает «условные соответствия», когда некоторые методы структуры предъявляют дополнительные требования к характеристикам, которых нет у самой структуры. Это выражается через явно объявленный self тип.:
    structGenericThing[Type: AnyType]:# Works with anything
    # Sugar for 'fn normal_method[Type: AnyType](self: GenericThing[Type]):'
    fnnormal_method(self):...
    # Just redeclare the requirements with more specific types:
    fn needs_move[Type: Movable](self: GenericThing[Type],owned val: Type):
    var tmp = val^# Ok to move 'val' since it is Movable
    ...
    fnusage_example():
    var a = GenericThing[Int]()
      a.normal_method()# Ok, Int conforms to AnyType
      a.needs_move(42)# Ok, Int is movable
    var b = GenericThing[NonMovable]()
      b.normal_method()# Ok, NonMovable conforms to AnyType
    # error: argument type 'NonMovable' does not conform to trait 'Movable'
      b.needs_move(NonMovable())
    

    Условное соответствие также работает с методами dunder и другими вещами.

  • В качестве особой формы «условного соответствия» инициализаторы в структуре могут указывать конкретные привязки параметров, которые следует использовать в типе их self аргумента. Например:
    @value
    structMyStruct[size: Int]:
    fn__init__(inoutself: MyStruct[0]):pass
    fn__init__(inoutself: MyStruct[1], a: Int):pass
    fn__init__(inoutself: MyStruct[2], a: Int, b: Int):pass
    deftest(x: Int):
        a = MyStruct()# Infers size=0 from 'self' type.
        b = MyStruct(x)# Infers size=1 from 'self' type.
        c = MyStruct(x, x)# Infers size=2 from 'self' type.
    
  • Mojo теперь поддерживает именованные привязки результатов. Именованные привязки результатов полезны для прямого помещения результатов функций в выходной слот функции. Эта функция обеспечивает большую гибкость и гарантии при помещении результатов функций по сравнению с «гарантированной» оптимизацией именованных возвращаемых значений (NRVO). Если @register_passable результат привязан к имени, значение результата становится доступным как изменяемая ссылка.
    fnefficiently_return_string(b: Bool)-> String as output:
    if b:
            output ="emplaced!"
            mutate(output)
    return
    return"regular return"
    

    Если бы мы использовали временный объект для output вместо этого, нам нужно было бы переместиться в слот результата, что не сработало бы, если бы тип результата был неперемещаемым.

    В функции с именованным результатом return может использоваться без операнда для обозначения выхода из функции или может использоваться как обычно для указания возвращаемого значения функции. Компилятор выдаст ошибку, если результат не инициализирован во всех обычных случаях выхода из функции.

  • __setitem__() теперь работает со списками переменных аргументов, такими как:
    structYourType:
    fn__setitem__(inoutself,*indices: Int, val: Int):...
    

    Компилятор Mojo теперь всегда передаёт «новое значение», устанавливаемое с помощью последнего ключевого аргумента __setitem__(), например, превращая yourType[1, 2] = 3 в yourType.__setitem__(1, 2, val=3). Это исправляет ошибку № 248.

  • Менеджеры контекста Mojo, используемые в областях кода, которые могут вызывать проблемы, больше не нуждаются в определении «условной» функции выхода в форме fn __exit__(self, e: Error) -> Bool. Эта функция позволяет контекстному менеджеру условно перехватывать и обрабатывать ошибку и разрешать функции продолжать выполнение. Это полезно для некоторых приложений, но во многих случаях условный выход делегируется функции безусловного выхода fn __exit__(self).Конкретно, это позволяет определять with области, которые безоговорочно распространяют внутренние ошибки, позволяя использовать такой код, как:
    defmight_raise()-> Int:
    ...
    deffoo()-> Int:
    with ContextMgr():
    return might_raise()
    # no longer complains about missing return
    defbar():
    var x: Int
    with ContextMgr():
            x = might_raise()
    print(x)# no longer complains about 'x' being uninitialized
    
  • async функции теперь поддерживают результаты только для памяти (например, StringList, и т.д.) И raises. Соответственно, оба варианта Coroutineи RaisingCoroutine были изменены на принятие AnyType вместо AnyTrivialRegType. Это означает типы результатов async функций не обязательно должны быть Movable.
    asyncfnraise_or_string(c: Bool) raises -> String:
    if c:
    raise"whoops!"
    return"hello world!"
    

    Обратите внимание, что async функции пока не поддерживают косвенные вызовы, refрезультаты, и конструкторы.

  • В Reference типе (и многих итераторах) теперь используются параметры только для вывода для представления изменчивости в течение их жизненного цикла, что упрощает интерфейс.
  • Переменная среды MOJO_PYTHON может указывать на исполняемый файл, чтобы привязать Mojo к определенной версии:
    exportMOJO_PYTHON="/usr/bin/python3.11"
    

    Или виртуальная среда, позволяющая всегда иметь доступ к этим модулям Python:

    exportMOJO_PYTHON="~/venv/bin/python"
    

    MOJO_PYTHON_LIBRARY все еще существует для сред с динамическим libpython но нет исполняемого файла Python.

  • Семантика псевдонимов указателей в Mojo изменилась. Изначально Mojo использовал семантику псевдонимов указателей и производных указателей, как в C. Однако семантика C содержит много истории и «балласта», которые не нужны в Mojo и усложняют оптимизацию компилятора. В целом язык обеспечивает более строгий набор инвариантов для псевдонимов указателей с учётом времени жизни и эксклюзивных изменяемых ссылок на значения и т. д.Теперь запрещено преобразовывать значение, не являющееся указателем, полученное из указателя, выделенного Mojo, например целочисленный адрес, в значение, являющееся указателем. «Полученное» означает, что биты значения, не являющегося указателем, совпадают с битами исходного значения указателя. Соответственно, конструктор UnsafePointer с ключевым словом address в качестве аргумента был удалён.По-прежнему возможно выполнить это преобразование в определенных случаях, когда это абсолютно необходимо, например, для взаимодействия с другими языками, такими как Python. В этом случае компилятор делает два предположения: любой указатель, полученный из значения, не типизированного по указателю, не является псевдонимом какого-либо указателя, полученного по Mojo, и что любые вызовы внешних функций оказывают произвольное влияние на память.
  • await теперь его использует сопрограмма on. Это подтверждает неизменность того, что сопрограммы можно ожидать только один раз.

Изменения в стандартной библиотеке

  • builtin пакет:
    • Набор автоматически импортируемых объектов (типов, псевдонимов, функций) в пользовательские программы Mojo был значительно сокращен. Раньше, при обработке модуля builtin, все объекты в следующих модулях включались автоматически:memorysysosutilspythonbitrandommathbuiltincollectionsТеперь в пользовательские программы Mojo автоматически импортируются только явно перечисленные объекты в prelude/__init__.mojo. Это приведет к поломке большого количества пользовательского кода, поскольку пользователям нужно будет явно импортировать то, что они используют, для случаев, которые ранее обычно включались ранее (таких как OptionalVariant, и функций, таких как abort()alignof()bitcast()bitwidthof() external_call()simdwidthof() sizeof(),,,,,,,,,,,,,,,,,,, и,,,).
    • Некоторые типы из модуля builtin были перемещены в другие модули для большей ясности, что стало возможным благодаря наличию модуля prelude, который может повторно экспортировать символы из модулей, отличных от builtin.В частности, builtin.string модуль был перенесен в collections.string.
  • Ввод и вывод:
    • Добавлена встроенная функция input(), которая работает так же, как Python. (PR #3392)
      name =input("Enter your name: ")
      print("Hello, "+ name +"!")
      

      Если пользователь введёт «Mojo», он получит ответ «Привет, Mojo!»

      При запуске функции input() с JIT-компиляцией возникает известная проблема (см. проблему #3479).

    • print() Теперь требуется, чтобы аргументы соответствовали признаку Formattable . Это позволяет по умолчанию выполнять эффективную потоковую запись, избегая ненужного выделения промежуточных строк в памяти.Ранее print() требуемые типы соответствовали Stringable. Это означало, что для выполнения вызова типа print(a, b, c) были отключены по крайней мере три отдельных выделения кучи строк для хранения отформатированных значений ab и c соответственно. Общее количество распределений могло бы быть намного выше, если бы, например, a.__str__() было реализовано объединение полей a, как в следующем примере:
      structPoint(Stringable):
      var x: Float64
      var y: Float64
      fn__str__(self)-> String:
      # Performs 3 allocations: 1 each for str(..) of each of the fields,
      # and then the final returned `String` allocation.
      return"("+str(self.x)+", "+str(self.y)+")"
      

      Тип, подобный приведенному выше, может перейти к дополнительной реализации Formattable со следующими изменениями:

      structPoint(Stringable, Formattable):
      var x: Float64
      var y: Float64
      fn__str__(self)-> String:
      return String.format_sequence(self)
      fnformat_to(self,inout writer: Formatter):
              writer.write("(",self.x,", ",self.y,")")
      

      В приведенном выше примере, String.format_sequence() используется для создания String из типа, который реализует Formattable. Этот шаблон реализации Stringable реализации типа с точки зрения его Formattable реализации сводит к минимуму шаблонность и дублирование кода, сохраняя обратную совместимость с требованиями часто используемой str() функции.

      Примечание

      Ошибка, отображаемая при передаче типа, который не реализуется Formattable в print(), в настоящее время не полностью описывает основную причину:

      error: invalid call to 'print': callee with non-empty variadic pack argument expects 0 positional operands, but 1 was specified
         print(point)
         ~~~~~^~~~~~~
      

      Если вы видите приведенную выше ошибку, убедитесь, что все типы аргументов реализованы Formattable.

    • debug_assert() теперь также требуется, чтобы его message аргумент соответствовал Formattable.
    • Добавлено TemporaryDirectory в модуле tempfile. (PR 2743)
    • Добавлено NamedTemporaryFile в модуле tempfile. (PR 2762)
  • String и друзья:
    • builtin.string Модуль был перемещен в collections.string.
    • Добавлен String.format() метод. (PR #2771)Поддерживает автоматическую и ручную индексацию *args.Примеры:
      print(
        String("{1} Welcome to {0} {1}").format("mojo","")
      )
      #  Wecome to mojo 
      
      print(String("{} {} {}").format(True,1.125,2))
      #True 1.125 2
      
    • String.format() теперь поддерживаются флаги преобразования !s и !r, позволяющие выполнять str() и repr() преобразования в строках формата. (PR #3279)Пример:
      String("{} {!r}").format("Mojo","Mojo")
      # "Mojo 'Mojo'"
      String("{0!s} {0!r}").format("Mojo")
      # "Mojo 'Mojo'"
      
    • Класс String теперь имеет методы rjust()ljust(), и center() для возврата строки с выравниванием по ширине и по символу заполнения. (PR #3278)
    • Функция atol() теперь корректно поддерживает ведущие подчёркивания (например, atol("0x_ff", 0)), когда указана или выводится соответствующая база (основание 0). Целочисленные литералы, отличные от десятичной системы счисления, в соответствии с Целочисленными литералами Python. (PR #3180)
    • Добавлен метод unsafe_cstr_ptr() для String и StringLiteral, который возвращает UnsafePointer[C_char] для удобной совместимости с API-интерфейсами C.
    • Добавлен метод byte_length() в StringStringSlice, и StringLiteral и удалены их частные методы _byte_length(). Добавлен комментарий к методу String.__len__(), что в будущем он будет возвращать длину в кодовых точках Юникода, и StringSlice.__len__() теперь возвращает длину в кодовых точках Юникода. (PR #2960)
    • Добавлен новый псевдоним типа StaticString . Его можно использовать вместо StringLiteral для строковых аргументов во время выполнения.
    • Добавлен StringSlice инициализатор, который принимает StringLiteral.
    • Конструкторы StringRef из DTypePointer.int8 были изменены таким образом, чтобы принимать UnsafePointer[C_char] в качестве параметра, что отражает их использование для совместимости с API-интерфейсами C.
    • Продолжен переход к UnsafePointer и типу беззнаковых байтов для строк:
      • String.unsafe_ptr() теперь возвращает UnsafePointer[UInt8] (было UnsafePointer[Int8])
      • StringLiteral.unsafe_ptr() теперь возвращает UnsafePointer[UInt8] (было UnsafePointer[Int8])
  • UnsafePointer и другие изменения ссылочного типа:
    • DTypePointerLegacyPointer и Pointer были удалены. Вместо них используйте UnsafePointer. Дополнительную информацию об использовании указателей см. в разделе Небезопасные указатели в руководстве Mojo.Функции, которые раньше принимали DTypePointer теперь принимают эквивалент UnsafePointer. Краткое правило для преобразования DTypePointer в UnsafePointer:
      DTypePointer[type]-> UnsafePointer[Scalar[type]]
      

      Могут быть места, где у вас есть код формы:

      fnf(ptr: DTypePointer):
      

      что эквивалентно DTypePointer[*_]. В этом случае вам нужно будет добавить параметр type только для вывода:

      fn f[type: DType,//](ptr: UnsafePointer[Scalar[type]]):
      

      потому что мы не можем иметь несвязанный параметр внутри структуры.

      Также могут быть места, где вы используете DTypePointer[Scalar[DType.invalid/index]], и было бы логично заменить их на UnsafePointer[NoneType/Int]. Но поскольку это не UnsafePointer для хранения Scalar, вам, возможно, придётся rebind/bitcast для соответствующих типов.

    • Методы DTypePointer load() и store() были перенесены в UnsafePointer.
    • UnsafePointer теперь поддерживаются strided_load()strided_store()gather(), и scatter() когда базовым типом является Scalar[DType].
    • Глобальные функции для работы с UnsafePointer стали методами благодаря использованию условных соответствий:
    • Метод UnsafePointer.offset() устарел и будет удалён в следующей версии. Вместо него используйте арифметику указателей.
      new_ptr = ptr.offset(1)
      

      Становится:

      new_ptr = ptr +1
      
    • UnsafePointer теперь есть alignment параметр для указания статического выравнивания указателя. Следовательно, UnsafePointer.alloc() больше не принимает параметр выравнивания, и выравнивание должно быть указано в типе.
      UnsafePointer[type].alloc[alignment](x)# now becomes
      UnsafePointer[type, alignment].alloc(x)
      
    • UnsafePointer появился новый exclusive: Bool = False параметр. Если для этого параметра установлено значение true, компилятор понимает, что пользователь знает, что этот указатель и все производные от него указатели имеют исключительный доступ к базовому выделению памяти. Компилятор не гарантирует, что будет что-то делать с этой информацией.
    • Больше нельзя преобразовывать (неявно или явно) из Reference в UnsafePointer. Вместо UnsafePointer(someRef) используйте UnsafePointer.address_of(someRef[]) для явного указания в коде, что UnsafePointer получает адрес того, на что указывает ссылка.
  • Изменения в совместимости Python:
    • Mojo теперь поддерживает совместимость с Python 3.12.
    • Теперь можно создать вложенный PythonObject из списка или кортежа объектов Python:
      var np = Python.import_module("numpy")
      var a = np.array([1,2,3])
      var b = np.array([4,5,6])
      var arrays = PythonObject([a, b])
      assert_equal(len(arrays),2)
      

      Также позволяет использовать более удобный синтаксис вызова:

      var stacked = np.hstack((a, b))
      assert_equal(str(stacked),"[1 2 3 4 5 6]")
      

      (PR # 3264)

    • Доступ к локальным модулям Python с помощью Python.add_to_path(".") больше не требуется. Теперь он ведет себя так же, как Python. Вы можете получить доступ к модулям в той же папке, что и целевой файл.:
      • mojo run /tmp/main.mojo можно получить доступ /tmp/mymodule.py
      • mojo build main.mojo -o ~/myexe && ~/myexe можно получить доступ ~/mymodule.py
  • Коллекции:
    • List значения теперь сопоставимы по равенству с == и !=, когда их тип элемента сопоставим по равенству. (PR # 3195)
    • Optional значения теперь сопоставимы по равенству с == и !=, когда их тип элемента сопоставим по равенству.
    • Добавлен новый Counter словарный тип, соответствующий большинству функций Python one. (PR # 2910)
    • Dict теперь реализует setdefault() функцию, которая получает значение из словаря по ключу или устанавливает значение по умолчанию, если его нет. (PR #2803)
    • Dict теперь поддерживает popitem(), который удаляет и возвращает последний элемент в Dict. (PR #2701)
    • Добавлена Dict.__init__() перегрузка для указания начальной ёмкости. (PR #3171)Ёмкость должна быть степенью двойки и больше или равна 8.Это позволяет ускорить инициализацию, пропуская этапы постепенного роста.

      Пример:

      var dictionary = Dict[Int,Int](power_of_two_initial_capacity =1024)
      # Insert (2/3 of 1024) entries
      
    • ListLiteral теперь поддерживает __contains__(). (PR #3251)
  • Утилиты файловой системы и среды:
    • Path.home() был добавлен для возврата пути к домашнему каталогу пользователя.
    • os.path.expanduser() и pathlib.Path.exapanduser() были добавлены для того, чтобы можно было расширить ~ с префиксом в String или Path с помощью домашнего пути пользователя:
      import os
      print(os.path.expanduser("~/.modular"))
      # /Users/username/.modular
      print(os.path.expanduser("~root/folder"))
      # /var/root/folder (on macos)
      # /root/folder     (on linux)
      
    • os.path.split() добавлено для разделения пути на head, tail:
      import os
      head, tail = os.path.split("/this/is/head/tail")
      print("head:", head)
      print("tail:", tail)
      # head: /this/is/head
      # tail: tail
      
    • os.makedirs() и os.removedirs() добавлены для создания и удаления вложенных каталогов:
      import os
      path = os.path.join("dir1","dir2","dir3")
      os.path.makedirs(path, exist_ok=True)
      os.path.removedirs(path)
      
    • Модуль pwd был добавлен для доступа к пользовательской информации в /etc/passwd в системах POSIX. Он работает по той же логике, что и Python:
      import pwd
      import os
      current_user = pwd.getpwuid(os.getuid())
      print(current_user)
      # pwd.struct_passwd(pw_name='jack', pw_passwd='********', pw_uid=501,
      # pw_gid=20, pw_gecos='Jack Clayton', pw_dir='/Users/jack',
      # pw_shell='/bin/zsh')
      print(current_user.pw_uid)
      # 501
      root = pwd.getpwnam("root")
      print(root)
      # pwd.struct_passwd(pw_name='root', pw_passwd='*', pw_uid=0, pw_gid=0,
      # pw_gecos='System Administrator', pw_dir='/var/root', pw_shell='/bin/zsh')
      
  • Другие новые возможности и сопутствующие функции:
    • Добавлена черта ExplicitlyCopyable для обозначения типов, которые можно копировать явно, но которые могут не поддерживаться неявным копированием.Это поддерживает работу по отказу от неявной копируемости типов коллекций стандартной библиотеки, которая может привести к непреднамеренным дорогостоящим копиям.
    • Добавлен Identifiable признак, используемый для описания типов, реализующих методы __is__() и __isnot__() trait. (PR #2807)
    • Типы, соответствующие Boolable (то есть реализующие __bool__()), больше не преобразуются неявно в Bool. Для типов, в которых требуется такое поведение, вводится новая черта ImplicitlyBoolable.
  • Разное:
    • NoneType Теперь это обычный тип стандартной библиотеки, а не псевдоним для необработанного типа MLIR.Подписи функций, написанные как fn() -> NoneType, должны перейти к записи как fn() -> None.
    • Теперь у Mojo есть UInt тип для моделирования целых чисел без знака (скалярных) с шириной, зависящей от платформы. UInt реализует большинство арифметических операций, которые имеют смысл для целых чисел, за заметным исключением __neg__(). Встроенные функции, такие как min()/max(), а также math функции, такие как ceildiv()align_down(), и align_up() также реализованы для UInt.
    • Теперь, когда у нас есть UInt тип, используйте его для представления возвращаемого типа хэша. В общем случае хэши должны быть целыми числами без знака, а также могут привести к повышению производительности в определенных случаях.
    • Добавлен C_char псевдоним типа в sys.ffi.
    • sort() теперь поддерживается stable параметр. Его можно вызвать с помощью
      sort[cmp_fn, stable=True](list)
      

      Для работы алгоритма требуется ()O(N) вспомогательной памяти. При выделении дополнительной памяти происходит сбой, программа завершает работу.

    • sort() больше не выполняется LegacyPointer, поскольку этот тип теперь удален.
    • Добавлена oct() встроенная функция для форматирования целых чисел в восьмеричном формате. (PR # 2914)
    • Добавлены функции assert_is() и assert_is_not() тестирования в testing модуль.
    • В math пакет теперь входят константы pie и tau (закрывает выпуск #2135).
    • ulp Функция из numerics была перенесена в math модуль.
    • bit модуль теперь поддерживает bit_reverse()byte_swap() и pop_count() для Int типа. (PR # 3150)
    • Несколько bit функций были переименованы для большей ясности:
    • Slice теперь использует OptionalReg[Int] для start и end и реализует конструктор, который принимает необязательные значения. Slice._has_end() также был удалён, поскольку срез без конца теперь представлен пустым вариантом Slice.end (PR #2495)
      var s = Slice(1,None,2)
      print(s.start.value())# must retrieve the value from the optional
      
    • Аргумент rank для algorithm.elementwise() больше не требуется и выводится только по умолчанию.
    • time.now() Функция устарела. Пожалуйста, используйте time.perf_counter() или time.perf_counter_ns вместо этого.
    • SIMD построение из Bool было ограничено DType.bool типом данных.

Изменения в инструменте

  • mojo test новые функции и изменения:
    • mojo test Теперь для запуска модульных тестов используется компилятор Mojo. Это позволит устранить проблемы с компиляцией, которые иногда возникали, а также сократит общее время тестирования, поскольку мы будем компилировать модульные тесты только один раз перед их выполнением.Эти изменения не распространяются на doctests из-за их иной семантики.
    • mojo test Команда теперь принимает --filter параметр, который сузит набор собираемых и выполняемых тестов. Строка фильтра представляет собой расширенное регулярное выражение POSIX.
    • Команда mojo test теперь поддерживает использование тех же параметров компиляции, что и mojo build.
    • Теперь вы можете отлаживать модульные тесты с помощью mojo test, передав --debug флаг. Поддерживаются большинство флагов отладки; запустите mojo test --help для получения полного списка.Отладка doctests в настоящее время не поддерживается.
  • Новые функции и изменения Mojo debugger:
    • mojo debug --rpc Команда была переименована в mojo debug --vscode, которая теперь может управлять несколькими окнами VS Code.
    • Отладчик Mojo теперь поддерживает break-on-raise команду, которая указывает отладчику останавливаться при выполнении любых raise инструкций. Аналогичные функции были добавлены в отладчик в VS Code.
    • Отладчик Mojo теперь скрывает аргументы искусственной функции __result__ и __error__, созданные компилятором для кода Mojo.
  • Изменения в поддержке VS Code:
    • Расширение VS Code теперь поддерживает пакет MAX SDK для VS Code, который автоматически загружается расширением и используется для всех функций Mojo, включая сервер Mojo Language Server, Mojo debugger, Mojo formatter и многое другое.
    • На сервер Mojo Language в VS Code добавлен прокси, который более корректно обрабатывает сбои.
  • Сервер Mojo Language Server больше не устанавливает . в качестве символа фиксации для автозаполнения.

❌ Удалено

  • Поддержка устаревшей fn __init__(...) -> Self: формы была удалена из компилятора, пожалуйста, переключитесь на использование fn __init__(inout self, ...): вместо этого.
  • Встроенный tensor модуль удален. Идентичная функциональность доступна в max.tensor, но обычно рекомендуется использовать структуры из buffer модуля, когда это возможно.
  • УдаленоString.unsafe_uint8_ptr()String.unsafe_ptr() теперь возвращает то же самое.
  • Удалено StringLiteral.unsafe_uint8_ptr() и StringLiteral.as_uint8_ptr().
  • УдаленоSIMD.splat(value: Scalar[type]). Вместо этого используйте конструктор для SIMD.
  • Удалены SIMD.{add,mul,sub}_with_overflow() методы.
  • Удалены методы SIMD.min() и SIMD.max(). Идентичная функциональность доступна с помощью встроенных функций min() и max().
  • Удалены предупреждения сервера Mojo Language о неиспользуемых аргументах функции.
  • Run Mojo File in Dedicated Terminal действие удалено, и оно Run Mojo File всегда будет открывать специальный терминал для каждого файла mojo, чтобы гарантировать правильную среду.

️ Исправлено

  • Исправлен сбой на языковом сервере Mojo при импорте текущего файла.
  • Исправлен сбой при указании аргументов ключевого слова variadic без выражения типа в def функциях, например:
    deffoo(**kwargs):...# now works
    
  • Mojo теперь печатает ref аргументы и результаты в сгенерированной документации корректно.
  • # 1734 - Вызов __copyinit__ self вызывает сбой.
  • # 3142 - [QoI] Сбивающий с толку __setitem__ метод завершается ошибкой «должен быть изменяемым».
  • # 248 - [Функция] Позволяет __setitem__ принимать переменные аргументы
  • # 3065 - Исправлено некорректное поведение SIMD.__int__ для неподписанных типов
  • # 3045 - Отключить неявные маршруты преобразования SIMD с помощью Bool
  • # 3126 - Список [ОШИБОК] не работает во время компиляции.
  • #3237 - [ОШИБКА] Разница между __getitem__ и [.] оператором.
  • # 3336 - Исправлены устаревшие ссылки на let в документации REPL.
  • Расширение VS Code больше не кэширует информацию о выбранном MAX SDK, что вызывало проблемы при внесении изменений в SDK.
  • Отладчик Mojo теперь перестает показывать ложные предупреждения при анализе замыканий.

Версия от 7-го июня 2024-го года:

версия 24.4 (2024-06-07)

✨ Основные моменты

Важные темы для этого выпуска:

  • Улучшена производительность и простота использования def функций.
  • Продолжена унификация стандартных библиотечных API вокруг UnsafePointer типа.
  • Множество улучшений качества жизни для стандартных типов библиотечных коллекций.
  • Значительные улучшения производительности при вставке в Dict. Производительность по этому показателю всё ещё не такая, какой мы хотели бы её  видеть, но она значительно улучшена.
  • Новый @parameter for механизм для выражения циклов времени компиляции, который заменяет более ранний (и менее надёжный) @unroll декоратор.
  • Новые страницы руководства Mojo по потоку управления, тестированию и использованию небезопасных указателей.

На странице, адрес которой приведен чуть ниже, вверху правой колонки можно посмотреть номер новой версии Mojo и дату её публикации, а в основном тексте перечислены особенности новой версии.

Привожу информацию со страницы https://docs.modular.com/mojo/changelog :

  • Проект
  • Журнал изменений

Журнал изменений Mojo

Это текущий список существенных изменений языка и инструментов Mojo. Он не включает все внутренние изменения реализации.

Обновите Моджо

Если у Вас ещё нет Mojo, см. руководство по началу работы .

Чтобы увидеть свою версию Mojo, запустите это:

mojo --version
Чтобы обновить Mojo, сначала обновите modular , а затем запустите это:
modular update mojo

v24.3 (02.05.2024 )

✨ Основные моменты

  • AnyPointerбыл переименован в UnsafePointer и теперь является предпочтительным типом небезопасного указателя Mojo. Он имеет несколько улучшений, в том числе:
    • Тип элемента теперь может быть любым: для этого не требуется Movable.
    • По этой причине take_value()методы emplace_value(), и move_into() были заменены на функции верхнего уровня и переименованы. Новые функции:
    • Новая destroy_pointee() функция запускает деструктор указателя.
    • UnsafePointerможет быть инициализирован непосредственно из Reference with UnsafePointer(someRef)и преобразован в ссылку с помощью yourPointer[]. Оба выводят тип элемента и адресное пространство. Обратите внимание: когда вы преобразуете указатель в ссылку, Mojo не может отслеживать время жизни исходного значения. Таким образом, полученная ссылка не безопаснее исходного указателя.
  • Все типы указателей подверглись некоторой очистке, чтобы сделать их более согласованными, например, unsafe.bitcast() глобальная функция теперь является согласованным bitcast() методом для указателей, который может преобразовывать тип элемента и адресное пространство.
  • Улучшения в поддержке переменных аргументов.
    • Аргументы гетерогенного пакета с вариациями теперь надежно работают даже с типами памяти и имеют более удобный для использования API, определенный типом VariadicPack. Например, упрощенную версию printможно реализовать так:
      fnprint[T: Stringable,*Ts: Stringable](first: T,*rest:*Ts):
          print_string(str(first))
      @parameter
      fn print_elt[T: Stringable](a: T):
              print_string(" ")
              print_string(a)
          rest.each[print_elt]()
      
    • Mojo теперь поддерживает объявление функций, которые имеют как необязательные, так и переменные аргументы, как позиционные, так и только ключевые слова. Например, теперь это работает:
      fnvariadic_arg_after_default(
        a: Int, b: Int =3,*args: Int, c: Int, d: Int =1,**kwargs: Int
      ):...
      

      Позиционные вариационные параметры также работают при наличии необязательных параметров. То есть:

      fn variadic_param_after_default[e: Int, f: Int =2,*params: Int]():
      pass
      

      Обратите внимание, что параметры ключевого слова с переменным числом вариантов пока не поддерживаются.

    Для получения дополнительной информации см. аргументы Variadic в Руководстве Mojo.

  • Команды mojo buildи mojo runтеперь поддерживают -gопцию. Этот более короткий псевдоним эквивалентен написанию --debug-level full. Эта опция также доступна в mojo debugкоманде, но уже используется по умолчанию.
  • Было добавлено множество новых API стандартных библиотек, в том числе множество вкладов сообщества. Изменения перечислены в разделе стандартной библиотеки.
  • В Руководстве Mojo появилась новая страница «Типы» .

Языковые изменения

  • Некоторые методы dunder, которые принимают индексы ( __getitem__()__setitem__()и __refitem__()) или имена ( __getattr__()и __setattr__()), теперь могут принимать индекс или имя в качестве значения параметра, а не значения аргумента. Это становится возможным, когда вы определяете один из этих методов без каких-либо аргументов, кроме self(для метода получения) или selfзаданного значения (для метода установки).Это позволяет использовать типы, индексация которых может осуществляться только с помощью параметров, а также такие вещи, как следующий пример, в котором имя атрибута передается в качестве параметра, чтобы имена атрибутов можно было проверить во время компиляции.
    structRGB:
    fn __getattr__[name: StringLiteral](self)-> Int:
    @parameter
    if name =="r":return...
    elif name =="g":return...
    else:
               constrained[name =="b","can only access with r, g, or b members"]()
    return...
    var rgb = RGB()
    print(rgb.b)# Works
    print(rgb.q)# Compile error
    
  • Mojo теперь позволяет пользователям фиксировать расположение исходного кода и динамически вызывать расположение функций с помощью встроенных функций __source_location()и __call_location(). Например:
    @always_inline
    fnmy_assert(cond: Bool, msg: String):
    ifnot cond:
    var call_loc = __call_location()
    print("In", call_loc.file_name,"on line",str(call_loc.line)+":", msg)
    fnmain():
        my_assert(False,"always fails")# some_file.mojo, line 193
    

    Это печатает » In /path/to/some_file.mojo on line 193: always fails«. Обратите внимание, что __call_location()работает только в функциях @always_inlineили @always_inline("nodebug"). Он дает неправильные результаты, если его поместить в @always_inlineфункцию, вызываемую из функции @always_inline("nodebug").

    Ни один из __source_location()них не __call_location()работает при вызове в контексте параметра. Например:

    @always_inline
    fnmystery_location()-> String:
    var loc = __call_location()
    returnstr(loc.file_name)
    defmain():
    alias doesnt_work = mystery_location()# <unknown location in parameter context>
    

Изменения в стандартной библиотеке

⭐️ Новинка

  • List имеет несколько новых методов:
    • pop(index) для удаления элемента по определенному индексу. По умолчанию List.pop() удаляет последний элемент в списке. ( @LJ-9801 , исправления #2017 )
    • resize(new_size)для изменения размера списка без необходимости указания дополнительного значения. ( @mikowals , исправления #2133 )
    • insert(index, value)для вставки значения по указанному индексу в файл List. ( @whym1here , исправления #2134 )
    • Новый конструктор List(ptr, size, capacity), позволяющий избежать необходимости делать глубокую копию существующего непрерывного выделения памяти при создании нового файла List. ( @StandinKP , исправления #2170 )
  • Dictтеперь есть update()метод обновления ключей/значений из другого файла Dict. ( @gabrieldemarmiesse )
  • Setтеперь имеет именованные методы для операций над множествами:
    • difference()сопоставление с-
    • difference_update()сопоставление с-=
    • intersection_update()сопоставление с&=
    • update()сопоставление с|=

    @arvindavoudi )

  • DictList, и Setвсе соответствуют Boolableпризнаку. Коллекции оцениваются, Trueсодержат ли они какие-либо элементы, Falseв противном случае:
    deflist_names(names: List[String]):
    if names:
    for name in names:
    print(name[])
    else:
    print("No names to list.")
    

    @gabrieldemarmiesse )

  • Добавлена reversed()​​функция создания обратных итераторов. Несколько типов диапазонов, List, и Dictтеперь поддерживают обратную итерацию.
    var numbers = List(1,2,3,4,5)
    for number inreversed(numbers):
    print(number)
    

    @helehex и @jayzhan211 , внесли свой вклад в #2325 )

  • Optionalтеперь реализует __is__и __isnot__методы, чтобы вы могли сравнить их Optionalс None. Например:
    var opt = Optional(1)
    if opt isnotNone:
    print(opt.value()[])
    

    @gabrieldemarmiesse )

  • Tupleтеперь работает с типами элементов, занимающими только память, например, Stringи позволяет напрямую индексировать их с помощью выражения параметра. Это означает, что теперь вы можете просто использовать x = tup[1]Python вместо x = tup.get[1, Int](). Теперь вы также можете назначать элементы кортежа с помощью tup[1] = x.
    vartuple=("Green",9.3)
    var name =tuple[0]
    var value =tuple[1]
    

    Обратите внимание: поскольку нижний индекс должен быть выражением параметра, вы не можете выполнять итерацию с Tupleпомощью обычного forцикла.

  • Тип Referenceпретерпел несколько изменений, в том числе:
    • Он переехал в memory.referenceмодуль вместо memory.unsafe.
    • Referenceтеперь имеет unsafe_bitcast() метод, аналогичный типам указателей.
    • Было удалено несколько небезопасных методов, в том числе offset()destroy_element_unsafe()и emplace_ref_unsafe(). Это потому, что Referenceэто безопасный тип — используйте его UnsafePointerдля выполнения небезопасных операций.
  • Boolтеперь может быть неявно преобразован из любого типа, соответствующего Boolable признаку. Это означает, что вам больше не нужно писать такой код:
    @value
    structMyBoolable:
    fn__bool__(self)-> Bool:...
    fn takes_boolable[T: Boolable](cond: T):...
    takes_boolable(MyBoolable())
    

    Вместо этого вы можете просто написать:

    fntakes_bool(cond: Bool):...
    takes_bool(MyBoolable())
    

    Обратите внимание, что вызовы takes_bool()будут выполнять неявное преобразование, поэтому в некоторых случаях все же лучше явно объявить параметр типа, например:

    fn takes_two_boolables[T: Boolable](a: T, b: T):
    # Short circuit means `b.__bool__()` might not be evaluated.
    if a.__bool__()and b.__bool__():
    ...
    
  • PythonObjectтеперь соответствует KeyElementпризнаку, а это означает, что его можно использовать в качестве типа ключа для Dict. Это позволяет вам легко создавать словари Python и взаимодействовать с ними в Mojo:
    defmain():
        d = PythonObject(Dict[PythonObject, PythonObject]())
        d["foo"]=12
        d[7]="bar"
        d["foo"]=[1,2,"something else"]
    print(d)# prints `{'foo': [1, 2, 'something else'], 7: 'bar'}`
    
  • FileHandle.seek()теперь имеет whenceаргумент, который по умолчанию выполняет os.SEEK_SETпоиск с начала файла. Теперь вы можете установить os.SEEK_CURсмещение на текущую FileHandleпозицию поиска:
    var f =open("/tmp/example.txt")
    # Skip 32 bytes
    f.seek(os.SEEK_CUR,32)
    

    Или os.SEEK_ENDдля смещения от конца файла:

    # Start from 32 bytes before the end of the file
    f.seek(os.SEEK_END,-32)
    
  • FileHandle.read()теперь можно читать прямо в DTypePointer:
    varfile=open("/tmp/example.txt","r")
    # Allocate and load 8 elements
    var ptr = DTypePointer[DType.float32].alloc(8)
    varbytes=file.read(ptr,8)
    print("bytes read",bytes)
    print(ptr.load[width=8]())
    
  • Модуль sysтеперь содержит exit()функцию, которая завершает программу Mojo с указанным кодом ошибки.
    from sys import exit
    exit(0)
    
  • Конструкторы for Tensorбыли изменены, чтобы сделать их более последовательными. В результате конструкторы принимают форму в качестве первого аргумента (а не второго) при построении тензора с данными указателя.Если вы передаете конструктору одно скалярное значение Tensor, он теперь передает это значение всем элементам тензора. Например, Tensor[DType.float32](TensorShape(2,2), 0)создает 2x2тензор, инициализированный всеми нулями. Это обеспечивает простой способ заполнения данных тензора.
  • Stringтеперь есть removeprefix()и removesuffix()методы. ( @gabrieldemarmiesse )
  • Функции ordи chrбыли улучшены и позволяют принимать любые символы Юникода. ( @mzaks , способствует #1616 )
  • atol()теперь обрабатывает пробелы. Функция atol()используется внутри String.__int__(), поэтому int(String( " 10 "))теперь возвращает результат 10, а не выдает ошибку. ( @artemiogr97 )
  • SIMDтеперь реализует __rmod__() метод. ( @bgreni , исправления #1482 )
  • bool(None)сейчас реализовано. ( @zhoujingya )
  • Тип DTypePointerтеперь реализует gather()сбор SIMDвектора по смещениям текущего указателя. Аналогичным образом была добавлена ​​поддержка scatter()разброса SIMD вектора по смещениям текущего указателя. ( @leandrolcampos )
  • Функция len()теперь обрабатывает range()указанное значение с отрицательным конечным значением, поэтому такие вещи len(range(-1))работают правильно. ( @сорарос )
  • debug_assert() теперь печатает его местоположение (имя файла, строку и столбец, в котором он был вызван) в сообщении об ошибке. Аналогично, assert помощники в testing модуле теперь включают в свои сообщения информацию о местоположении.
  • Функция testing.assert_equal[SIMD]() теперь вызывается, если какой-либо из элементов не совпадает в двух SIMD сравниваемых аргументах. ( @gabrieldemarmiesse )
  • Функции testing.assert_almost_equal() и math.isclose()теперь имеют equal_nanфлаг. Если установлено значение True, NaN считаются равными.
  • Тип objectтеперь поддерживает операторы деления, по модулю, а также сдвигов влево и вправо, включая варианты на месте и в обратном направлении. ( @LJ-9801 , исправления #2224 )
  • Добавлены проверяемые арифметические операции для SIMDцелых чисел.SIMDЦелочисленные типы (включая скаляры целых чисел, такие как Int64) теперь могут выполнять проверенные сложения, вычитания и умножения, используя следующие новые методы:

    Проверенная арифметика позволяет вызывающей стороне определить, превысила ли операция числовые пределы типа. Например:

    var simd = SIMD[DType.int8,4](7,11,13,17)
    var product: SIMD[DType.int8,4]
    var overflow: SIMD[DType.bool,4]
    (product, overflow)= simd.mul_with_overflow(simd)
    for i inrange(len(product)):
    if overflow[i]:
    print("<overflow>")
    else:
    print(product[i])
    

    @лш )

  • Добавлен os.remove()и os.unlink()для удаления файлов. ( @artemiogr97 , исправления #2306 )

 Изменился

Изменения в инструментах

  • Поведение mojo buildпри вызове без выходного -oаргумента немного изменилось: mojo build ./test-dir/program.mojoтеперь исполняемый файл выводится в путь ./program, тогда как раньше он выводился в путь ./test-dir/program.
  • Команда mojo packageбольше не поддерживает этот -Dфлаг. Все флаги среды компиляции должны быть предоставлены в момент использования пакета (например, mojo runили mojo build).
  • REPL больше не позволяет неинициализировать объявления переменных уровня типа, например, он будет отклонять var s: String. Это связано с тем, что он не обеспечивает надлежащего отслеживания времени жизни (пока!) между ячейками, и такой код может привести к сбою. Эту проблему можно обойти, инициализировав фиктивное значение и перезаписав его позже. Это ограничение применимо только к переменным верхнего уровня, переменные в функциях работают так же, как и всегда.

Другие изменения

Языковые изменения

  • Была добавлена ​​встроенная функция низкого уровня, __get_mvalue_as_litref(x)предоставляющая доступ к базовому представлению памяти в виде !lit.refзначения без проверки статуса инициализации базового значения. Это полезно в логике очень низкого уровня, но не предназначено для общего удобства использования и, вероятно, изменится в будущем.
  • Свойства теперь можно указывать во встроенных операциях MLIR:
    _ =__mlir_op.`kgen.source_loc`[
        _type =(
    __mlir_type.index,__mlir_type.index,__mlir_type.`!kgen.string`
    ),
        _properties =__mlir_attr.`{inlineCount =1: i64}`,
    ]()
    

    Как показано в примере выше, _propertiesатрибут protected можно передать во время построения операции со DictionaryAttrзначением MLIR.

❌ Удален

  • Поддержка пакетов вариаций «только для регистрации» удалена. Вместо AnyRegType, пожалуйста, обновите свой код до AnyTypeтаких примеров:
    fn your_function[*Types: AnyRegType](*args:*Ts):...
    

    Этот шаг дает вам доступ к более удобному API и имеет то преимущество, что он безопасен для памяти и корректен для нетривиальных типов. Если вам нужны конкретные API для типов, используйте правильный признак вместо AnyType.

  • List.pop_back()был удален. Вместо этого используйте List.pop()вариант, который по умолчанию выталкивает последний элемент в списке.
  • SIMD.to_int(value)был удален. Используйте int(value)вместо этого.
  • Магическая __get_lvalue_as_address(x)функция удалена. Чтобы получить ссылку на использование значения Reference(x)и если вам нужен небезопасный указатель, вы можете использовать UnsafePointer.address_of(x).

️ Исправлено

  • #516 и #1817 и многие другие, например «Невозможно создать функцию, возвращающую две строки».
  • #1178 (os/kern) сбой (5).
  • #1609 псевдоним с DynamicVector[Tuple[Int]]ошибками.
  • #1987 На данный момент определение main в пакете Mojo является ошибкой. Это пока не предназначено для работы, ошибки на данный момент помогут предотвратить случайное неопределенное поведение.
  • #1215 и #1949 Сервер Mojo LSP больше не отключает предварительный просмотр при наведении для функций с функциональными аргументами, параметрами или результатами.
  • #1901 Исправлена ​​обработка Mojo LSP и генерации документации для входных аргументов.
  • #1913 - 0__парсер Mojo больше не аварийно завершает работу.
  • #1924 Исправлена ​​JIT-отладка на Mac.
  • #1941 Вариативные аргументы Mojo не работают с нетривиальными типами, состоящими только из регистров.
  • #1963 a!=0 теперь правильно анализируется и форматируется с помощью mojo format.
  • #1676 Исправлен сбой, связанный с @valueдекоратором и структурами с пустым телом.
  • #1917 Исправлен сбой после синтаксической ошибки во время создания кортежа.
  • #2006 Mojo LSP теперь правильно поддерживает типы подписей с именованными аргументами и параметрами.
  • #2007 и #1997 Mojo LSP больше не аварийно завершает работу при определенных типах замыканий.
  • #1675 Обеспечить @value корректный сбой декоратора после ошибки дублирования поля.
  • #2068 Исправление SIMD.reduce()размера _out == 2. ( @soraros ).

!…

Приглашаю всех высказываться в Комментариях. Критику и обмен опытом одобряю и приветствую. В особо хороших комментариях сохраняю ссылку на сайт автора!

И не забывайте, пожалуйста, нажимать на кнопки социальных сетей, которые расположены под текстом каждой страницы сайта.
Mojo обновленияПродолжение тут…

Deviz_18

Добавить комментарий

Ваш e-mail не будет опубликован. Обязательные поля помечены *

Можно использовать следующие HTML-теги и атрибуты: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>

Проверка комментариев включена. Прежде чем Ваши комментарии будут опубликованы пройдет какое-то время.