为什么 Crystal 无法推断实例变量的类型?
Why Crystal fails to infer type for instance variable?
为什么这段代码对实例变量失败?
a = 4.days # Works
class A
@a = 4.days # Fails
end
P.S.
以后有改进的计划吗?好像是很普通也很有用的东西。
从 Crystal 1.4 开始,现在支持此功能。是合法的代码。
主题 came up again recently, and now the compiler is smart enough to detect most of the simple cases (thanks to Asterite's changes in 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,我之前的回答现在大部分已经过时了。由于历史原因,我将其保留;它的部分内容仍然相关,但像原始问题中的简单案例现在是合法的 Crystal。只有在旧版本中(直到 1.3.2),它才会无法推断 4.days
或 1 + 1
.
@a = 4
会工作,因为 4
是 literal, but 4.days
is an expression and thus cannot be automatically deduced. For the same reason @a = 1 + 1
,即使 @a = 2
不会。
关于未来的计划,有趣的是该功能存在,但被有意删除。
总之,就是为了让编译步骤简单。自动归纳类型很优雅,但也有缺点:
- 编译速度较慢
- 为错误类型的程序生成良好的错误消息变得困难
- 重用以前的编译结果变得困难(或不可能?)
原因是,通常,您必须分析贯穿整个源代码的函数调用链。请注意,并非所有表达式都像 1 + 1
这样简单。即使 4.days
已经有些复杂,因为编译器需要推断 days
方法调用的 return 类型。
如果您想了解有关设计决策的更多信息,我建议您阅读 discussion from 2015。
您可能会问,为什么它对 class 之外的第一个作业有效?我假设在那种情况下,上下文更本地化。因此,反对允许它的论点并不完全适用。例如,如果您更改函数内的语句,其效果不如更改 class.
的布局那样全局。
同样,这是一个权衡。但是在这两种情况下强制使用类型都会极大地改变体验。虽然在 class 的上下文中效果相当小,但对任何赋值强制显式类型会将“Ruby-like”Crystal 语言变成传统的类型化语言,其中每个赋值需要明确输入。
为什么这段代码对实例变量失败?
a = 4.days # Works
class A
@a = 4.days # Fails
end
P.S.
以后有改进的计划吗?好像是很普通也很有用的东西。
从 Crystal 1.4 开始,现在支持此功能。是合法的代码。
主题 came up again recently, and now the compiler is smart enough to detect most of the simple cases (thanks to Asterite's changes in 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,我之前的回答现在大部分已经过时了。由于历史原因,我将其保留;它的部分内容仍然相关,但像原始问题中的简单案例现在是合法的 Crystal。只有在旧版本中(直到 1.3.2),它才会无法推断 4.days
或 1 + 1
.
@a = 4
会工作,因为 4
是 literal, but 4.days
is an expression and thus cannot be automatically deduced. For the same reason @a = 1 + 1
@a = 2
不会。
关于未来的计划,有趣的是该功能存在,但被有意删除。
总之,就是为了让编译步骤简单。自动归纳类型很优雅,但也有缺点:
- 编译速度较慢
- 为错误类型的程序生成良好的错误消息变得困难
- 重用以前的编译结果变得困难(或不可能?)
原因是,通常,您必须分析贯穿整个源代码的函数调用链。请注意,并非所有表达式都像 1 + 1
这样简单。即使 4.days
已经有些复杂,因为编译器需要推断 days
方法调用的 return 类型。
如果您想了解有关设计决策的更多信息,我建议您阅读 discussion from 2015。
您可能会问,为什么它对 class 之外的第一个作业有效?我假设在那种情况下,上下文更本地化。因此,反对允许它的论点并不完全适用。例如,如果您更改函数内的语句,其效果不如更改 class.
的布局那样全局。同样,这是一个权衡。但是在这两种情况下强制使用类型都会极大地改变体验。虽然在 class 的上下文中效果相当小,但对任何赋值强制显式类型会将“Ruby-like”Crystal 语言变成传统的类型化语言,其中每个赋值需要明确输入。