初始化器现在被视为返回 Self 实例的静态方法。 这意味着初始化器的 out 参数现在与其他函数结果或 out 参数的处理方式相同。这一变化通常是不可见的,但像 instance.init() 和 x.copyinit(y) 这样的模式将不再有效。只需将它们分别替换为 instance = T() 和 x = y 即可。
遗留的 borrowed/inout 关键字和 -> T as foo 语法现在会生成警告。 请改用 read/mut/out 参数语法。
@value 装饰器现在还会派生 ExplicitlyCopyable 特性的实现。 这将有助于在 Mojo 集合类型中默认过渡到显式可复制性要求。
对同质元组进行索引操作现在会生成一致的元素类型,而无需重新绑定:
mojo
复制
var x = (1, 2, 3, 3, 4)
var y : Int = x[idx] # 直接生效!
你现在可以通过仅关键字参数重载位置参数,并且可以使用不同名称的仅关键字参数:
mojo
复制
struct OverloadedKwArgs:
var val: Int
fn __init__(out self, single: Int):
self.val = single
fn __init__(out self, *, double: Int):
self.val = double * 2
fn __init__(out self, *, triple: Int):
self.val = triple * 3
fn main():
OverloadedKwArgs(1) # val=1
OverloadedKwArgs(double=1) # val=2
OverloadedKwArgs(triple=2) # val=6
这也适用于索引操作:
mojo
复制
struct OverloadedKwArgs:
var vals: List[Int]
fn init(out self):
self.vals = List[Int](0, 1, 2)
fn getitem(self, idx: Int) -> Int:
return self.vals[idx]
fn getitem(self, *, idx2: Int) -> Int:
return self.vals[idx2 * 2]
fn setitem(mut self, idx: Int, val: Int):
self.vals[idx] = val
fn setitem(mut self, val: Int, *, idx2: Int):
self.vals[idx2 * 2] = val
fn main():
var x = OverloadedKwArgs()
print(x[1]) # 1
print(x[idx2=1]) # 2
x[1] = 42
x[idx2=1] = 84
print(x[1]) # 42
print(x[idx2=1]) # 84
标准库变化
StringRef 已被移除,取而代之的是 StringSlice。 这两种类型在 ABI 上是兼容的,如果需要完全相同的行为,可以使用 StaticString,它是 StringSlice[StaticConstantOrigin] 的别名。
为 b64decode() 函数添加了一个新的 validate 参数。
新增了 SIMD.from_bytes() 和 SIMD.as_bytes() 函数,用于将字节列表转换为标量列表,反之亦然,并接受字节序作为参数。 类似于 Python 的 int.from_bytes() 和 int.to_bytes() 函数。
在 sys.ffi 中添加了更多别名,以满足 FFI 绑定的常见需求。
用于构造不同类型的自由浮动函数已被弃用,改用实际构造函数:
之前 之后
int() Int()
str() String()
bool() Bool()
float() Float64()
这些函数是 Mojo 无法区分隐式和显式构造函数时的临时解决方案。在本版本中,你会收到弃用警告,下一个版本中将变为编译器错误。你可以通过匹配大小写和全词搜索替换来快速更新代码,例如将 int( 替换为 Int(。
UnsafePointer 的 bitcast 方法现在被拆分为 bitcast(用于更改类型)、origin_cast(用于更改可变性)、static_alignment_cast(用于更改对齐方式)和 address_space_cast(用于更改地址空间)。
UnsafePointer 现在根据可变性进行参数化。 以前,UnsafePointer 只能表示可变指针。新的 mut 参数可用于将 UnsafePointer 限制为特定的可变性:UnsafePointer[T, mut=False] 表示指向不可变 T 值的指针。这类似于 C++ 中的 const * 指针。
UnsafePointer.address_of() 现在会根据参数推断结果指针的来源和可变性。 例如:
mojo
复制
var local = 10
构造一个可变指针,因为 local
是一个可变内存位置
var ptr = UnsafePointer.address_of(local)
要强制构造指向可变内存位置的不可变指针,请使用强制转换:
mojo
复制
var local = 10
将可变指针强制转换为不可变指针
var ptr = UnsafePointer.address_of(local).origin_castmut=False
几个标准库集合类型的 unsafe_ptr() 方法已更新为使用参数化可变性: 它们将返回一个 UnsafePointer,其可变性继承自调用站点接收器的 ref self 的可变性。例如,ptr1 将是不可变的,而 ptr2 将是可变的:
mojo
复制
fn take_lists(read list1: List[Int], mut list2: List[Int]):
不可变指针,因为接收器是不可变的 read
引用
var ptr1 = list1.unsafe_ptr()
# 可变指针,因为接收器是可变的 `mut` 引用
var ptr2 = list2.unsafe_ptr()
添加了 Optional.copied(),用于通过复制指针值从 Optional[Pointer[T]] 构造一个拥有的 Optional[T]。
添加了 Dict.get_ptr(),它返回一个 Optional[Pointer[V]]。 如果字典中存在给定的键,则该可选值将持有指向该值的指针。否则,返回一个空的可选值。
添加了新的 List.extend() 重载,接受 SIMD 和 Span。 这些重载允许通过复制 SIMD 向量或 Span[Scalar[..]] 的元素来扩展 List[Scalar[..]],从而简化了一些优化 SIMD 感知功能的编写。
添加了 Char,用于表示和存储单个 Unicode 字符。
Char 实现了 CollectionElement、EqualityComparable、Intable 和 Stringable。
添加了从 Char 构造 String 的构造函数。
Char 可以通过 Char.to_u32() 转换为 UInt32。
Char 提供了用于分类字符类型的方法,包括:Char.is_ascii()、Char.is_posix_space()、Char.is_python_space()、Char.is_ascii_digit()、Char.is_ascii_upper()、Char.is_ascii_lower()、Char.is_ascii_printable()。
chr(Int) 现在会在给定无效的 Char 码点时中止。
添加了 StringSlice.from_utf() 工厂方法,用于从包含 UTF-8 编码数据的缓冲区验证构造 StringSlice。 如果缓冲区内容不是有效的 UTF-8,此方法将引发错误。
添加了 StringSlice.chars(),它返回一个 Chars 迭代器。 这是一个符合标准的 UTF-8 解码器,返回字符串中编码的每个 Unicode 码点。
添加了 StringSlice.getitem(Slice),它返回一个子字符串。 仅支持步长为 1 的情况。
几个标准库函数已更改为接受 StringSlice 而不是 String。 这使它们可以用于内存中任何适当编码的字符串,而不需要字符串是堆分配的。
atol()
atof()
ord()
ascii()
b64encode()
b64decode()
b16encode()
b16decode()
此外,之前接受 List 的 b64encode() 重载已更改为接受 Span。
添加了新的 String.chars() 和 String.char_slices() 迭代器方法,并弃用了现有的 String.iter() 方法。
不同的用例可能更喜欢迭代字符串中编码的 Chars,或者迭代包含单个字符的子切片。这两种迭代语义都不是明显的默认选择,因此现有的 iter() 方法已被弃用,暂时支持编写显式的迭代方法。
代码形式如下:
mojo
复制
var s: String = ...
for c in s:
...
可以迁移为使用 .char_slices() 方法:
mojo
复制
var s: String = ...
for c in s.char_slices():
...
String.len() 和 StringSlice.len() 方法现在返回字符串的字节长度。
以前,这些方法的文档指出它们最终会返回 Unicode 码点的长度。它们已更改为保证返回字节长度,因为字节长度是它们今天最常用的方式(例如,作为低级内存操作逻辑的边界)。此外,码点长度是一种更专业化的字符串长度概念,很少是正确的度量标准。
知道需要码点长度的用户可以使用 str.char_length() 方法,或 len(str.chars())。
各种功能已从 String 和 StringRef 移至更通用的 StringSlice 类型。
StringSlice 现在实现了 Representable,并且该实现现在由 String.repr() 和 StringRef.repr() 使用。
StringSlice 现在实现了 EqualityComparable。
到目前为止,StringSlice 已经实现了与具有任意其他来源的 StringSlice 类型进行更通用的 eq 和 ne 比较。然而,为了满足 EqualityComparable,StringSlice 现在还具有更窄的比较方法,支持仅与具有完全相同来源的 StringSlice 进行比较。
添加了 StringSlice.char_length() 方法,与现有的 StringSlice.byte_length() 方法配对。
在未来的 Mojo 版本中,StringSlice.len() 可能会更改为返回字节长度,以匹配 C++ 和 Rust 等语言中的字符串长度方法约定。知道需要 Unicode 码点长度的调用者应更新为调用 StringSlice.char_length()。
从一些执行分配的标准库初始化器方法中移除了 @implicit 装饰器。 这减少了 Mojo 代码可能在用户不知情的情况下隐式分配的地方。
从以下方法中移除 @implicit:
String.init(out self, StringRef)
String.init(out self, StringSlice)
List.init(out self, owned *values: T)
List.init(out self, span: Span[T])
ExplicitlyCopyable 特性已更改为需要 fn copy(self) -> Self 方法。 以前,ExplicitlyCopyable 需要一个签名为 fn init(out self, *, other: Self) 的初始化器。
这提高了程序员在查找代码中可能执行复制的地方时的“可搜索性”和一目了然的可读性。
bit_ceil 已重命名为 next_power_of_two,bit_floor 已重命名为 prev_power_of_two。 这是为了提高其使用时的可读性和清晰度。
之前用于索引的 Indexer 和 IntLike 特性已合并。 这使得 SIMD 标量整数类型和 UInt 可以用于索引到所有集合类型,并优化了 UInt 索引的规范化检查。
添加了 ImplicitlyIntable 特性,允许类型通过实现 as_int 方法隐式转换为 Int:
mojo
复制
@value
struct Foo(ImplicitlyIntable):
var i: Int
fn __as_int__(self) -> Int:
return self.i
你现在可以使用构造函数转换 SIMD 类型:
mojo
复制
var val = Int8(42)
var cast = Int32(val)
当将标量类型传递给更大的向量大小时,它也有效:
mojo
复制
var vector = SIMDDType.int64, 4 # [42, 42, 42, 42]
对于非标量值,SIMD 向量的大小需要相等:
mojo
复制
var float_vector = SIMDDType.float64, 4
SIMD.cast 仍然存在以推断新向量的大小:
mojo
复制
var inferred_size = float_vector.castDType.uint64 # [42, 42, 42, 42]
你现在可以使用 max() 和 min() 处理可变数量的参数。
标准库中添加了新的 LinkedList 类型。
String.write 静态方法已移至 String 构造函数,并且现在是缓冲的。 与其这样做:
mojo
复制
var msg = "my message " + String(x) + " " + String(y) + " " + String(z)
这会重新分配 String,你应该这样做:
mojo
复制
var msg = String("my message", x, y, z, sep=" ")
这更简洁,并且缓冲到堆栈,因此 String 只分配一次。
你现在可以将任何 Writer 传递给 write_buffered:
mojo
复制
from utils.write import write_buffered
var string = String("existing string")
write_buffered(string, 42, 42.4, True, sep=" ")
这会在重新分配 String 之前写入堆栈上的缓冲区。
__disable_del x 操作已收紧,以将 x 的所有字段视为在 del 时被消耗,因此应在所有子字段被转移或以其他方式消耗后使用(例如在函数结束时),而不是在字段使用之前。
工具变化
mblack(即 mojo format)不再格式化非 Mojo 文件。 这防止了意外格式化 Python 文件。
完整的结构体签名信息现在在文档生成器中公开,并通过 Mojo 语言服务器在符号大纲和悬停标记中公开。
sys 模块中添加了 env_get_dtype 函数。 这允许你从参数环境中获取 DType 的值。
❌ 移除
StringRef 已被弃用。 请改用 StringSlice。
更改了 sys.argv() 以返回 StringSlice 列表。
添加了 Path 从 StringSlice 的显式构造函数。
移除了 StringRef.startswith() 和 StringRef.endswith()。
移除了 StringRef.strip()。
Tuple.geti, T 方法已被移除。 请根据需要改用 tup[i] 或 rebindT。
StringableCollectionElement 已被弃用,请改用 WritableCollectionElement,它仍然允许你构造 String,但可以避免中间分配。
Type{field1: 42, field2: 17} 语法用于直接初始化寄存器可传递类型已被移除。 这是遗留语法 - 要升级你的代码,请将 @value 装饰器添加到你的结构体以获取成员初始化器,并改用 Type(field1=42, field2 = 17)。
🛠️ 修复
Mojo 内核在 Jupyter Notebooks 中的夜间版本再次正常工作。
mojo debug --vscode 命令现在正确设置了当前工作目录。
修复了问题 #3796 - 处理 for-else 语句时的编译器崩溃。
修复了问题 #3540 - 使用命名输出槽会破坏特性一致性。
修复了问题 #3617 - 无法为包装 !lit.ref 的类型生成构造函数。
Mojo 语言服务器不再在空的 init.mojo 文件上崩溃。 问题 #3826。
修复了问题 #3935 - 错误使用 Tuple.get 时出现令人困惑的 OOM 错误。
修复了问题 #3955 - 循环中使用 def 参数时的意外复制行为。
修复了问题 #3960 - 无限 for 循环。