【发布时间】:2021-08-12 00:58:03
【问题描述】:
为什么此代码对实例变量失败?
a = 4.days # Works
class A
@a = 4.days # Fails
end
附言
以后有没有改进的计划?似乎是很常见和有用的东西。
【问题讨论】:
-
好消息!在 Crystal 1.4 中,它将立即编译。我用详细信息更新了我的答案。
标签: crystal-lang
为什么此代码对实例变量失败?
a = 4.days # Works
class A
@a = 4.days # Fails
end
附言
以后有没有改进的计划?似乎是很常见和有用的东西。
【问题讨论】:
标签: crystal-lang
从 Crystal 1.4 开始,现在支持此功能。这是合法的代码。
主题came up again recently,现在编译器足够聪明,可以检测到大多数简单的情况(感谢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.days 或 1 + 1。
@a = 4 会像 4 是 literal 一样工作,但 4.days 是一个表达式,因此不能自动推导。出于同样的原因@a = 1 + 1also requires explicit types,尽管@a = 2 不会。
关于未来的计划,有趣的是该功能存在,但被故意删除。
简而言之,原因是为了保持编译步骤简单。自动归纳类型很优雅,但也有缺点:
原因是,通常,您必须分析整个源代码中的函数调用链。请注意,并非所有表达式都像1 + 1 一样简单。即使4.days 已经有些复杂了,因为编译器需要推导出days 方法调用的返回类型。
如果您想了解有关设计决策的更多信息,我建议您阅读discussion from 2015。
您可能会问,为什么它适用于课堂外的第一个作业?我假设在这种情况下,上下文更加本地化。因此,反对允许它的论点并不完全适用。例如,如果您更改函数内部的语句,其效果并不像更改类的布局那样全局。
同样,这是一种权衡。但是在这两种情况下强制类型都会极大地改变体验。虽然在类的上下文中效果相当小,但强制任何赋值的显式类型会将“类 Ruby”Crystal 语言变成传统的类型化语言,其中每个赋值都需要显式类型化。
【讨论】: