gpt4 book ai didi

crystal-lang - Crystal : Ensure return value is not Nil

转载 作者:行者123 更新时间:2023-12-04 04:57:27 30 4
gpt4 key购买 nike

我有一个定义如下的辅助类:

require "toml"

module Test
class Utils
@@config

def self.config
if @@config.is_a?(Nil)
raw_config = File.read("/usr/local/test/config.toml")
@@config = TOML.parse(raw_config)
end
@@config
end
end
end

当我在代码的其他地方调用这个方法时:

server = TCPServer.new("localhost", Utils.config["port"])

我收到以下编译时错误:

in src/test/daemon.cr:10: undefined method '[]' for Nil (compile-time type is (Hash(String, TOML::Type) | Nil))

server = TCPServer.new("localhost", Utils.config["port"])

Utils.config 无法运行 Nil 的东西,所以我不明白这个错误。

  1. 我如何告诉编译器 Utils.config 将始终返回不是 Nil 的内容?
  2. (次要附加问题)对于将在类之间共享但只应创建一次的资源(config),这是一个好的设计模式吗?

最佳答案

您的代码的问题在于,在 if 分支中检查 @config 是否为 nil(顺便说一句,使用 @config.nil 更容易?)时,该实例变量的值可能已经更改,直到它到达返回行。例如,如果它是从不同的光纤更改的,编译器必须假设它可以再次为 nil。

你可以将它保存到一个局部变量中并返回它

class Utils
@@config

def self.config
if (config = @@config).nil?
raw_config = File.read("/usr/local/test/config.toml")
@@config = TOML.parse(raw_config)
else
config
end
end
end

或者稍微重构但本质上是一样的:

class Utils
@@config

def self.config
@@config ||= begin
raw_config = File.read("/usr/local/test/config.toml")
TOML.parse(raw_config)
end
end
end

我更喜欢将 @@config 设置为 nil 而不是使用空对象进行默认初始化,因为它清楚地表明该对象不可用。例如,如果配置文件恰好为空,则检查 empty? 将始终触发重新加载和解析,从而消除内存功能。

||= 运算符基本上意味着

if config = @@config
config
else
@@config = # ...
end

关于crystal-lang - Crystal : Ensure return value is not Nil,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/47066810/

30 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com