接下来与if。在一个.each循环中?

时间:2010-02-17 04:22:41

标签: ruby coding-style

我正在使用Ruby进行文本处理。基本上,我必须实现一个简单的状态机(一个字符后视)。

我的代码目前看起来像这样:

text.each{ |c|
  ...
  ...
  ...
  ...
  if @state!=:some_state
    next
  end
  #processing stuff for if in :some_state mode
  ...
  ...
  ...
  ...
  ...
}

这是正确的吗?或者它应该像下面这样实现:

text.each{ |c|
  ...
  ...
  ...
  ...
  if @state==:some_state
    #processing stuff for if in :some_state mode
    ...
    ...
    ...
    ...
    ...
  end
}

有正确的方式还是只是偏好?哪一个与做事的“红宝石方式”更加融合?

4 个答案:

答案 0 :(得分:21)

完全赞同@DigitalRoss,如果在评估某些条件后存在复杂的代码,我看到有人使用next,即

 next if @state!=:some_state
 # some long complicated code

另一方面如果有一个简单的操作需要在某些条件的基础上执行那么我宁愿

 if @state == :some_state
   #call_a_method_to_do_something
 end

 OR

 call_a_method if @state == :some_state

话虽如此,编写冗长复杂代码的不良做法。如果您的代码干净且设计良好,那么您就不必在代码中使用next

答案 1 :(得分:5)

我认为你给出的例子并没有真正捕捉到next有所作为的情况。考虑一下代码中有多个“next-points”的情况:

text.each do |c|
  next if @state == :state1
  ...
  next if @state == :state2
  ...
  next if @state == :state3
  ...
end

并将其与if-variant进行比较:

text.each do |c|
  unless @state == :state1
    ...
    unless @state == :state2
      ...
      unless @state == :state3
        ...
      end
    end
  end
end

虽然第一种可以被一些纯粹主义者视为意大利面风格,但恕我直言,它比后者更具可读性。

答案 2 :(得分:3)

第二种方式

有些学派反对使用各种语言的内容,例如nextretrycontinuebreak,因为它们只是有点太多了不受尊重的goto陈述的方向。

这些语句确实有它们的用例,但总的来说,当一个结构化的向下指向的结构将完成相同的事情时故意“spaghettify”代码是一个坏主意。现在,如果条件要求跳过整个循环体,那么我可能更喜欢使用next

答案 3 :(得分:1)

我会选择:

text.each{ |c|
  ...
  ... Generic state processing
  ...
  case @state
    when :state_1 then code
    when :state_2 then code
  end
}

但如果它与第一个样本一样(意味着只有一个状态需要额外处理)

text.each{ |c|
  ...
  ... Generic state processing
  ...
  next unless @state == :state_1
  ...
  ... Code that process states other than :state_1
}

更进一步而不是点击实例变量,如果对象是否处于我们需要的状态,它听起来会更好:

def processed?
  @state == :state_1
end

...
next unless processed? # sounds like natural language...
...

进一步推理,我认为除了处理之外,还有一个像'下一个'的衬里?只有在同一缩进级别中不超过10行代码才有用,否则我宁愿做另一行,所以缩进会帮助我乍看之下发生了什么