红宝石:"create and increment"成语



我正在寻找一种简洁的方法来处理以下情况:给定一个变量(在实践中,类中的一个实例变量,尽管我认为这在这里并不重要(,已知它要么nil,要么保持一些Integer。如果是整数,则应递增变量。如果为 nil,则应使用1初始化。

这些是显而易见的解决方案,将@counter作为要处理的变量:

# Separate the cases into two statements
@counter ||= 0
@counter += 1

# Separate the cases into one conditional
@counter = @counter ? (@counter + 1) : 1

我不喜欢这些解决方案,因为它们需要重复变量的名称。以下尝试失败:

# Does not work
(@counter ||= 0) += 1

这无法完成,因为赋值运算符的结果不是左值,尽管实际的错误消息有点模糊。在这种情况下,您会_unexpected tOP_ASGN收到错误,期望end_。

是否有一个好的成语来编码我的问题,或者我必须坚持使用我笨拙的解决方案之一?

问题很清楚:

  • 已知变量包含nil或整数。如果nil变量要设置为等于1,否则将设置为等于其值加1
  • 在 Ruby 中实现这一点的最佳方法是什么?

第一,两点。

  • 问题指出,"如果它是零,它应该用1初始化。这与已知变量是nil或整数的说法相矛盾,这意味着它已经被初始化,或者更准确地说,已经定义。对于实例变量,这种区别是无关紧要的,因为 Ruby 初始化未定义的实例变量,以便在它们作为右值引用时nil。但是,对于局部变量来说,这是一个重要的区别,因为当未定义的局部变量作为右值引用时,会引发异常。
  • 注释主要解决变量包含nilinteger以外的对象的情况。因此,它们无关紧要。如果OP希望扩大问题范围以允许变量保存nil或整数(例如数组或哈希(以外的对象,则应提出一个单独的问题。

在决定哪种代码最好时应使用什么标准?在提到的各种可能性中,我没有看到效率的重要差异。假设是这种情况,或者相对效率在应用程序中并不重要,我们只剩下可读性(以及扩展的可维护性(作为唯一的标准。如果x等于nil或整数,或者是一个未定义的实例变量,也许最清晰的代码如下:

x = 0 if x.nil?
x += 1

x = x.nil? ? 1 : x+1

可读性略低:

x = (x || 0) + 1

落后一步:

x = x.to_i + 1

这需要读者知道nil.to_i #=> 0.

OP可能会认为这些解决方案"笨拙",但我认为它们都很漂亮。

是否可以编写引用x一次的表达式?我想不出一种方法,评论中也没有建议,所以如果有一种方法(我相信是可疑的(,它可能无法满足可读性的测试。

现在考虑局部变量x可能尚未定义的情况。在这种情况下,我们可以这样写:

x = (defined?(x) ? (x || 0) : 0) + 1

定义?是一个 Ruby 关键字。

最新更新