Ruby:if变量vs if variable.nil?


11

我是Ruby的新手,当我发现除nil和false之外的所有对象均为真时,我感到很惊讶。偶数为0。

关于该语言的属性的一件好事是,您可以编写:

if !variable
  # do stuff when variable is nil
end

我的同事是经验丰富的Ruby开发人员,他们坚持认为我应该选择该选项,而不要使用.nil?像这样:

if variable.nil?
  # do stuff when variable is nil
end

但是,我认为后者是一个更好的选择,原因有两个:1.我认为它更面向对象,尤其是在像Ruby这样的语言中,一切都是对象和消息交换。2.我认为,即使它不那么紧凑,它也更具可读性。

我在这里犯“新手”错误吗?


4
您要测试零吗?还是假值?

我正在测试零。基本上,如果变量为nil,我会做(或不做)
Javier Holguera

3
如果要测试nil,为什么还要对false的测试也输入该代码块?

同意,我指出了另一个选择.nil的理由?但是他们坚持认为“如果变量做x”比“如果变量做x”更惯用,并且当您知道变量不是布尔值时更可取
Javier Holguera 2015年

Answers:


17

写出你的意思。意思是你写的。

让我们进行其他测试。 .vowel?

if char == 'a'
   # do stuff
end

if char.vowel?
   # do stuff
end

现在,很明显,这些功能不能完成相同的工作。但是,如果您只是期望char会成功ab那还是可以的。但这会使下一个开发人员感到困惑-在char [eiou]也存在的情况下,将进入第二个块。但是对于a,它将正常工作。

是的,是的情况下nilfalse在Ruby的唯一falsy值。但是,如果您通过测试来nil进行测试nil || false,那不是您的意思。

这意味着下一位开发人员(恰好是一个疯狂的斧头谋杀者,知道您的家庭住址)将阅读该代码,并且想知道为什么false也要去那里。

编写准确表达您的意思的代码。


3

考虑以下:

response = responses.to_a.first

这将返回的第一个元素responses,或nil。然后,因为条件语句nil就像false我们可以这样写:

response = responses.to_a.first
if response
  # do something ('happy path')
else
  # do something else
end

比以下内容更具可读性:

if response.nil?
  # do something else
else
  # do something ('happy path')
end

if (object)模式在Ruby代码中非常常见。它还可以很好地导致重构,例如:

if response = responses.to_a.first
  do_something_with(response)
else
  # response is equal to nil
end

还要记住,Ruby方法nil默认返回。所以:

def initial_response
  if @condition
    @responses.to_a.first
  else
    nil
  end
end

可以简化为:

def initial_response
  if @condition
    @responses.to_a.first
  end
end

因此,我们可以进一步重构:

if response = initial_response
  do_something_with(response)
else
  # response is equal to nil
end

现在您可以辩称,返回nil并不总是最好的主意,因为这意味着检查nil所有地方。但这是另一锅鱼。鉴于测试对象“存在或不存在”的需求如此频繁,因此对象的真实性是Ruby的一个有用方面,尽管对于使用该语言的新手来说是令人惊讶的。


2

不仅if variable.nil?读起来更像自然语言,它还扼守对程序员意外分配一个false值,落入你的if说法,因为Ruby是一种松散类型的语言。


1
那么原始问题的最初评论是错误的吗?应该是“当变量为nil或false时执行操作”?并且由于与注释不匹配的代码是一个错误,所以马上就有一个错误吗?
gnasher729

正确。一个简单的真实性测试可能会引入逻辑错误。
格雷格·伯格哈特

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.