问题描述
Crystal 不能/不会解决这种类型的原因是什么? (我看到文档没有提到编译器可以推断实例方法调用,但它背后的原理是什么,尤其是当只涉及 stdlib 函数时?编译时间?)
class Something
def blah
@result = 1 + 1
end
end
Something.new().blah
编译器错误:
Showing last frame. Use --error-trace for full trace.
error in line 3
Error: can't infer the type of instance variable '@result' of SomeObject
The type of a instance variable,if not declared explicitly with
`@result : Type`,is inferred from assignments to it across
the whole program.
The assignments must look like this:
1. `@result = 1` (or other literals),inferred to the literal's type
2. `@result = Type.new`,type is inferred to be Type
3. `@result = Type.method`,where `method` has a return type
annotation,type is inferred from it
4. `@result = arg`,with 'arg' being a method argument with a
type restriction 'Type',type is inferred to be Type
5. `@result = arg`,with 'arg' being a method argument with a
default value,type is inferred using rules 1,2 and 3 from it
6. `@result = uninitialized Type`,type is inferred to be Type
7. `@result = LibSome.func`,and `LibSome` is a `lib`,type
is inferred from that fun.
8. `LibSome.func(out @result)`,type
is inferred from that fun argument.
Other assignments have no effect on its type.
can't infer the type of instance variable '@result' of SomeObject
解决方法
如果我没记错的话,Crystal 过去在推断类型时更加激进。虽然它在某些示例中很优雅,但它在更大的项目中会产生更多问题。编译时间成为一个问题(增量编译很难或不可能),并且当一切传播时,代码中的错误(例如,由于错字)可能更难追踪。
最后,保持干扰规则更简单并回退到表达式的显式类型被认为更实用。这是 2015 年的 https://app.vagrantup.com/boxes/search。我没有参与语言设计,但是通过阅读线程,我认为线程中的参数适用于您的问题(为什么需要显式键入 1 + 1
)。请注意,1 + 1
是一个简单的情况,但是一旦您允许,表达式就会变得更加复杂。一般来说,编译器必须通过整个程序代码来进行分析。