【Studio】Luau 回顾:2021 年 9 月

欢迎来到 Luau 回顾!

Luau 是我们的新语言,您可以在 https://luau-lang.org 了解更多信息。

泛型函数

这个月的大新闻:泛型函数回来了!

Luau 一直支持泛型函数的类型推断,例如:

type Point<X,Y> = { x: X, y: Y }
function swap(p)
  return { x = p.y, y = p.x }
end
local p : Point<number, string> = swap({ x = "hi", y = 37 })
local q : Point<boolean, string> = swap({ x = "hi", y = true })

但在此之前,我们没有办法编写 swap 的类型,因为 Luau 对函数没有类型参数(只有普通的数据参数)。而现在我们可以了:

function swap<X, Y>(p : Point<X, Y>): Point<Y, X>
  return { x = p.y, y = p.x }
end

泛型函数在函数声明和函数类型中都可以使用,例如:

type Swapper = { swap : <X, Y>(Point<X, Y>) -> Point<Y, X> }

大家可能还记得,在四月份时,我们发布了泛型函数,但后来不得不将其停用。那是因为 DataBrain 在 typeof 和泛型之间发现了一个讨厌的交互,它可能会写出需要使用嵌套泛型函数的代码,而这在当时是不支持的。

但现在我们支持嵌套的泛型函数了,所以您可以编写这样的代码:

function mkPoint(x)
  return function(y)
    return { x = x, y = y }
  end
end

并让 Luau 推断由一个泛型函数返回另一个泛型函数的类型

function mkPoint<X>(x : X) : <Y>(Y) -> Point<X,Y>
  return function<Y>(y : Y) : Point<X,Y>
    return { x = x, y = y }
  end
end

用行话来说就是:Luau 现在支持 Rank N Types 了,而此前它只支持 Rank 1 Types。

双向类型检查

在此之前,Luau 一直使用自下而上的类型检查。例如,对于一个函数调用 f(x),我们首先找到 f 的类型(假设它是 (T)->U)和 x 的类型(假设它是 V),确保 V 是 T 的一个子类型,所以 f(x) 的类型是 U。

通常情况下,这是可行的。但在注册回调事件处理程序这样的例子中却会出现问题。在如

part.Touched:Connect(function (other) ... end)

的代码中,如果我们从局部到整体地进行类型检查,就会出现问题。因为当我们对函数主体进行类型检查时,我们不知道 other 的类型。

在这种情况下,我们想要的是一种从局部到整体和从整体到局部的混合类型检查。在这个例子中,从 part.Touched:Connect 的类型中我们可以知道,other 一定有 BasePart 类型。

这种从局部到整体和从整体到局部的混合类型检查被称为双向类型检查。这意味着由类型引导的自动完成工具可以提供更好的建议。

编辑器功能

我们对 Roblox Studio 中的 Luau 自动完成测试版功能做了一些改进:

  • 我们不再为服务器端脚本中的纯客户端 API 提供自动完成建议,反之亦然。
  • 对于已知结构的表字面量,我们提供属性的自动完成建议。
  • 我们为 Player.PlayerGui 提供自动完成建议。
  • 诸如 then 和 else 这样的关键词可以更好地自动完成了。
  • 在注释范围内(以 --[[ 开头的注释),自动完成功能被禁用。

拼写检查改善

在其他拼写检查的新闻中:

  • Luau 约束解析器现在可以细化等式的操作数。
  • Luau 类型保护细化现在支持更多的随机情况。例如 typeof(foo) ~= “Instance” 可以消除所有不是 Instance 子类的对象。
  • 我们修复了一些在类型推断过程中由释放后重用引起的崩溃。
  • 当脚本在数据模型中被移动时,我们能更好地跟踪更新了。
  • 我们修复了递归类型可能导致free types(自由类型)泄漏 的途径之一。
  • 我们改进了 return 语句与互递归函数声明的交互方式。
  • 我们改进了解析器对那些看起来像函数调用(但实际并非)函数调用的代码的恢复,如
local x = y
(expr)[smth] = z
  • 我们会在类型错误之前报告解析错误。
  • 我们将更多的类型显示为 unknown,而不是像 error#### 那样的内部类型名称。
  • Luau 现在能更准确地推断出 Instance:Clone() 的结果。

性能优化

  • 优化了 Vector3.new 构造函数,它现在比之前快了约 2 倍。
  • 加强了之前对表尺寸预测的优化。使用 setmetatable 时,可以预测最终的表尺寸。例如 local self = setmetatable({}, Klass)
  • 优化了用户指定对象的方法调用。它的速度提高了 2-4%。
  • 现在 debug.traceback 比之前快了 1.5 倍。但对于注重性能的代码来说,debug.info 可能仍然更有优势。
  • 创建具有明确数字索引的表字面量(如 { [1] = 42 })的速度显著加快了。但我们仍然推荐您使用列表式结构。

其他改进

  • 现有的“TableLiteral”提示符现在可以标记出表字面量中出现完全相同的数字索引的情况,例如 { [1] = 1, [1] = 2 }
1 个赞

do the generic functions include fastcalls when generating instructions?

yes, they do

关于我们    加入我们    条款    隐私政策
©2021 Roblox Corporation、Roblox、Roblox 标志及 Powering Imagination 是我们在美国及其他国家或地区的注册与未注册商标。
粤ICP备20013629号