开发者

next versus if in a .each loop?

I have a text processing thing I'm doing in Ruby. Basically, I have to implement a simple state machine (with one character look-behind).

My code at the moment looks like this:

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

Is this开发者_JAVA技巧 proper? Or should it rather be implemented like:

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

Is there a right way or is it just preference? Which one blends more with "the ruby way" of doing things?


Totally agree with @DigitalRoss and I have seen people using next if there is complicated piece of code after some condition is being evaluated i.e.

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

on the other hand if there is a simple operation that needs to be performed on the basis of some condition then I would prefer

 if @state == :some_state
   #call_a_method_to_do_something
 end

 OR

 call_a_method if @state == :some_state

Having said that, its bad practice to write long complicated code. If your code is clean and well designed then you would never have to use next within your code.


I think that the example you gave doesn't really capture situation where doing next makes a difference. Consider the situation where you have multiple "next-points" in your code:

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

and compare it with if-variant:

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

Although the first could be viewed as spaghetti-style by some purists, IMHO it is more readable than the latter.


Do it the second way

Some schools of thought are opposed to things in various languages like next, retry, continue, and break, because they are just a little bit too much in the direction of the disrespected goto statement.

Those statements do have their use cases, but in general it's a bad idea to deliberately "spaghettify" the code when a structured downward-pointing construct will accomplish the same thing. Now if the condition called for skipping the entire loop body, in that case I might prefer the use of next.


i would go for:

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

But if it's as on the first sample ( meaning just 1 state needs extra processing )

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

Going even further instead of hitting the instance variable, it sound nicer to ask the object if it's in the state we need like:

def processed?
  @state == :state_1
end

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

Reasoning a little bit further, I think one liners like 'next unless processed?' are good only when there are no more than 10 lines of code in the same indentation level, otherwise i rather do the other, so indentation will help me understand at first glance what's happening

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜