为什么Crystal不能推断实例变量的类型?



为什么这段代码对于实例变量失败?

a = 4.days # Works
class A
@a = 4.days # Fails
end

公立小学将来有改进的计划吗?似乎是很常见和有用的东西。

从Crystal 1.4开始,现在支持这一点。

这个话题最近又出现了,现在编译器足够聪明,可以检测到大多数简单的情况(感谢Asterite在PR #11812中的更改!)。现在,下面这些曾经是非法的例子现在被支持了:

class A
@x = 4.days
end
class B
@x = 2 * 3 + 4
end
class C
@x = [1, 2, 3].reverse  # (will be Array(Int32))
end

2022年4月6日更新:幸运的是,我之前的回答对于Crystal 1.4来说已经过时了。出于历史原因,我把它留了下来;它的部分内容仍然相关,但像最初问题中的简单案例现在是合法的。仅在旧版本(1.3.2之前)中,它将无法推断4.days1 + 1

@a = 4可以工作,因为4是文字,但4.days是表达式,因此不能自动推导。出于同样的原因,@a = 1 + 1也需要显式类型,尽管@a = 2不需要。

关于未来的计划,有趣的是,这个功能是存在的,但被故意删除了。

简而言之,原因是为了使编译步骤简单。自动诱导类型很优雅,但也有缺点:

<<ul>
  • 慢编译/gh>
  • 为错误类型的程序生成良好的错误消息变得困难
  • 重用以前编译的结果变得困难(或不可能?)
  • 原因是,一般来说,您必须在整个源代码中分析函数调用链。注意,并非所有表达式都像1 + 1那样简单。甚至4.days也已经有些复杂了,因为编译器需要推断days方法调用的返回类型。

    如果你想了解更多关于设计决策的信息,我建议你阅读2015年的讨论。

    你可能会问,为什么它适用于类外的第一次作业?我认为在这种情况下,上下文更本地化。因此,反对允许它的论据并不完全适用。例如,如果你改变一个函数中的语句,它的影响不像改变一个类的布局那样全局。

    同样,这是一种权衡。但在这两种情况下,强迫类型将彻底改变体验。虽然这种影响在类的上下文中相当小,但强制为任何赋值执行显式类型将使"ruby式"将Crystal语言转换为传统的类型语言,其中每个赋值都需要显式地键入。

    相关内容

    • 没有找到相关文章

    最新更新