我正在尝试使用安全导航操作符&
来选择性地调用可能是散列或[]
的变量的nil
方法。据我所知,这就是安全导航操作员的用途。
my_hash = nil
puts "hello, #{ my_hash&[:test] }"
my_hash = { test: "world" }
puts "hello, #{ my_hash&[:test] }"
我希望这能输出:
hello, false
hello, world
但是它不适用于哈希;相反,我得到:
hello, false
undefined method `&` for `{:test=>"world"}:Hash` (NoMethodError)
我做错了什么?
答案 0 :(得分:4)
因为这个
my_hash[:test]
是这个的语法糖
my_hash.[](:test)
所以这应该有用
my_hash&.[](:test)
但是它并不漂亮,我知道。
答案 1 :(得分:1)
我正在尝试使用
&
来选择在哈希上调用[]
方法,该方法可能是nil
,也可能不是。{/ p>
为此,您需要直接调用[]
方法。 hash[:key]
实际上是在哈希上调用:[]
方法:
# This will not work:
my_hash&[:test]
# This will:
my_hash&.[](:test)
这显然不是最漂亮的解决方案,但是......您可能希望在方法(return if my_hash.nil?
)中使用保护子句,或者执行以下操作:
my_hash.to_h[:test]
答案 2 :(得分:0)
您的问题是没有“安全导航操作员&
”这样的东西。
所谓的安全导航操作符是&.
。你的代码中没有任何地方:
my_hash&[:test]
是否有安全导航操作员&.
。
答案 3 :(得分:-3)
您的程序中存在逻辑和语法错误,包括:
""
)插值返回的内容。&.
)时的语法错误。在下面的部分中,我解决了您的逻辑错误,并提供了一些使用本机Hash方法的建议,这些方法可以实现您所寻找的结果,而不会无声地吞噬错误,这些错误会更多地关注代码中有问题的部分。
这个答案的目标不仅仅是指出错误,还要展示如何成功完成你想要做的事情。您的里程可能会有所不同。
原始问题中存在一些关键逻辑错误。如果您希望在Hash值不存在时返回“false”进行插值,请使用#fetch。例如:
hash = {}
hash.fetch :test, false
#=> false
然而,有一个重要的警告。 如果在nil上调用,Hash #fetch将引发NoMethodError,因为nil不响应fetch:
nil.respond_to? :fetch
#=> false
此是问题安全导航旨在处理:缺少方法。因此,如果您吞下异常而不是通过#method_missing来拯救它或处理它,那么使用安全导航是有意义的。例如:
hash = nil
hash.fetch :test, false
#=> NoMethodError: undefined method `fetch' for nil:NilClass
hash&.fetch :test, false
#=> nil
但是,这样做基本上会导致以hash.fetch :test rescue false
的方式静默地吞下错误,所以这通常是错误的,因为它隐藏了一个逻辑问题或者你已经得到的事实看到一个意想不到的对象,比如nil,而不是空的哈希。但是,它肯定会解决您的插值问题:
hash = nil
"#{hash.fetch :test rescue false}"
#=> "false"
对于你发布的代码,我强调你可能想要使用合理的Hash方法不默默地吞下异常,但你的真实世界里程肯定会有所不同。
您的原始问题中似乎至少有其他四个相关问题:
&.
,因此它仅适用于使用虚线表示法的方法。 my_hash&[:test]
不是有效的构造。Hash&.[]
是一个有效的构造(它没有),这也不会达到你所期望的那样。nil.to_s
没有按你的想法行事;它返回一个空字符串,而不是FalseClass的实例。为了证明,请考虑"#{nil}" #=> ""
。请考虑以下示例:
hash = {}
hash.fetch :test
#=> KeyError: key not found: :test
hash.fetch :test, nil
#=> nil
hash.values_at :test
#=> [nil]
在大多数情况下,默认值为nil的哈希#fetch可能是您想要的,但如果您愿意这样做,您肯定可以拯救KeyError或rescue nil
(甚至rescue false
),尽管真正意外异常的全能救援通常被认为是代码气味。