【问题标题】:how do you type instance variable caching in Sorbet?如何在 Sorbet 中键入实例变量缓存?
【发布时间】:2020-10-07 21:17:00
【问题描述】:

我的代码看起来像这样 (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 说返回类型与信号不匹配。公平。
  • 当我将initialize 中的类型声明为@expensive = nil 时,Sorbet 说nil 不使用下面的Integer 定义进行类型检查。也很公平。
  • 如果我在initialize 中声明@expensive = [],我对||= 的分配将变得无法访问。
  • 我当然可以说@expensive = compute_expensive if @expensive.empty?,然后返回@expensive,但我更感兴趣的是Sorbet 的类型系统如何适应||= 模式。

这对我来说是 Ruby 中非常常见的模式!如何让 Sorbet 为我进行类型检查?

【问题讨论】:

标签: sorbet


【解决方案1】:

Playground Link 马上回复你。

所以,真正使用初始化是这里的重要部分。

  sig { void }
  def initialize
    @expensive = T.let(nil, T.nilable(T::Array[Integer]))
  end

因为在实际调用之前,memoization 仍然是 nil,因此您必须允许它与 T::Array[Integer] 一起为 nil,然后您需要将其添加到初始化中以使类听起来。

【讨论】:

猜你喜欢
  • 2011-04-08
  • 1970-01-01
  • 2019-01-19
  • 2021-12-01
  • 1970-01-01
  • 2017-06-05
  • 2011-10-26
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多