你如何在 Sorbet 中键入实例变量缓存?
how do you type instance variable caching in Sorbet?
我有这样的代码 (playground link):
# typed: strict
class A
extend T::Sig
sig { returns(T::Array[Integer]) }
def compute_expensive
[1, 2, 3]
end
sig { returns(T::Array[Integer]) }
def expensive
@expensive ||= T.let(compute_expensive, T::Array[Integer])
end
end
这无法进行类型检查,表示:
editor.rb:12: The instance variable @expensive must be declared inside initialize or declared nilable https://srb.help/5005
12 | @expensive ||= T.let(compute_expensive, Integer)
^^^^^^^^^^
我已经尝试了一些方法来解决这个问题……
- 当我将类型声明为
T.nilable(Integer)
时,Sorbet 说 return 类型与 sig 不匹配。公平。
- 当我在
initialize
中将类型声明为 @expensive = nil
时,Sorbet 说 nil
不使用下面的 Integer
定义进行类型检查。也公平。
- 如果我在
initialize
中声明 @expensive = []
,我对 ||=
的分配将无法访问。
- 我当然可以说
@expensive = compute_expensive if @expensive.empty?
然后 return @expensive
但我更感兴趣的是 Sorbet 的类型系统如何适应 ||=
模式。
我觉得这在 Ruby 中很常见!我怎样才能让 Sorbet 为我进行类型检查?
A Playground Link 马上回给你。
所以,真正使用初始化是这里的重要部分。
sig { void }
def initialize
@expensive = T.let(nil, T.nilable(T::Array[Integer]))
end
因为在实际调用之前记忆仍然为零,所以你必须允许它为零,以及 T::Array[Integer]
,然后你需要将它添加到初始化中以进行class 声音。
我有这样的代码 (playground link):
# typed: strict
class A
extend T::Sig
sig { returns(T::Array[Integer]) }
def compute_expensive
[1, 2, 3]
end
sig { returns(T::Array[Integer]) }
def expensive
@expensive ||= T.let(compute_expensive, T::Array[Integer])
end
end
这无法进行类型检查,表示:
editor.rb:12: The instance variable @expensive must be declared inside initialize or declared nilable https://srb.help/5005
12 | @expensive ||= T.let(compute_expensive, Integer)
^^^^^^^^^^
我已经尝试了一些方法来解决这个问题……
- 当我将类型声明为
T.nilable(Integer)
时,Sorbet 说 return 类型与 sig 不匹配。公平。 - 当我在
initialize
中将类型声明为@expensive = nil
时,Sorbet 说nil
不使用下面的Integer
定义进行类型检查。也公平。 - 如果我在
initialize
中声明@expensive = []
,我对||=
的分配将无法访问。 - 我当然可以说
@expensive = compute_expensive if @expensive.empty?
然后 return@expensive
但我更感兴趣的是 Sorbet 的类型系统如何适应||=
模式。
我觉得这在 Ruby 中很常见!我怎样才能让 Sorbet 为我进行类型检查?
A Playground Link 马上回给你。
所以,真正使用初始化是这里的重要部分。
sig { void }
def initialize
@expensive = T.let(nil, T.nilable(T::Array[Integer]))
end
因为在实际调用之前记忆仍然为零,所以你必须允许它为零,以及 T::Array[Integer]
,然后你需要将它添加到初始化中以进行class 声音。