【问题标题】:What type checks does Raku perform at compile time? May that change in the future?Raku 在编译时执行哪些类型检查?将来可能会改变吗?
【发布时间】:2020-12-08 13:45:23
【问题描述】:

目前(截至 2020 年 8 月)Rakudo 不在编译时对函数的返回值进行类型检查;也就是说,它不提供函数满足其返回约束的静态保证。具体来说,以下两个函数都编译为 Raku:

sub get-int(--> Int) { 'bug' }
sub get-int($a --> Int) { 
   when $a == 5 { 'Rare bug' }
   default      { 42 }
}

我有两个相关的问题:

  1. 有什么方法可以知道当前在编译时发生了什么(如果有的话)类型检查? (通过某人编写的列表、文档中的某处或 Rakudo 源中的中心位置)还是比这更临时?

  2. 缺乏编译时类型检查是否是有意的设计决策?或者是添加更多静态类型检查的东西,有一天会很高兴,但还没有实现?

(我熟悉 Johnathan 对 The performance penalties for types/constraints in Raku? 的出色回答,其中指出“Raku 要求写入程序的类型约束在运行时最迟强制执行。”该回答描述了多种方式以避免类型检查的运行时成本,但没有描述在编译时进行的类型检查(如果有的话)(这肯定会避免运行时成本!)。)

【问题讨论】:

  • ❶ 在编译时强制执行6.d 的返回类型语义将提供比预期更少的价值,因为它有一个隐式 |Nil。 ❷ 大多数人不知道这一点。 ❸ jnthn 勾勒出未来。未来可能允许(相当于)省略 |Nil 并根据 explicit 约束执行或警告。 ❹ Raku 的类型是 名义上的,类似于结构 quasi-static typing 及其“错误类型”和“矛盾”类型的类别。 Rakudo,或检查模块,可以越来越多地警告或(r)相对于这两个类别。
  • 我认为2005 comment by Audrey Tang about possible type inference 涵盖的领域与今天的 Raku(do) 所涵盖的领域非常相似,因此它是一本有用的读物​​。关于 Raku(do) 类型检查器由于“类型错误”的程序而能够在编译时拒绝程序,请关注她的Error 类别。 Aiui,在我们今天拥有的 Raku 中,课程永远不会“关闭”或“最终确定”。如果引入这些,Rakudo 可能必须强制执行并了解整个程序的打开/关闭/最终状态。
  • @raiph 就问题中的示例而言,Nil 没有涉及;可以有效地检测到从声明为 Int 的东西返回的 Str。您所说的与在调用现场处理返回值有关。
  • @raiph 就类而言:通常我们倾向于说程序的词法元素是针对静态分析的,而方法调用是发生后期绑定的地方,因此不受此限制。在类型检查模块(或做出封闭世界假设的 IDE)中,以进行更多检查的名义假设方法调用没有这么晚是可能的,但我认为这并不适合标准语言。跨度>
  • @JonathanWorthington 感谢您的回复。你所说的对我来说很有意义,而且对于 Raku、Rakudo、Comma 和分析插件/模块来说听起来很棒。谢谢你的聪明。 :)

标签: raku typechecking rakudo


【解决方案1】:

目前很少在编译时检查类型;这主要是作为静态优化器的副作用发生的。今天的检查主要是关于子程序调用,其中:

  • 我们可以确定调用的数量并知道传递的参数数量永远不会匹配
  • 我们有文字参数,并且可以看到它们永远不可能与签名匹配

这是静态优化器进行更多内联工作时的遗留问题。现在,它只在编译时内联原生操作符,其余的留给 VM 的动态优化器,后者在内联方面的能力大大提高,也可以取消内联(允许推测优化,但也意味着可以恢复原始堆栈跟踪,而静态优化器丢失了这些信息)。

在编译时做更多的事情被认为是可取的,但是有一些实际问题需要考虑。

  1. 引入额外的检查也可能会破坏以前工作的代码。考虑一个具有代码路径的模块,该模块将无法通过更严格的编译时检查,但它正在用于从未遇到这种情况的系统中。如果它开始无法在较新版本的编译器上编译,那么在编译器升级后将无法部署该系统。一般来说,这意味着执行的检查应该随着语言版本的变化而变化。 (这仍然意味着人们在编写代码时应该声明他们正在编写的语言版本,请注意。)
  2. 在编译时进行的更多检查将“肯定避免运行时成本”这可能是真的,但推理起来并非易事。托管运行时不能盲目地相信它给出的字节码中的承诺,因为这可能导致内存安全违规(导致 SIGSEGV 或更糟)。这在 Raku 这样的语言中是非常清楚的,其中类型检查的语义是可编程的,但在 JVM、CLR 等中是正确的。 Raku 中与类型相关的最大优势来自于使用本机类型,这可以避免大量分配,从而避免垃圾收集工作。
  3. 实施进一步检查将增加编译器的复杂性以及编译所需的时间。其中第一个已经是一个问题。大约十年来,编译器前端没有看到任何重大的架构变化。当前为宏奠定基础的 RakuAST 工作还涉及对编译器前端的近乎重写。改进后的架构应该更容易实现进一步的编译时类型检查,但也考虑了如何并行化编译的各个方面,这可以让编译器在不增加挂钟编译时间的情况下做更多事情。

一旦当前编译器前端大修完成,似乎很可能会引入更多编译时检查(但仅从下一个语言版本启用) - 至少,只要有人在它上面工作。

然而,在这个领域还有一个更令人兴奋的机会出现:因为将有一个 Raku 程序的 API,并且随着自定义编译器通行证的计划一起制定,它也很快可以实现类型检查器 作为模块!其中一些可能会导致检查,使其成为未来的 Raku 语言版本。其他的可能是特定领域的,旨在更正确地使用给定的模块。其他人可能会执行不符合基本语言精神的严格要求,但某些语言用户可能希望选择加入。

【讨论】:

  • 感谢您提供的信息丰富且令人兴奋的答案。其中一些可能性真的很酷——说到 Raku,肯定有很多值得期待的!
猜你喜欢
  • 2012-01-27
  • 2023-03-13
  • 2014-02-08
  • 2011-05-23
  • 2020-02-07
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多