Подтвердить что ты не робот

Следующий в сравнении с if в цикле .each?

У меня есть текстовая обработка, которую я делаю в 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
}

Есть ли правильный путь или это просто предпочтение? Какой из них больше сочетается с "рубиновым способом"? "

4b9b3361

Ответ 1

Полностью согласен с @DigitalRoss, и я видел людей, использующих next, если есть сложная часть кода после того, как какое-либо условие оценивается i.e.

 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 в вашем коде.

Ответ 2

Я думаю, что пример, который вы дали, на самом деле не фиксирует ситуацию, когда выполнение next имеет значение. Рассмотрим ситуацию, когда в вашем коде несколько "следующих точек":

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

и сравните его с if-вариантом:

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

Хотя первый может быть рассмотрен некоторыми пуристами в стиле спагетти, ИМХО он более читабельен, чем последний.

Ответ 3

Сделайте это вторым способом

Некоторые школы мысли выступают против вещей на разных языках, таких как next, retry, continue и break, потому что они немного слишком сильно направлены в сторону неутешительного goto утверждение.

У этих утверждений есть свои варианты использования, но в целом это плохая идея сознательно "расстегнуть" код, когда структурированная конструкция, направленная вниз, выполнит одно и то же. Теперь, если условие вызвало пропущение всего тела цикла, в этом случае я мог бы предпочесть использование next.

Ответ 4

я хотел бы:

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 строк кода, иначе я скорее сделаю другой, поэтому отступы помогут мне понять на первый взгляд, что происходит