你会如何用 Sorbet 做玫瑰记忆?

mik*_*ker 4 ruby sorbet

尝试注释此代码时,rose memoization ( @||=) 给了我一个错误Use of undeclared variable @git_sha

# typed: strict
# frozen_string_literal: true

module Util
  extend T::Sig

  sig { returns(String) }
  def self.git_sha
    @git_sha ||= ENV.fetch(
      'GIT_REV',
      `git rev-parse --verify HEAD 2>&1`
    ).chomp
  end
end
Run Code Online (Sandbox Code Playgroud)

据我发现,我应该声明变量的类型,T.let但还没有弄清楚具体如何。

jez*_*jez 5

从 0.4.4679 开始,Sorbet 现在已经内置了对此的支持。在此之前,还有其他解决方法(见下文)。

  1. 将实例变量初始化为T.nilable,并用该方法替换其他地方对实例变量的所有直接访问:
# typed: strict
# frozen_string_literal: true

module Util
  extend T::Sig

  sig { returns(String) }
  def self.git_sha
    @git_sha = T.let(@git_sha, T.nilable(String))
    @git_sha ||= ENV.fetch(
      'GIT_REV',
      `git rev-parse --verify HEAD 2>&1`
    ).chomp
  end
end
Run Code Online (Sandbox Code Playgroud)

? 在 sorbet.run 上查看

这是首选的解决方案。

  1. 在方法之外初始化实例变量,并给它一个类型注解:
# typed: strict
# frozen_string_literal: true

module Util
  extend T::Sig

  @git_sha = T.let(nil, T.nilable(String))

  sig { returns(String) }
  def self.git_sha
    @git_sha ||= ENV.fetch(
      'GIT_REV',
      `git rev-parse --verify HEAD 2>&1`
    ).chomp
  end
end
Run Code Online (Sandbox Code Playgroud)

? 在 sorbet.run 上查看

从概念上讲,这个类有两个执行阶段:初始化时和使用时。如果一个实例变量在 Sorbet 中初始化时没有被赋予类型注解,它将T.untyped无处不在(或在 中出现错误# typed: strict)。因为如果它没有在初始化中注释,Sorbet 就无法知道哪个代码路径可能首先写入这个位置。(即使在这种情况下只有一个位置,Sorbet 也不会进行那种全局分析。)

Sorbet 仅在实例变量为 nilable 时才放宽这一点,在这种情况下,它可以在任何地方初始化,因为 Sorbet 不需要保证它被初始化为非 nil。

  1. 使用不同的严格级别

有关严格级别的文档

如果您发现添加类型注释太麻烦,您可以通过 using 选择不要求类型注释# typed: true,其中需要对实例变量进行类型注释的错误被消除。