Ruby 分配一个变量或在 nil 时引发错误
Posted
技术标签:
【中文标题】Ruby 分配一个变量或在 nil 时引发错误【英文标题】:Ruby assign a variable or raise error if nil 【发布时间】:2021-05-25 07:28:11 【问题描述】:在 kotlin 和 C# 中,您可以分配一个变量,否则如果值为 nil,您可以使用 ?:
和 ??
运算符引发异常。
例如,在 C# 中:
var targetUrl = GetA() ?? throw new Exception("Missing A");
// alt
var targetUrl = GetA() ?? GetB() ?? throw new Exception("Missing A or B");
这在红宝石中可能吗?如果有,怎么做?
基本上,我想做的就是这个
target_url = @maybe_a || @maybe_b || raise "either a or b must be assigned"
我知道我可以做到这一点
target_url = @maybe_a || @maybe_b
raise "either a or b must be assigned" unless target_url
但如果可能的话,我想在一行中完成
【问题讨论】:
【参考方案1】:基本上,我想做的就是这个
target_url = @maybe_a || @maybe_b || raise "either a or b must be assigned"
您必须在raise
中添加括号才能使您的代码正常工作:
x = a || b || raise("either a or b must be assigned")
使用控制流运算符or
而不是||
会“更正确”:(这使得括号是可选的)
x = a || b or raise "either a or b must be assigned"
这是 Perl 的 “做这个或死” 的成语,我认为它是干净整洁的。它强调了raise
没有为x
提供结果这一事实——它只是因为它的副作用而被调用。
但是,有些人认为 or
/ and
令人困惑,根本不应该使用。 (见rubystyle.guide/#no-and-or-or)
Rails 大量使用的模式是有两种方法,一种没有!
,它不提供错误处理:
def a_or_b
@maybe_a || @maybe_b
end
还有一个带有!
的:
def a_or_b!
a_or_b || raise("either a or b must be assigned")
end
然后通过以下方式调用它:
target_url = a_or_b!
【讨论】:
谢谢!我没有意识到它就像在raise
的参数周围需要括号一样简单。非常感谢【参考方案2】:
使用运算符优先级
另一种通过极少的代码更改来完成您想要的操作的方法是使用lower-precedence or
运算符,它的优先级低于||
和=
。例如:
# This is closest to what you want, but violates many style guides.
target_url = @maybe_a || @maybe_b or raise "either a or b must be assigned"
您也可以在不改变其工作方式的情况下换行逻辑行,例如:
# Same code as above, but wrapped for line length
# and to clarify & separate its expressions.
target_url = @maybe_a || @maybe_b or
raise "either a or b must be assigned"
无论哪种方式,代码都会按预期引发 RuntimeError 异常。由于优先规则,不需要括号。
请注意,许多style guides like this one 会告诉您完全避免使用or
运算符,或者仅将其用于流控制,因为它通常是导致难以发现的细微优先级错误的原因一眼。话虽如此,包装后的版本实际上只是 my other answer 的反转变体,并且在不使用括号的情况下很容易在视觉上区分,尤其是在启用语法突出显示的情况下。您的里程和风格指南的严格程度肯定会有所不同。
【讨论】:
【参考方案3】:在赋值表达式中使用后缀条件
因为 Ruby 中的大多数内容都计算为一个表达式,所以您可以通过使用 unless
作为后缀条件后跟赋值表达式来将其作为单个逻辑行来执行。我选择将线换行以适应合理的线长,但如果您真的想要“单线”,请随意将其设为单线。例如:
raise "either a or b must be assigned" unless
target_url = @maybe_a || @maybe_b
这将正确地引发 RuntimeError,正如您所期望的那样。
自动激活
请注意,这种特殊方法将自动激活 @maybe_a 并为其分配 nil
。如果 @maybe_a 评估为假,它也会对 @maybe_b 执行相同的操作。虽然很方便,但如果您依赖 defined? 来识别代码中其他地方的未定义变量,那么自动激活可能会在以后绊倒您。因此,这个习语的优缺点取决于你更广泛的意图,但它肯定会在原始问题的范围内完成工作。
【讨论】:
【参考方案4】:你可以用括号来解决它:
(target_url = @maybe_a || @maybe_b) || raise("either a or b must be assigned")
【讨论】:
以上是关于Ruby 分配一个变量或在 nil 时引发错误的主要内容,如果未能解决你的问题,请参考以下文章
Error-ASP.NET:由于未能找到 id 为“FileUpload1$gvFiles$ctl02$lnkBtnRemoveFile”的控件或在回发后将同一 ID 分配给另一个控件,导致发生错误。