官方 Modular AI 代理技能。Modular发布了 官方 AI 代理技能,用于与 MAX 和 Mojo 配合使用。这四项技能new-modular-project——`a`、mojo-syntax`b`、 mojo-gpu-fundamentals`c` 和mojo-python-interop`d`——可帮助 AI 编码代理使用合适的工具创建新项目、生成正确的现代 Mojo 语法、遵循 GPU 编程最佳实践,并处理 Python 与 Mojo 的互操作。这些技能遵循开放的 代理技能标准,并可与 Claude Code 和其他兼容代理配合使用。使用以下命令安装它们 npx skills add modular/skills:`.`
条件特性一致性。结构体现在可以声明特性一致性,这些一致性仅在类型参数满足特定条件时才适用,where方法是在一致性列表中使用子句。九种标准库类型(包括List`String`、Dict`String`、Set`String` 和 ` OptionalString`)现在使用此功能在编译时强制执行特性要求。
def/ fnunification. def现在是 Mojo 的标准函数声明关键字。def函数不再隐式抛出异常,并且现在与 具有相同的语义fn:默认情况下不抛出异常,对于 raises可能抛出异常的函数,则需要显式声明。fn已被弃用,将在未来的版本中移除。
T 字符串。Mojo现在支持带有t"..."前缀的模板字符串。T 字符串生成的TString值同时包含静态格式字符串和运行时参数,从而实现无需立即分配内存的结构化字符串处理。
comptime if``comptime for新的 ` comptime ifand` 语法取代comptime for了用于编译时条件语句和循环语句的旧式@parameter if`and` @parameter for装饰器形式。此版本同时接受这两种语法;旧式@parameter形式很快将被弃用。
assert语句。Mojo现在支持独立的 ` assertif` 语句,类似于 Python 的 `if` 语句assert。它会在运行时检查条件,如果条件为假则中止,并可选择添加一条消息。底层会将 assert其反语法糖化为 `if`语句,debug_assert()并遵循该-D ASSERT标志。
@align(N)装饰器。现在结构体可以 @align(N)像 C++alignas和 Rust一样指定最小对齐方式#[repr(align(N))]。对齐值可以作为结构体参数,从而支持通用的缓存对齐和硬件对齐类型。
隐式Int转换SIMD已弃用。Int从 ` int` 到SIMD标量类型(例如 ` Int8int` 或 ` int`)的隐式转换Float32现已弃用。依赖这些转换的代码应改用显式构造函数。该mojo build --experimental-fixit命令可协助进行迁移。
初始化统一。`and`__moveinit__()方法现在__copyinit__()分别重命名为__init__()仅包含关键字参数take和copy 参数的形式。旧名称仍然可用,但应迁移到新形式。
Stringable这些特性已Representable被弃用。它们已被统一Writable特性所取代,后者提供了默认实现。大多数标准库类型已经移除了它们的Stringable一致性 Representable。
UTF-8 安全性改进。 现在,当索引位于多字节码点的中间时,下标操作会引发 panic;String对于会产生无效 UTF-8 的操作,也会引发 panic。字节位置下标现在返回整个 Unicode 码点,而不是单个字节。
trait不再继承ImplicitlyDestructible。特性声明不再自动遵循ImplicitlyDestructible;需要遵循该特性的特性现在必须显式选择加入。这延续了 v0.26.1 中关于显式销毁类型的工作,并鼓励生态系统默认支持线性类型。
def现在 `__function__` 是 Mojo 的标准函数声明关键字。def函数不再隐式抛出异常,并且现在与 `__function__` 具有相同的语义fn:默认情况下不抛出异常,接受raises异常说明符,并支持类型错误。`__function__` fn已被弃用,将在未来的版本中移除。我们建议将所有fn声明切换到 `__function__` def。
# Previouslydef foo(): # Implicitly raised Error.fn bar(): # Did not raise.fn baz() raises: # Explicitly raised Error.fn qux() raises EmptyDictError: # Raised a typed error.# Nowdef foo(): # Does not raise.def bar() raises: # Explicitly raises Error.def baz() raises EmptyDictError: # Raises a typed error.fn qux(): # Deprecated: use 'def' instead.fn qux() raises: # Deprecated: use 'def' instead.fn qux() raises EmptyDictError: # Deprecated: use 'def' instead.
这一变化通过明确错误处理来澄清函数契约:def不raises保证错误会在本地处理或不会发生,编译器强制执行此不抛出异常的保证。
Mojo 现在支持结构体声明中的条件 trait 一致性where。结构体可以使用一致性列表中的子句声明,仅当其类型参数满足特定条件时才遵循某个 trait 。该where子句接受任何 [Bool]类型化的参数表达式。例如, [List]现在可以使用此子句来有条件地遵循 某个 trait [Equatable], [Writable]前提是其元素类型满足该 trait:
struct List[T: Movable]( Copyable, Equatable where conforms_to(T, Equatable), Movable, Writable where conforms_to(T, Writable),): ...
以下是一个简短的独立示例:
@fieldwise_initstruct Wrapper[T: Copyable & ImplicitlyDestructible]( Writable where conforms_to(T, Writable),): var value: Self.T@fieldwise_initstruct NotWritable(Copyable, ImplicitlyDestructible): var data: Intdef main(): var w = Wrapper[Int](42) print(w) # OK — Int is Writable. Prints: Wrapper[Int](value=42) var w2 = Wrapper[NotWritable](NotWritable(10)) # OK to construct print(w2) # errors at parse time
当前限制: 尚不支持对[RegisterPassable]、 [TrivialRegisterPassable]和 的 条件性符合性。[ImplicitlyDestructible]
Mojo 现在支持 t-string(模板字符串),用于构建带有插值表达式的结构化字符串模板。t-string 使用t"..." 前缀,并生成一个 [TString]包含静态格式字符串和所有运行时参数的值,而不是立即生成一个冒号 [String]。
def main(): var x = 10 var y = 20 print(t"{x} + {y} = {x + y}") # prints: 10 + 20 = 30
使用{{`and`}}可以将字面大括号包含在输出中:
print(t"Use {{braces}} like this") # prints: Use {braces} like this
Mojo 现在支持使用comptime if`&& comptime for` 作为编译时条件和循环结构的首选语法,取代了旧式的 `&&` @parameter if和@parameter for装饰器形式:
# Old syntax (still accepted, deprecated in a future release)@parameterif some_condition: ...@parameterfor i in range(10): ...# New syntaxcomptime if some_condition: ...comptime for i in range(10): ...
此版本同时支持两种语法。旧@parameter语法即将弃用,解析器会发出警告并提供修复建议,提示用户迁移到新语法。
assertMojo 现在支持类似 Python 的 独立语句assert。它会在运行时检查一个条件,如果条件为假,则中止程序:
assert x > 0, "x must be positive"assert len(items) != 0
条件必须是一个Bool表达式,可选的消息可以是任何Writable表达式(例如StringLiteral`&&` String、`&&` Int、`&&` 等)。底层会将assert其反语法糖化为对 `&&` 的调用 debug_assert(),因此它遵循现有的-D ASSERT标志:当使用 ` -D ASSERT=all&&` 编译时,断言处于激活状态;否则,断言将不执行任何操作。
Mojo 现在支持 装饰器来指定结构体的最小对齐方式,类似于 C++ 和 Rust 的 ` minalignment` 。该值 必须是 2 的正幂,并指定以字节为单位的最小对齐方式。实际对齐方式为`minalignment`——您不能使用 ` minalignment` 将对齐方式降低到低于结构体的自然对齐方式。例如,对包含 `int`(8 字节对齐)的结构体使用 `minalignment` 会发出警告,并且该结构体将保持 8 字节对齐。@align(N)``alignas``#[repr(align(N))]``N``max(N, natural_alignment)``@align``@align(1)``Int
from sys import align_of@align(64)struct CacheAligned: var data: Intdef main(): print(align_of[CacheAligned]()) # Prints 64
栈和堆的分配都遵循@align。
对齐值也可以是结构体参数,从而支持通用的对齐类型:
@align(Self.alignment)struct AlignedBuffer[alignment: Int]: var data: Intdef main(): print(align_of[AlignedBuffer[64]]()) # Prints 64 print(align_of[AlignedBuffer[128]]()) # Prints 128
Mojo 现在支持为推断参数指定默认值,从而更容易创建部分绑定类型:
struct Pointer[mut = False, // o: Origin[mut]] : pass# Default to immutable pointercomptime ImmPointer = Pointer[_]# Explicitly set to mutable pointercomptime mutPointer = Pointer[mut = True, _]# Inferred mutability from `SomeOrigin()`comptime InferredPointer = Pointer[SomeOrigin()]# Parametric mutability pointer.comptime ParametricPointer = Pointer[...]
Mojo 现在强制执行更明确的参数绑定规则:
[]必须使类型更加具体:
struct SomeStruct[a : Int = 1]: pass# SS1 is a parametric typecomptime SS1 = SomeStruct# SS2 a concrete type alias of `SomeStruct[1]comptime SS2 = SomeStruct[]
使用时[],它必须生成具体类型,除非使用_/...来解绑特定/多个缺失的参数。
struct SomeStruct[a : Int, b: Int, c: Int = 2]: pass# Error: can not infer `b`, since `[]` must produce a concrete type, without `_`/`...``comptime SS1 = SomeStruct[1]# This is a concrete type alias of `SomeStruct[1, 1, 2]`comptime SS2 = SomeStruct[1, 1]# Using `...` defers binding of b and c, and produces `SomeStruct[1, ?, ?]` (preserving possible defaults)comptime SS3 = SomeStruct[1, ...]# Even though SS3 unbinds `c`, Mojo keeps track of the fact that there is a default value for c:# This install b (using 1) and c (using default value), and produce `SomeStruct[1, 1, 2]`comptime SS4 = SS3[1]# This installs the default and is identical to `SomeStruct[1, ?, 2]`comptime SS5 = SomeStruct[1, _]# This unbind the default explicitly and is identical to `SomeStruct[1, ?, ?]`comptime SS6 = SomeStruct[1, _, _]# The following two are equivalent:comptime SS7 = SomeStructcomptime SS8 = SomeStruct[...]
Mojo 现在支持更灵活的默认参数,当它们的类型是参数化的时,声明的类型可以不匹配。这允许在将它们用作默认值时从中推断参数,例如:
def take_string_slice[o: ImmOrigin](str: StringSlice[o] = ""): ... def use_it(): take_string_slice() # Ok, defaults to empty string, inferring "o". # Explicit calls also work of course. take_string_slice(StaticString("hello")) # Default value is checked for validity at the call site. def defaultArgumentBadType2[T: AnyType](a: T = 1.0): pass def callDefaultArgumentBadType2(): # Ok! defaultArgumentBadType2[Float64]() # error: value passed to 'a' cannot be converted from 'FloatLiteral[1]' to 'Int' defaultArgumentBadType2[Int]()
Mojo 现在允许移动构造函数将其“take”参数作为 deinit或var。deinit通常应该优先选择 ,但var在某些特殊情况下,例如需要类似 C++ 的行为时,析构函数在移动构造函数处理完值后仍然对该值运行,则 可能很有用。
def __init__(out self, *, var take: Self): self.data = munge(take.data) # take.__del__() runs here.
**_参数绑定列表中不再*_支持这些参数。请使用更简洁的方式...显式取消绑定任何未指定的参数。
[VariadicParamList]现在,同质可变参数通过类型(以前称为)传递 ,参数现在通过 (以前称为)VariadicList一致地传递, 而不是直接传递平凡类型。[VariadicList] VariadicListMem
下标中的切片字面量已更改为更类似于集合字面量。现在,它们会传递一个空元组作为必需的__slice_literal__ 关键字参数,以消除切片歧义。如果您定义了自己的范围类型,请__slice_literal__: () = ()为其构造函数添加参数。
trait声明不再自动继承自 ImplicitlyDestructible。struct声明不会改变,仍然继承自ImplicitlyDestructible。
以前, [@explicit_destroy] 需要通过注解来选择不遵循 ImplicitlyDestructible规范。现在,如果一个特性的用法依赖于隐式可销毁性,则必须显式地选择加入规范:
# Beforetrait Foo: ...# After:trait Foo(ImplicitlyDestructible): ...
反之,如果一个 trait 想要支持非隐式可销毁类型,则不再需要使用以下注解@explicit_destroy:
# Before@explicit_destroytrait Foo: ...# Aftertrait Foo: ...
继续struct继承ImplicitlyDestructible而不是不再 继承trait旨在平衡常见情况下的可用性和熟悉度,同时需要促进 Mojo 生态系统对明确销毁类型的广泛支持。
如果大多数struct类型 ImplicitlyDestructible在实践中都如此,那就不是问题。但是,如果许多生态系统库都编写得过于苛刻,设置了不必要的限制,那么任何选择显式销毁的ImplicitlyDestructible单个类型的可用性都会受到影响。struct
包含通用算法和类型的库应该编写成支持线性类型。ImplicitlyDestructible对 trait 采取可选方式可以鼓励默认支持,只有当特定类型和函数ImplicitlyDestructible确实需要时,才选择加入更严格的要求。
大多数以引用作为输入的通用算法应该不会受到影响。
从包中重新导出的符号__init__.mojo不再被同名子模块遮蔽。例如,如果pkg/foo.mojo定义了 `x`fn foo并pkg/__init__.mojo执行了 `y` from .foo import foo,那么 `x` 和 `y`from pkg import foo现在from pkg import *会正确解析为函数 `x` 而不是模块 `y`。
is_compile_time()已重命名为 `__init__` __is_run_in_comptime_interpreter,现在它是一个关键字,而不是函数调用。它提供了一种机制,用于支持编译时解释器和运行时生成的代码中不同的代码执行路径。此值不能在任何编译时表达式中用作常量,因为它始终作为True编译时表达式的值进行求值。将此检查用作运行时的条件if。如果将其用作的条件,编译器现在会发出警告comptime if。
Mojo 支持使用标准 Python 的 `__init__` __getitem__()和`__init__`__getattr__()方法进行下标和名称索引。之前,它使用启发式方法来判断一个__get*__方法使用的是动态索引还是参数索引。现在,Mojo 采用了一种简单明确的策略:如果一个类型实现了 `__init__` __getitem_param__()或 ` __getattr_param__()__init__` 方法,并且索引是有效的参数表达式,编译器会选择它(但不支持 `__init__` 和 `__init__` 的 __setitem__()组合)。否则,或者如果索引只是有效的运行时值,Mojo 将像往常一样尝试使用 `__init__` __getitem__()。__setitem__()这使得行为更加可预测和明确,但要求类型如果想要使用参数式下标,则必须切换到 param方法名称。这只会影响少数特殊类型,例如 `__init__`Tuple和 `__init__` VariadicPack。
装饰@doc_private器已更名,以@doc_hidden更好地体现其隐藏文档生成声明的目的,而非暗示访问控制的任何变更。旧@doc_private名称仍然可用,但已被弃用,将在未来的版本中移除。
Dict内部实现已替换为使用 SIMD 分组探测进行查找的瑞士表实现。这提高了查找、插入和删除的性能——尤其是在查找字典中不存在的键时——同时将负载因子从 2/3 提高到 7/8,从而提高了内存效率。power_of_two_initial_capacity关键字参数已重命名 capacity,现在接受任何正整数(内部向上取整到下一个 2 的幂,最小值为 16)。
Dict现在,当表中已充满墓碑但存活元素数量较少时,会执行原地墓碑重哈希操作。这可以防止在重复插入/删除操作后造成不必要的容量翻倍。
[StaticTuple] 现在支持比较运算符。 当__eq__()`\`为真时,` /`__ne__()可用;当 `\` 为假时, `/// ` 可用。所有运算符均使用字典序,并在编译时展开循环。element_type: Equatable``__lt__()``__le__()``__gt__()``__ge__()``element_type: Comparable
[Set.pop()] 现在 [Dict.popitem()] 直接使用,避免了冗余的重新哈希。顺序从先进先出 (FIFO) 变为后进先出 (LIFO),与 Python 的无序排序相匹配set.pop()。
Set.__gt__()现在Set.__lt__()使用 O(1)len()检查加上一次 issubset()遍历,而不是两次完整的遍历。
InlineArray现在需要显式地使用字面量进行构造。例如:
var a: InlineArray[UInt8, 4] = [1, 2, 3, 4]# instead of InlineArray[UInt8, 4](1, 2, 3, 4)
以下类型现已正确实现write_repr_to():
该[itertools] 模块现在包含三个新的迭代器组合器:
[cycle(iterable)] 创建一个迭代器,无限循环遍历元素。
[take_while[predicate](iterable)] :返回元素,而谓词返回 True
[drop_while[predicate](iterable)] :当谓词返回 True 时,删除元素,然后返回剩余元素。
` Stringableand`Representable特性现已弃用。请改用 ` Writable or` 来使您的类型可格式化为字符串。`or` Writable提供了一个默认实现,因此在许多情况下,只需添加 Writable一致性即可,无需手动实现write_to() `or` write_repr_to()。但是,您可以手动实现这些特性以获得自定义输出。
正在stdlib逐步移除对 `and`Stringable 和 ` Representabletraits` 的支持,转而支持统一的Writable`trait`。大多数标准库类型已经不再符合 ` Stringableand` 和 `traits` Representable,并且相关的__str__() `and`__repr__()方法也已被弃用。
__reversed__()原有的 `on` String、 `on`[StringSlice](https://docs.modular.com/stable/mojo/std/collections/string/string_slice/StringSlice/)和 ` on`方法StringLiteral 已被弃用,取而代之的是新的codepoints_reversed()方法。新方法名称明确表明迭代是按相反顺序遍历 Unicode 码点,从而与现有的 `on`codepoints() 和 ` codepoint_slices()on` 方法保持一致。已弃用的__reversed__()方法仍可继续使用,但会发出弃用警告。
StringSlice从现在开始,构造函数会String传递可变性。如果您持有对 `a` 的可变引用String,StringSlice(str)则会返回一个可变的 `a` StringSlice。该 String.as_string_slice() 方法已被弃用,取而代之的是StringSlice(str)构造函数,并且 该方法String.as_string_slice_mut() 已被移除。
String.ljust(),, String.rjust()和String.center()已更名为 String.ascii_ljust(),String.ascii_rjust()和String.ascii_center()。同样,它们在StringSlice和上的对应项也已更名StaticString。
String.resize() 如果新的长度会截断代码点,程序现在会发出异常。之前,这会导致生成一个无效的 UTF-8 字符串。
String.resize()``fill_byte如果值大于等于 128,则会引发 panic 。之前这样做会生成无效的 UTF-8 编码。
现在,如果索引位于 UTF-8 编码码位的中间,使用下标String操作将会引发 panic。之前,它们会返回无效的 UTF-8 编码。此 panic 是无条件的。如果您确实需要之前的行为,请使用其他方法。StringSlice``.as_bytes()[...]
StringSlice[byte=]现在下标操作返回的是一个值StringSlice而不是一个值 String。这与基于范围的下标操作一致。
现在,使用下标String并按StringSlice字节位置指定将返回完整的 Unicode 代码点。以前,它只会返回单个字节,如果索引落在多字节代码点的起始字节上,则会生成无效的 UTF-8 编码。
String、、StringSlice和StringLiteral的.format()方法现在要求它们的参数是Writable。
TString.write_to()现在使用紧凑的格式字符串编码。格式字符串在编译时被扁平化为以 NUL 结尾的字面量段,与之前基于结构体的预编译条目相比,生成的静态数据量显著更小,运行速度也更快。
编译时格式化字符串StringLiteral不再分配内存。它用于global_constant存储原本需要在堆上分配的已解析格式化数据。
T 字符串现在支持原始前缀 ( rt"..."),它将反斜杠保留为字面字符,同时仍然支持插值。
var name = "Mojo"print(t"C:\{name}\Documents") # prints "C:\Mojo\Documents"
String现在,下标StringSlice需要一个命名参数来进行范围索引。例如,s[1:3]现在是s[byte=1:3]。
Int现在已弃用从`int` 到 `int` 的隐式转换[SIMD] ,并将在 Mojo 的未来版本中移除。这包括弃用从 ` Intint` 到特定SIMD标量类型(例如Int8`int` 或 `int`)的转换Float32。
> 注意:此实验性mojo build --experimental-fixit命令可能有助于将您的代码迁移以反映此更改。
当前代码依赖于隐式转换,例如:
def foo(arg: Int) -> Float32: return arg
应该改为使用显式转换:
def foo(arg: Int) -> Float32: return Float32(arg)
Int有时,当从标量到更宽泛的值发生隐式转换时SIMD,编译器会建议进行一些更改,以使转换显式化,这种更改比较冗长,它会在一步中同时执行类型转换和“展开”操作:
var bits: SIMD[DType.uint8, 16] = ...- var y = bits >> (j * 4)+ var y = bits >> SIMD[DType.uint8, 16](j * 4)
一个更简单的改动是显式地进行类型转换,并让“splat”继续隐式地发生(这将继续得到支持):
var bits: SIMD[DType.uint8, 16] = ...- var y = bits >> (j * 4)+ var y = bits >> UInt8(j * 4)
对于类似情况,编译器可能会发出过于冗长的建议LayoutTensor.element_type,其中编译器可能会建议更改形式:
- tensor[i] = i * l+ tensor[i] = LayoutTensor[DType.uint32, Layout(IntTuple(-1)), stack].element_type(i * l)
如果只需进行更简单的更改即可:
- tensor[i] = i * l+ tensor[i] = UInt32(i * l)# Note: If the tensor's `dtype` is not statically known, this works as well:+ tensor[i] = Scalar[tensor.dtype](i * l)
SIMD's 的安全除法运算符(' __floordiv__,__mod__',' )现在以元素级的方式返回安全结果。此前,如果除数的任何__divmod__元素为零,则它们返回零结果:
comptime Int32x2 = SIMD[DType.int32, 2]var a = Int32x2(99, 99)var b = Int32x2(4, 0)# Now returns [24, 0]# Previously returned [0, 0]print(a.__floordiv__(b))
[Int.__truediv__()] 现在执行截断整数除法,返回 `None`Int 而不是之前弃用的 `None` Float64。Float64浮点数除法请使用显式类型转换。
目前的文档 [SIMD.__round__()] 澄清了之前的行为,即平局将四舍五入到最接近的偶数,而不是远离零。
[Int.write_padded()] 现在计算宽度时会考虑负号,从而无论符号如何,都能得到一致的宽度:
Int(1).write_padded(s, 4) # writes " 1"Int(-1).write_padded(s, 4) # writes " -1"
SIMD现在有一个write_padded()处理整数 DTypes 的方法,其行为与 一致Int.write_padded()。填充是逐元素添加的。与 SIMD常规打印不同,默认情况下元素之间不会添加空格:
Int32(1).write_padded(s, 4) # writes " 1"Int32(-1).write_padded(s, 4) # writes " -1"# "[ 1, -1, 0,1234]"SIMD[DType.int32, 4](1,-1,0,1234).write_padded(s, 4)# "[255,255]"SIMD[DType.uint8, 2](255).write_padded(s, 1)
添加了[comb(n, k)] `and` 和 perm(n, k)`to` std.math,与 Python 的 ` math.comb()and`相匹配math.perm()。`compute`comb(n, k)计算二项式系数 C(n, k),但不计算完全阶乘,当 ` k > n.`时返回 0。`compute`perm(n, k)计算排列 P(n, k);省略k(默认值 -1)返回 ` n!.`
该builtin.math模块已合并到 math。特性 Absable、 DivModable、 Powable和 Roundable函数 abs()、 divmod()、max()、 现已成为该模块的一部分 min(),并继续在 prelude 中使用。之前显式从 导入的代码 pow()应 更新为从 导入。round()math``builtin.math``math
现在,函数签名中的数学 函数std.math()使用子句代替函数体中的检查。这在调用点提供了更清晰的编译时错误信息。使用这些函数并带有泛型参数的调用者可能需要添加证据(子句或 )来证明其 参数类型为浮点数。exp()``exp2()``log2()``erf()``tanh()``sin()``cos()``tan()``acos()``asin()``atan()``atan2()``acosh()``asinh()``atanh()``cosh()``sinh()``expm1()``log10()``log1p()``logb()``cbrt()``erfc()``j0()``j1()``y0()``y1()``where dtype.is_floating_point()``__comptime_assert``dtype``where``__comptime_assert